NPE calls getLength () on NodeList
I am using the org.w3c.dom.Document interface to parse the XML messages that are passed between the client and the server. Intermittently I come across NPE that I cannot explain.
The chain of events is as follows: the client sends a message to the server on a separate (not AWT) thread. The response is captured as a string converted to a Document object, at which point the root element is received:
Element root = response.getDocumentElement();
This root element is then passed to the leaderboard screen, thus:
Leaderboard leaderboard = ScreenCache.getLeaderboard();
if (!leaderboard.isVisible())
{
return;
}
leaderboard.buildTablesFromResponseLater(root);
Then I call on the AWT thread, since I am going to use the data to redraw the screen in various ways (updating tables, etc) and Swing is not thread safe. I also read somewhere that DOM stuff is not thread safe (although I can't get life to discover it again).
public void buildTablesFromResponseLater(final Element root)
{
Runnable updateRunnable = new Runnable()
{
@Override
public void run()
{
buildTablesFromResponse(root);
}
};
SwingUtilities.invokeLater(updateRunnable);
}
Inside buildTablesFromResponse, I start to parse the XML. I get various attributes from it and then I call the following code:
NodeList children = root.getElementsByTagName(TAG_ROOM_STATS);
int length = children.getLength(); <- NPE HERE
However, this creates an NPE as shown below:
10/05 23:44:14.505 java.lang.NullPointerException
at com.sun.org.apache.xerces.internal.dom.DeepNodeListImpl.nextMatchingElementAfter(Unknown Source)
at com.sun.org.apache.xerces.internal.dom.DeepNodeListImpl.item(Unknown Source)
at com.sun.org.apache.xerces.internal.dom.DeepNodeListImpl.getLength(Unknown Source)
at online.screen.g.d(Leaderboard.java:370)
at online.screen.g.c(Leaderboard.java:364)
at online.screen.g.b(Leaderboard.java:315)
at online.screen.g.a(Leaderboard.java:312)
at online.screen.g$4.run(Leaderboard.java:305)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$400(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
I can't see what I am doing wrong here. There are various other places where I parse XML like this and it works great and as I said this issue is rare even with Leaderboard. The only differences I can think of are the following:
- The listing post is likely to be "cumbersome" than the others.
- Other places will almost certainly get a NodeList / length on the same stream that opens the socket, which will be a non-AWT stream. However, I would have thought it would be more prone to problems than less!
If somehow the AWT issue is an issue then this is a quick fix to parse the XML before accessing the AWT thread to draw the screen. I'm just reluctant to do this without understanding the underlying problem.
Obviously this is a very old thread, but in case anyone else runs into this problem ... I recently ran into this problem and after some research, the only suggestion I could find is that it happens because parsing still happens when accessors are called. So I guess to briefly summarize what I found, yes, you have to completely finish parsing the XML before accessing it.
From this thread ( https://community.oracle.com/thread/2114086 ):
This is because JAXP is not thread safe. need to sync the bracket or use a flow parser.