There is a placeholder answer over at the unofficial guide with a link to an article which (to me) seems quite unrelated.
I use XJC to generate my JAXB classes and while most of them map to each other as expected, some elements get mapped to JAXBElement<Foo>
. This is most annoying for graphs with cycles, where sometimes the parent node of a Foo element will be the JAXBElement<Foo>
, which doesn't itself have a parent property, breaking the cycle.
I can think of various workarounds, but it would be much nicer if someone could explain this behaviour to me. Why does JAXB sometimes map a <Foo>
element to JAXBElement<Foo>
instead of Foo?
JAXBElement is used to preserve the element name/namespace in use cases where enough information is not present in the object model. It's often used with substitution groups. Without any JAXB metada the result will be wrapped in a JAXBElement.
public class JAXBElement<T> extends Object implements Serializable. JAXB representation of an Xml Element. This class represents information about an Xml Element from both the element declaration within a schema and the element instance value within an xml document with the following properties. element's xml tag name.
If getProject() returns the type JAXBElement<String> then getName() returns the name of the XML tag. To get the value of that element you need to call getValue() .
jaxb package. An ObjectFactory allows you to programatically construct new instances of the Java representation for XML content. The Java representation of XML content can consist of schema derived interfaces and classes representing the binding of schema type definitions, element declarations and model groups.
JAXBElement is used to preserve the element name/namespace in use cases where enough information is not present in the object model. The most common occurence is with substitution groups:
With Substitution Group:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org"
xmlns="http://www.example.org"
elementFormDefault="qualified">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element ref="anElement"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="anElement" type="xs:string"/>
<xs:element name="aSubstituteElement" type="xs:string" substitutionGroup="anElement"/>
</xs:schema>
Will generate:
package org.example;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"anElement"
})
@XmlRootElement(name = "root")
public class Root {
@XmlElementRef(name = "anElement", namespace = "http://www.example.org", type = JAXBElement.class)
protected JAXBElement<String> anElement;
public JAXBElement<String> getAnElement() {
return anElement;
}
public void setAnElement(JAXBElement<String> value) {
this.anElement = ((JAXBElement<String> ) value);
}
}
Without Substitution Group:
If you remove the substitution group:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org"
xmlns="http://www.example.org"
elementFormDefault="qualified">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element ref="anElement"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="anElement" type="xs:string"/>
</xs:schema>
The following class will be generated:
package org.example;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"anElement"
})
@XmlRootElement(name = "root")
public class Root {
@XmlElement(required = true)
protected String anElement;
public String getAnElement() {
return anElement;
}
public void setAnElement(String value) {
this.anElement = value;
}
}
You may also get a JAXBElement when you unmarshal, compare the following examples:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With