I have a piece of JAXB unmarshalling code that looks like this:
Foo foo = null;
try {
logger.debug(methodNamePrefix + "xmlString is \n" + xmlString);
JAXBContext jaxbContext = JAXBContext
.newInstance(Foo.class);
Unmarshaller u = jaxbContext.createUnmarshaller();
u.setEventHandler(new DefaultValidationEventHandler());
StreamSource streamsource = new StreamSource(new StringReader(xmlString));
foo = (Foo) u.unmarshal(streamsource);
sanityCheckDbpAfterUnmarshalling(xmlString, foo);
}catch(Exception e){
throw new AnalysisNotPossibleException();
}
if (foo==null){
throw new AnalysisNotPossibleException();
}
This code has been working for months, until recently, on one machine, it started failing. When it failed, it spit out a seemingly legit complaint -- except that the same piece of code, with same input xmlString, when run on another machine, or even on the very same machine but in unit test, would not complain:
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"entry"). Expected elements are (none)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:642)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:254)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:249)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:116)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.childElement(Loader.java:101)
at com.sun.xml.bind.v2.runtime.unmarshaller.StructureLoader.childElement(StructureLoader.java:243)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:478)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:459)
at com.sun.xml.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:148)
I am quite sure that this is due to some local environment of that machine, but I could not figure out what that is. I have tried cleaning all my binary in my Eclipse.
I know this needs debugging, and I do not expect a full answer. But I would appreciate any ideas for some more things that I can check. Thanks!
Updated
The class Foo looks like this:
@XmlRootElement
public class Foo implements Serializable{
private static final long serialVersionUID = -4550266352252980254L;
@XmlElement
private HashMap<String, SomeProperty> mapAllPortletProperty =
new HashMap<String, SomeProperty>();
...
And the XML string looks like this
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo>
<mapAllPortletProperty>
<entry>
<key>Portlet 6262</key>
<value>
<apIdStrAtBirth>4536</apIdStrAtBirth>
...
2nd Update
Thanks for all the help so far. That has helped me to think about these two aspects:
- Resource leak?
StreamSource
andStringReader
are holding onto some resources after they are done with unmarshalling? - Thread safety? c.f. This SO post about "JAXB creating context and marshallers cost"
For #1, I have checked that there does not appear to have resource leak. I also have a stress-test program and it does a lot of unmarshalling. I did not observe the program has ever growing memory footprint.
For #2, I have rewritten my code so that for each class that needs
to be unmarshalling, my code instantiate an JAXBContext
only once.
Unfortunately, with the above new insight, I still have not been able to find the root cause of the problem. Any more insight are welcome!