Discussion:
removing dynamically added nodes (from the update thread)
Jorg Heymans
2004-07-29 14:12:19 UTC
Permalink
Hi,


I am able to add stuff to the DOM in the update thread
(getUpdateManager().getUpdateRunnableQueue().invokeLater() )

Why is a simple removal then not working like i expect it to work?
I locate the node to remove using document.getElementById , making sure
with getLocalName() and getAttributes() that this is actually the node i
want to remove.

Then in the update thread i am doing
removenode.getParent().removeChild(removenode) which results in
stacktrace ("g" being the element i want to remove)

org.w3c.dom.DOMException: The child node (type: 1, name: g) is missing.
at org.apache.batik.dom.AbstractNode.createDOMException(Unknown Source)
at org.apache.batik.dom.AbstractParentNode$ChildNodes.remove(Unknown Source)
at org.apache.batik.dom.AbstractParentNode.removeChild(Unknown Source)
at com.terrasel.osgis.batikapplet.SVGApplet$2.run(SVGApplet.java:187)
at org.apache.batik.util.RunnableQueue.run(Unknown Source)
at java.lang.Thread.run(Thread.java:534)

The element i want to remove is the one i just dynamically added. I
think i am operating on a recent document instance because i can
actually *find* the element.

Removing static elements always works, so where am I missing the sync on
the document instance?


Any hints?


Regards
Jorg
Thomas DeWeese
2004-07-31 00:34:04 UTC
Permalink
Hi Jorg,

I have no idea why you are getting this error. I have
never seen it. My initial suspicion is that you are removing
the same element from two different threads. I would be
curious to know what getPreviousSibling() and getNextSibling()
return right before calling removeChild.

I would also be interested in knowing how you add the
elements to the DOM.

Is this error totally reproducable? can you produce a
reproducable standalone test case?
Post by Jorg Heymans
Hi,
I am able to add stuff to the DOM in the update thread
(getUpdateManager().getUpdateRunnableQueue().invokeLater() )
Why is a simple removal then not working like i expect it to work?
I locate the node to remove using document.getElementById , making sure
with getLocalName() and getAttributes() that this is actually the node i
want to remove.
Then in the update thread i am doing
removenode.getParent().removeChild(removenode) which results in
stacktrace ("g" being the element i want to remove)
org.w3c.dom.DOMException: The child node (type: 1, name: g) is missing.
at org.apache.batik.dom.AbstractNode.createDOMException(Unknown Source)
at org.apache.batik.dom.AbstractParentNode$ChildNodes.remove(Unknown Source)
at org.apache.batik.dom.AbstractParentNode.removeChild(Unknown Source)
at com.terrasel.osgis.batikapplet.SVGApplet$2.run(SVGApplet.java:187)
at org.apache.batik.util.RunnableQueue.run(Unknown Source)
at java.lang.Thread.run(Thread.java:534)
The element i want to remove is the one i just dynamically added. I
think i am operating on a recent document instance because i can
actually *find* the element.
Removing static elements always works, so where am I missing the sync on
the document instance?
Any hints?
Regards
Jorg
---------------------------------------------------------------------
Jorg Heymans
2004-08-04 08:00:45 UTC
Permalink
Hi Thomas,

Apologies for the late reply, here is a bit more info.

1) the code is running in an applet

2) I have a monitor class implementing all 4 listener classes
(Updatemanager, svgdocumentloader,gvttreebuilder,gvttreerenderer)

3) I have a class extending the svgloadeventdispatcher, and in
svgloadeventdispatchstarted() i assign the document instance
this.document=canvas.getSVGDocument()

4) in init() of the applet i have
canvas.setDocumentState(JSVGCanvas.ALWAYS_DYNAMIC);
canvas.addSVGLoadEventDispatcherListener(new SVGLoadMonitor());
canvas.addSVGDocumentLoaderListener(monitor);
canvas.addGVTTreeBuilderListener(monitor);
canvas.addGVTTreeRendererListener(monitor);
canvas.addUpdateManagerListener(monitor);
canvas.setURI(getClass().getClassLoader().getResource("base.svg")
.toExternalForm());

5) i am adding and removing DOM elements via checkboxes, so in
itemStateChanged(ItemEvent e) i do

.....
//ADDING elements (works)
String parser = XMLResourceDescriptor.getXMLParserClassName();
SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
final SVGDocument doc = (SVGDocument) f.createDocument(uri);
final Node documentNode = document.importNode(doc
.getElementsByTagName("g").item(0), true);
//find the node we need to append to
String xpath = "//*[@id='" + feature + "']";
final NodeList nodeList = org.apache.xpath.XPathAPI
.selectNodeList(document, xpath);

