I've been annotating classes with @XMLType when the structure will be
used more than once within an XML schema and with @XMLRootElement when
it will be used only once - is this the best approach?
One thing to know is that neither the @XmlRootElement
or @XmlType
annotation is required. They aren't the equivalent of @Entity
from JPA. You can use a JAXB (JSR-222) implementation without any annotations what so ever:
Below I'll explain what @XmlRootElement
and @XmlType
do.
@XmlRootElement
There are times when your JAXB implementation needs to instantiate an object based only on the XML element that is being processed. The @XmlRootElement
annotation is the primary means of specifying this association. Note if a class corresponds to more than one XML element then the @XmlElementDecl
annotation should be used insteat,
ROLE #1 - Specifying the Root Object
@XmlRootElement
is primarily used to specify the root object. This is so when your JAXB implementation begins unmarshalling an XML document it knows what object to instantiate. Almost all subsequent annotations will be based on information gathered from the parent class.
Foo
@XmlRootElement(name="root")
public class Foo {
private String name;
}
Bar
public class Bar {
private String name;
}
XML
<root>
<name>Jane Doe</name>
</root>
Demo
Foo foo = (Foo) unmarshaller.unmarshal(xml);
Bar bar = unmarshaller.unmarshal(xml, Bar.class).getValue();
ROLE #2 - Substitution Groups
The @XmlElementRef
annotation delegates the type of object instantiated to the name/uri of the element. This enables the mapping to the concept of substitution groups for representing inheritance.
ROLE #3 - Any Content
@XmlAnyElement
allows you to map a wild card section of your XML document. If you specify @XmlAnyElement(lax=true)
then elements associated with domain objects will be converted to the corresponding domain object.
@XmlType
ROLE #1 - Schema Gen
By default a named complex type is generated for each Java class known to the JAXB context. You can control the name of this type using the @XmlType
annotation, or specify that an anonymous complex type should be generated by specifying the name as ""
.
ROLE #2 - Inheritance and xsi:type
By default JAXB leverages the xsi:type
attribute as the inheritance indicator. The value on this attribute corresponds to the name and namespace you have specified on the @XmlType
annotation, or is defaulted based on the class.
ROLE #3 - Prop Order
As you mention you can use the @XmlType
to specify the property order.
ROLE #4 - Factory Methods
@XmlType
allows you to specify a factory class and/or method that can be used to instantiate the domain object instead of the default constructor.
A different but related question which I'll include here. The @XMLType
annotation has an propOrder attribute to specify in which order it's
elements appear - is there an equivalent for @XMLRootElement?
No, the propOrder
aspect belongs to the @XmlType
annotation. This makes sense since complex types are responsible for specifying an (or lack of) order. You can of course use these annotations at the same time.
@XmlRootElement
@XmlType(propOrder={"foo", "bar"}
public class Root {
...
}