I'm trying to unmarshall xml file, but get very strange NPE from the depths of JAXB library. Could you, please, help me to solve this problem?
Here's exception stacktrace's top:
java.lang.NullPointerException
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:258)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.handleGenericException(Loader.java:245)
at com.sun.xml.bind.v2.runtime.unmarshaller.Scope.add(Scope.java:123)
at com.sun.xml.bind.v2.runtime.property.ArrayERProperty$ReceiverImpl.receive(ArrayERProperty.java:213)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.endElement(UnmarshallingContext.java:538)
Here's xml classes code:
public class Base {
public Base() {
}
}
public class A extends Base {
public A() {
}
}
public class B extends Base{
public B() {
}
}
@XmlRootElement(name = "test")
@XmlAccessorType
public class TestXml {
@XmlElementWrapper(name = "list")
@XmlAnyElement
@XmlJavaTypeAdapter(Adapter.class)
public List<Base> list = new ArrayList<>();
}
Here's adapter's unmarshal() method, it was taken from here and was slightly modified.
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public T unmarshal(Element element) throws Exception {
if (null == element) {
return null;
}
// 1. Determine the values type from the type attribute.
Class<?> clazz = classLoader.loadClass(element.getAttribute("class"));
// 2. Unmarshal the element based on the value's type.
DOMSource source = new DOMSource(element);
Unmarshaller unmarshaller = getJAXBContext(clazz).createUnmarshaller();
JAXBElement jaxbElement = unmarshaller.unmarshal(source, clazz);
return (T) jaxbElement.getValue();
}
Here's test code:
JAXBContext jaxbContext = JAXBContext.newInstance(TestXml.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
TestXml auth = (TestXml) unmarshaller.unmarshal(new File("testData/test.xml"));
And finally, here's xml file, which I try to unmarshall:
<test>
<list>
<item class="my.package.A" />
<item class="my.package.B" />
</list>
</test>
While debugging I found out that adapter works well, i.e. unmarshall() method always returns instance of right class, but something bad happens after it.
The next thing I found out is that the adapter's code
JAXBElement jaxbElement = unmarshaller.unmarshal(source, clazz);
causes NPE. When I remove this line of code and replace unmarshall()'s return statement to
return new A(); //for example
no NPE occurs.