Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

when does JAXB unmarshaller.unmarshal returns a JAXBElement<MySchemaObject> or a MySchemaObject?

I have two codes, in two different java projects, doing almost the same thing, (unmarshalling the input of a webservice according to an xsd-file).

But in one case I should write this: (Input is a placeholder name) ( element is OMElement input )

ClassLoader clInput = input.ObjectFactory.class.getClassLoader(); JAXBContext jc = JAXBContext.newInstance("input", clInput); Unmarshaller unmarshaller = jc.createUnmarshaller(); Input input = (Input)unmarshaller.unmarshal( element.getXMLStreamReader() ); 

and in the other lib I must use JAXBElement.getValue(), because it is a JAXBElement that is returned, and a simple (Input) cast simply crashes:

Input input = (Input)unmarshaller.unmarshal( element.getXMLStreamReader() ).getValue(); 

Do you know what leads to such a difference ?

like image 808
Stephane Rolland Avatar asked Apr 20 '12 09:04

Stephane Rolland


People also ask

How do you Unmarshal Jaxbelement?

Unmarshalling. To unmarshal an XML string into a JAXB object, just inject the Jaxb2Marshaller and call the unmarshal() method.

Is Jaxb Unmarshaller thread safe?

A: The JAXB Specification currently does not address the thread safety of any of the runtime classes. In the case of the Oracle JAXB RI, the JAXBContext class is thread safe, but the Marshaller , Unmarshaller , and Validator classes are not thread safe.


2 Answers

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 
like image 137
bdoughan Avatar answered Oct 19 '22 21:10

bdoughan


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> 
like image 40
Puce Avatar answered Oct 19 '22 21:10

Puce