canvas.getUpdateManager().getUpdateRunnableQueue().invokeLater(
new Runnable() {
public void run() {
document.getDocumentElement().replaceChild(
documentNode, nodeList.item(0));
}
});
......
//REMOVING ELEMENTS (does not work)
final Element remove = document.getElementById("wta");
canvas.getUpdateManager().getUpdateRunnableQueue().invokeLater(
new Runnable() {
public void run() {
//EXCEPTION OCCURS HERE
remove.getParentNode().removeChild(remove);
}
});

6) The calls to getPreviousSibling() and getNextSibling() on the node i
want to remove :
getNodeName() -> "#text"
getNodeValue() -> a few blanks and newlines, seems correct
getNodeType() -> 3

7) Adding and removing happens in thread "RunnableQueue-0" according to
log4j. All other operations in thread "AWT-EventQueue-1".

Hope i haven't flooded you with too much info, if you need more info
just shout.

Regards
Jorg
Post by Thomas DeWeese
Hi Jorg,
I have no idea why you are getting this error. I have
never seen it. My initial suspicion is that you are removing
the same element from two different threads. I would be
curious to know what getPreviousSibling() and getNextSibling()
return right before calling removeChild.
I would also be interested in knowing how you add the
elements to the DOM.
Is this error totally reproducable? can you produce a
reproducable standalone test case?
Post by Jorg Heymans
Hi,
I am able to add stuff to the DOM in the update thread
(getUpdateManager().getUpdateRunnableQueue().invokeLater() )
Why is a simple removal then not working like i expect it to work?
I locate the node to remove using document.getElementById , making
sure with getLocalName() and getAttributes() that this is actually the
node i want to remove.
Then in the update thread i am doing
removenode.getParent().removeChild(removenode) which results in
stacktrace ("g" being the element i want to remove)
org.w3c.dom.DOMException: The child node (type: 1, name: g) is missing.
at org.apache.batik.dom.AbstractNode.createDOMException(Unknown Source)
at org.apache.batik.dom.AbstractParentNode$ChildNodes.remove(Unknown Source)
at org.apache.batik.dom.AbstractParentNode.removeChild(Unknown Source)
at com.terrasel.osgis.batikapplet.SVGApplet$2.run(SVGApplet.java:187)
at org.apache.batik.util.RunnableQueue.run(Unknown Source)
at java.lang.Thread.run(Thread.java:534)
The element i want to remove is the one i just dynamically added. I
think i am operating on a recent document instance because i can
actually *find* the element.
Removing static elements always works, so where am I missing the sync
on the document instance?
Any hints?
Regards
Jorg
---------------------------------------------------------------------
Thomas DeWeese
2004-08-04 10:08:29 UTC
Permalink
Hi Jorg,

I believe this is caused by a bug in your code.
However it is probably a bug that we should have caught
Post by Jorg Heymans
document.getDocumentElement().replaceChild(
documentNode, nodeList.item(0));
I am reasonably sure that the Document Element is not the
parent of nodeList.item(0). In which case the above call will
slightly corrupt our DOM. I've added additional checks so an
error will be raised in this condition in the future.

You probably want:

Element elt = (Element)nodeList.item(0);
elt.getParentNode().replaceChild(documentNode, elt);

Also why are you dragging in XPath just to do getElementById?
Post by Jorg Heymans
final NodeList nodeList = org.apache.xpath.XPathAPI
.selectNodeList(document, xpath);
Jorg Heymans
2004-08-04 11:49:27 UTC
Permalink
Thomas DeWeese wrote:

<snip/>
Post by Thomas DeWeese
I am reasonably sure that the Document Element is not the
parent of nodeList.item(0). In which case the above call will
slightly corrupt our DOM. I've added additional checks so an
error will be raised in this condition in the future.
okay.
Post by Thomas DeWeese
Element elt = (Element)nodeList.item(0);
elt.getParentNode().replaceChild(documentNode, elt);
Works fine now, thanks !
Post by Thomas DeWeese
Also why are you dragging in XPath just to do getElementById?
Post by Jorg Heymans
final NodeList nodeList = org.apache.xpath.XPathAPI
.selectNodeList(document, xpath);
I know, leftover from more complicated node searches :)


Thanks again
Jorg Heymans
Carsten Birn
2004-08-04 15:57:40 UTC
Permalink
Hi

Are mails with attachments not allowed on the Mailinglist...?
Or is there somekind of response time?

:-)

Carsten

Loading...