Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAXB not unmarshalling xml any element to JAXBElement

Tags:

java

jaxb

I have a webservice call. In my response when I try to get the xml any element in to a JAXBElement it throws an error.

In the schema I have:

<xs:complexType name="InputType">
    <xs:annotation></xs:annotation>
    <xs:sequence>           
        <xs:element name="Id" type="xs:string" />
        <xs:any namespace="##any" processContents="lax" minOccurs="0" />
    </xs:sequence>
</xs:complexType>

The code I am using:

Object obj = inputType.getAny();
Object o = ((JAXBElement)obj).getValue(); 

This line throws the error: org.apache.xerces.dom.ElementNSImpl incompatible with javax.xml.bind.JAXBElement error in soap ui.

Why doesn't it covert to JAXBElement? How do I make it work?

like image 480
valve2010 Avatar asked Feb 25 '11 20:02

valve2010


People also ask

How do you Unmarshal Jaxbelement?

To unmarshal an xml string into a JAXB object, you will need to create an Unmarshaller from the JAXBContext, then call the unmarshal() method with a source/reader and the expected root object.

What is QName in Jaxbelement?

protected QName name − This is the xml element tag name. protected boolean nil − This is true if the xml element instance has xsi:nil="true". protected Class scope − This is the scope of xml element declaration representing this xml element instance. protected T value − This is the xml element value.

How does JAXB marshalling work?

In JAXB, marshalling involves parsing an XML content object tree and writing out an XML document that is an accurate representation of the original XML document, and is valid with respect the source schema. JAXB can marshal XML data to XML documents, SAX content handlers, and DOM nodes.


1 Answers

If the property is annotated with the following the contents will be mapped as DOM nodes:

@XmlAnyElement

If the lax=true flag is set then known elements will be converted to domain objects:

@XmlAnyElement(lax=true)

For more information on @XmlAnyElement see:

  • http://bdoughan.blogspot.com/2010/08/using-xmlanyelement-to-build-generic.html

UPDATE #1

With lax=true you can get a mix of domain objects and DOM nodes. The following is from the java docs:

  • http://download.oracle.com/javase/6/docs/api/javax/xml/bind/annotation/XmlAnyElement.html#lax()

When true

If true, when an element matches a property marked with XmlAnyElement is known to JAXBContext (for example, there's a class with XmlRootElement that has the same tag name, or there's XmlElementDecl that has the same tag name), the unmarshaller will eagerly unmarshal this element to the JAXB object, instead of unmarshalling it to DOM. Additionally, if the element is unknown but it has a known xsi:type, the unmarshaller eagerly unmarshals the element to a JAXBElement, with the unknown element name and the JAXBElement value is set to an instance of the JAXB mapping of the known xsi:type.

As a result, after the unmarshalling, the property can become heterogeneous; it can have both DOM nodes and some JAXB objects at the same time.


UPDATE #2

To ultimately solve the problem:

  1. Since it is possible for that property to contain a DOM node, your code should account for this possibility by doing some type checking.
  2. To reduce the amount of DOM nodes received you need to associate the possible root elements of those fragments with Java classes. This is done by annotating classes with @XmlRootElement(name="foo", namespace="bar"), or with @XmlElementDecl.

Check out my blog for an example:

  • http://bdoughan.blogspot.com/2010/08/using-xmlanyelement-to-build-generic.html
like image 107
bdoughan Avatar answered Nov 15 '22 23:11

bdoughan