2. JAXB Configuration

Custom JAXB bindings for date and date time to use Jode DateTime.

jaxb-bindings.xjb
                
<?xml version="1.0" encoding="UTF-8"?> 
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
               xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
               jaxb:extensionBindingPrefixes="xjc"
               version="2.0"> 

    <jaxb:bindings> 
        <jaxb:globalBindings> 
            <jaxb:serializable/> 
            
            <xjc:javaType adapter="org.springbyexample.jaxb.beans.adapter.DateXmlAdapter" name="org.joda.time.DateTime" xmlType="xsd:date" />
            <xjc:javaType adapter="org.springbyexample.jaxb.beans.adapter.DateTimeXmlAdapter" name="org.joda.time.DateTime" xmlType="xsd:dateTime" />
        </jaxb:globalBindings> 
    </jaxb:bindings>
     
</jaxb:bindings>
                
            

Entity base model for persistent entities. It is defined as an xsd:complexType so it can be extended, but is annotated to have XmlRootElement so it can be serialized by JAXB if it is returned directly from a controller (as opposed to being part of another instance returned).

entity-base.xsd
                
<xsd:schema xmlns="http://www.springbyexample.org/schema/beans/entity" 
            targetNamespace="http://www.springbyexample.org/schema/beans/entity"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
            xmlns:annox="http://annox.dev.java.net" 
            jaxb:extensionBindingPrefixes="annox">

    <xsd:complexType name="pk-entity-base">
        <xsd:annotation>
            <xsd:appinfo>
                <annox:annotate>
                    <annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="pk-entity-base"/>
                </annox:annotate>
            </xsd:appinfo>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="id" type="xsd:int" />
            
            <xsd:element name="lock-version" type="xsd:int" />
            
            <xsd:element name="last-updated" type="xsd:dateTime" />
            <xsd:element name="last-update-user" type="xsd:string" />
            <xsd:element name="created" type="xsd:dateTime" />
            <xsd:element name="create-user" type="xsd:string" />
        </xsd:sequence>
    </xsd:complexType>

</xsd:schema>
                
            

Responses for single and multiple results. Abstract base classes are defined to provide a way to handle responses more generically in the Java code.

Excerpt from response-base.xsd

                
<xsd:schema xmlns="http://www.springbyexample.org/schema/beans/response" 
            targetNamespace="http://www.springbyexample.org/schema/beans/response"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
            xmlns:annox="http://annox.dev.java.net" 
            jaxb:extensionBindingPrefixes="annox"
            jaxb:version="2.1">

    ...

    <xsd:complexType name="abstract-response">
        <xsd:annotation>
            <xsd:appinfo>
                <jaxb:class ref="org.springbyexample.schema.beans.response.AbstractResponse"/>
            </xsd:appinfo>
        </xsd:annotation>
    </xsd:complexType>

    <xsd:complexType name="abstract-response-result">
        <xsd:annotation>
            <xsd:appinfo>
                <jaxb:class ref="org.springbyexample.schema.beans.response.AbstractResponseResult"/>
            </xsd:appinfo>
        </xsd:annotation>
    </xsd:complexType>
    <xsd:complexType name="abstract-entity-response-result" abstract="true">
        <xsd:complexContent>
            <xsd:extension base="abstract-response-result">
                <xsd:sequence>        
                    <xsd:element name="errors" type="xsd:boolean" />
                    <xsd:element name="message-list" type="message" minOccurs="0" maxOccurs="unbounded" />
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="abstract-find-response-result">
        <xsd:annotation>
            <xsd:appinfo>
                <jaxb:class ref="org.springbyexample.schema.beans.response.AbstractFindResponseResult"/>
            </xsd:appinfo>
        </xsd:annotation>
    </xsd:complexType>
    <xsd:complexType name="abstract-entity-find-response-result" abstract="true">
        <xsd:complexContent>
            <xsd:extension base="abstract-find-response-result">
                <xsd:sequence>        
                    <xsd:element name="errors" type="xsd:boolean" />
                    <xsd:element name="message-list" type="message" minOccurs="0" maxOccurs="unbounded" />

                    <!-- primarily for paginated results -->
                    <xsd:element name="count" type="xsd:long" />
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="response-result">
        <xsd:annotation>
            <xsd:appinfo>
                <annox:annotate>
                    <annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="response-result"/>
                </annox:annotate>
            </xsd:appinfo>
        </xsd:annotation>
        <xsd:complexContent>
            <xsd:extension base="abstract-response">
                <xsd:sequence>        
                    <xsd:element name="errors" type="xsd:boolean" />
                    <xsd:element name="message-list" type="message" minOccurs="0" maxOccurs="unbounded" />
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="find-response-result">
        <xsd:complexContent>
            <xsd:extension base="response-result">
                <xsd:sequence>
                    <!-- primarily for paginated results -->
                    <xsd:element name="count" type="xsd:long" />
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="message">
        <xsd:sequence>
            <xsd:element name="message-type" type="message-type" />
            <xsd:element name="message" type="xsd:string" />
            <xsd:element name="message-key" type="xsd:string" />
            <xsd:element name="property" type="xsd:string" />
        </xsd:sequence>
    </xsd:complexType>

    <xsd:simpleType name="message-type">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="INFO" />
            <xsd:enumeration value="WARN" />
            <xsd:enumeration value="ERROR" />
            <xsd:enumeration value="FATAL" />
        </xsd:restriction>
    </xsd:simpleType>

