I have a schema that defines the following type:
<xsd:complexType name="Payload">
<xsd:sequence>
<xsd:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
</xsd:sequence>
</xsd:complexType>
And that creates an object like so:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Payload", propOrder = {
"any"
})
public class Payload {
@XmlAnyElement(lax = true)
protected List<Object> any;
}
Now I try adding another generated JAXB object to that Payload doing something like this:
Class payloadClass = ...;
JAXBContext context = JAXBContext.newInstance( WrapperRequest.class, payloadClass);
...
marshaller.marshal( wrappedRequest );
But I get a terrible exception that looks like it’ll never work so I decide to serialize the payload object to XML first then add that as a string in the payload.
StringWriter writer = new StringWriter();
JAXBContext context = JAXBContext.newInstance( sdoRequest.getClass() );
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(new JAXBElement(new QName("uri", sdoRequest.getClass().getSimpleName()), sdoRequest.getClass(), sdoRequest), writer);
payload.getAny().add( writer.toString() );
And this blows up with an exception saying “java.lang.String” does not contain an @XmlRootElement.
So how will the use of xs:any ever work with JAXB? Nothing seems to want to work because JAXB turns the Payload into Object, and it won’t serialize just anything in Object. This is all inside Axis2 as well so it’s been very challenging to get to this point.
Below I will demonstrate JAXB (JSR-222) and
anywith an example:Payload
The
anyproperty is annotated with@XmlAnyElement(lax=true). This means that for that property if an element is associated with a class via@XmlRootElementor@XmlElementDeclthen an instance of the corresponding object will be used to populate the property if not the element will be set as an instance oforg.w3c.dom.Element.Foo
Below is an example of a class annotated with
@XmlRootElement.Bar
Below is an example of a class without the
@XmlRootElementannotation. In this use case we will leverage the@XmlElementDeclannotation on a factory class (usually calledObjectFactory) annotated with@XmlRegistry.ObjectFactory
Below is an example of specifying an
@XmlElementDeclannotation for theBarclass.input.xml
Below is the input document we’ll use for this example. There are 3 elements that correspond to the
anyproperty. The first corresponds to the@XmlRootElementannotation on theFooclass. The second corresponds to the@XmlElementDeclannotation for theBarclass and the third does not correspond to any of the domain classes.Demo
In the demo code below we will unmarshal the input document, then output the classes of the objects in the resulting
anyproperty and then marshal thepayloadobject back to XML.Output
Below is the output from running the demo code. Note the classes corresponding to the objects in the
anyproperty. Thefooelement became an instance of theFooclass. Thebarelement became an instance ofJAXBElementthat holds an instance ofBar. Theotherelement became an instance oforg.w3c.dom.Element.