Java – JAXB xjc:simple binding does not generate @XmlRootElement for base class

javajaxbxml

I am using JAXB 2.0. I have various elements and types defined in an XSD file. Here's an example:

<xs:element name="Person" type="Person" />
<xs:complexType name="Person">
    <xs:attribute name="name" type="xs:string"/>
</xs:complexType>

<xs:element name="Musician" type="Musician"/>
<xs:complexType name="Musician">
    <xs:complexContent>
        <xs:extension base="Person">
             <xs:attribute name="instrument" type="xs:string"/>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

<xs:element name="People" type="People"/>
<xs:complexType name="People">
    <xs:sequence>
        <xs:element name="person" type="Person" minOccurs="0" maxOccurs="Unbounded/>
    </xs:sequence>
</xs:complexType>

So as you can see from the above schema example, we have a Person, who has a name, and a Musician, who is also a Person (though this may be subject to some debate, but that's for another forum). There is also a People element, which is essentially a collection of Person types.

I have the following in a bindings file:

<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
jaxb:version="2.0" 
xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc" 
jaxb:extensionBindingPrefixes="xjc"> 
    <jaxb:globalBindings optionalProperty="wrapper"> 
            <xjc:simple/>
    </jaxb:globalBindings> 

My intended use of these objects is:

  1. A Person may appear as a solitary Marshalled element, or may be a part of a People object
  2. If a Person is part of a People object, then the xsi:type should indicate whether it's just a normal Person or a Musician.

So I need the generated Java classes to contain both an @XmlRootElement annotation as well as an @XmlType annotation. The xjc:simple binding creates both annotations for a Musician, but only creates the @XmlType for Person. So when I Marshall a Person object, all I get is:

<?xml version="1.0" encoding="UTF-8"?>

Whereas what I would like to see is:

<?xml version="1.0" encoding="UTF-8"?>
<Person name="John Doe"/>

For a People object, I want to see:

<?xml version="1.0" encoding="UTF-8"?>
<People>
    <person name="John Doe" xsi:type="Person"/>
    <person name="Keith Richards" xsi:type="Musician"/>
</People>

I have read about the simple binding with xjc, and it works with all the lowest levels in an inheritance hierarchy. However, the base classes end up without an @XmlRootElement annotation. For the use case I'm working on, it's imperative that base classes can be Marshalled as both a top-level element and as a member of other elements. Any suggestions would be welcome.

Best Solution

https://github.com/highsource/jaxb2-annotate-plugin could be used

<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings xmlns:annox="http://annox.dev.java.net"
               xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
               jaxb:version="2.1"
               xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
               jaxb:extensionBindingPrefixes="xjc annox">

    <jaxb:bindings node="//xs:complexType[@name='Person']">
        <annox:annotate>
            <annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="person"/>
        </annox:annotate>
    </jaxb:bindings>
</jaxb:bindings>