</xsd:schema>
                
            

Person/Student/Professional complex types and their responses are defined.

person-base.xsd
                
<xsd:schema xmlns="http://www.springbyexample.org/schema/beans/person"
            targetNamespace="http://www.springbyexample.org/schema/beans/person"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
            xmlns:annox="http://annox.dev.java.net" 
            jaxb:extensionBindingPrefixes="annox"
            xmlns:entity="http://www.springbyexample.org/schema/beans/entity"
            xmlns:response="http://www.springbyexample.org/schema/beans/response">

    <xsd:import namespace="http://www.springbyexample.org/schema/beans/entity" schemaLocation="entity-base.xsd" />
    <xsd:import namespace="http://www.springbyexample.org/schema/beans/response" schemaLocation="response-base.xsd" />

    <xsd:element name="person-response">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="response:abstract-entity-response-result">
                    <xsd:sequence>
                        <xsd:element name="results" type="person" />
                    </xsd:sequence>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

    <xsd:element name="person-find-response">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="response:abstract-entity-find-response-result">
                    <xsd:sequence>
                        <xsd:element name="results" type="person" minOccurs="0" maxOccurs="unbounded" />
                    </xsd:sequence>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

    <xsd:element name="professional-response">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="response:abstract-entity-response-result">
                    <xsd:sequence>
                        <xsd:element name="results" type="professional" />
                    </xsd:sequence>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

    <xsd:element name="professional-find-response">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="response:abstract-entity-find-response-result">
                    <xsd:sequence>
                        <xsd:element name="results" type="professional" minOccurs="0" maxOccurs="unbounded" />
                    </xsd:sequence>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

    <xsd:complexType name="person">
        <xsd:annotation>
            <xsd:appinfo>
                <annox:annotate>
                    <annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="person"/>
                </annox:annotate>
            </xsd:appinfo>
        </xsd:annotation>
        <xsd:complexContent>
            <xsd:extension base="entity:pk-entity-base">
                <xsd:sequence>
                    <xsd:element name="first-name" type="xsd:string" />
                    <xsd:element name="last-name" type="xsd:string" />
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="student">
        <xsd:annotation>
            <xsd:appinfo>
                <annox:annotate>
                    <annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="student"/>
                </annox:annotate>
            </xsd:appinfo>
        </xsd:annotation>
        <xsd:complexContent>
            <xsd:extension base="person">
                <xsd:sequence>
                    <xsd:element name="school-name" type="xsd:string" />
                </xsd:sequence>                
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="professional">
        <xsd:annotation>
            <xsd:appinfo>
                <annox:annotate>
                    <annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="professional"/>
                </annox:annotate>
            </xsd:appinfo>
        </xsd:annotation>
        <xsd:complexContent>
            <xsd:extension base="person">
                <xsd:sequence>
                    <xsd:element name="company-name" type="xsd:string" />
                </xsd:sequence>                
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

</xsd:schema>