when does JAXB unmarshaller.unmarshal returns a JAXBElement<MySchemaObject> or a MySchemaObject?
If the root element uniquely corresponds to a Java class then an instance of that class will be returned, and if not a JAXBElement
will be returned.
If you want to ensure that you always get an instance of the domain object you can leverage the JAXBInstrospector
. Below is an example.
Demo
package forum10243679;
import java.io.StringReader;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
public class Demo {
private static final String XML = "<root/>";
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBIntrospector jaxbIntrospector = jc.createJAXBIntrospector();
Object object = unmarshaller.unmarshal(new StringReader(XML));
System.out.println(object.getClass());
System.out.println(jaxbIntrospector.getValue(object).getClass());
Object jaxbElement = unmarshaller.unmarshal(new StreamSource(new StringReader(XML)), Root.class);
System.out.println(jaxbElement.getClass());
System.out.println(jaxbIntrospector.getValue(jaxbElement).getClass());
}
}
Output
class forum10243679.Root
class forum10243679.Root
class javax.xml.bind.JAXBElement
class forum10243679.Root
It depends on the presence of XmlRootElement annotation on the class of your root element.
If you generate your JAXB classes from an XSD, the following rules are applied:
- if the type of the root element is an anonymous type -> XmlRootElement annotation is added to the generated class
- if the type of the root element is a top level type -> XmlRootElement annotation is omitted from the generated class
For that reason I often choose anonymous types for root elements.
You can customize the class name of this anonymous type with a customization file. E.g. create a bindings.xjc file like this:
<jxb:bindings version="1.0"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:bindings schemaLocation="yourXsd.xsd" node="/xs:schema">
<jxb:bindings node="//xs:element[@name='yourRootElement']">
<jxb:class name="YourRootElementType"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>