Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

A JAXB Tutorial

Download as pdf or txt
Download as pdf or txt
You are on page 1of 92

A JAXB Tutorial

Wolfgang Laun
Thales Rail Signalling Solutions GesmbH

1 Introduction 1.1 About JAXB 1.2 Overview 1.3 Hello World 2 Writing an XML Schema for JAXB 2.1 XML Schema Types 2.2 JAXB Examples 2.2.1 Defining an Integer Range Type 2.2.2 Numeric Types 2.2.3 Defining a String with Length Limits 2.2.4 Defining a String Type Restricted By Pattern 2.2.5 Date and Time 2.2.6 Binary Data 2.2.7 Defining a List of Integers 2.2.8 Defining Other Lists 2.2.9 Defining an Enumeration 2.2.10 Defining a Type Union 2.2.11 Defining Types for XML Elements Without Content 2.2.12 Defining Types for XML Elements With Content 2.2.12.1 Content: A Value 2.2.12.2 Content: An Ordered Set of Elements 2.2.12.3 Content: An Unordered Set of Elements 2.2.12.4 Content: Alternative Elements 2.2.12.5 Content: A Homogeneous List of Elements 2.2.12.6 Content: A Mixed List of Elements 2.2.12.7 Mixed Content 2.2.12.8 No Value 2.2.13 Defining Subtypes 2.2.14 Substitution Groups 2.2.15 Referring to Another XML Element 2.2.16 Elements With Any Type 2.2.16.1 DOM Elements 2.2.16.2 Another Content Tree as Element 2.2.17 Image Data 2.3 Hints on Writing XML Schemas 2.3.1 Don't Use Anonymous Types 2.3.2 Common Schema Definitions 2.3.3 A Note on Groups 2.3.4 Conserving Compatibility 2.3.5 Spurious Classes 2.3.6 Avoid Unnecessary JAXBElement<?> 3 Unmarshalling and Using the Data 3.1 Unmarshalling 3.2 Using the Element Tree 3.3 Validation 3.4 Validation Event Handling 3.5 The JAXB Context 4 Building and Marshalling an XML Document 4.1 The Object Factory 4.2 Assembling Document Tree Nodes 4.3 Assembling Data with Links (ID, IDREF) 4.3.1 One Element per Identification

4.3.2 Preserving Object Identity 4.4 Last Resort: Assembling a Java Object 4.5 Calling marshal 5 Customizing 5.1 Reasons for Customizing 5.2 Defining Package Names 5.3 Overriding Names 5.4 Adding Documentation 5.5 Interning Strings 5.6 Overriding the Datatype 5.6.1 Replacing the Conversions 5.6.2 Replacing a Simple Type 6 JAXB Annotations 6.1 How a Schema Mapping Is Implemented 6.2 A Survey Of JAXB Annotations 6.2.1 Top-level Elements: XmlRootElement 6.2.2 Annotation for Classes: XmlType 6.2.3 Annotations for the Schema: XmlSchema 6.2.4 The Object Factory: XmlRegistry, XmlElementDecl 6.2.5 Controlling Element Selection: XmlAccessorType, XmlTransient 6.2.6 Class Inclusion: XmlSeeAlso 6.2.7 Annotations for Fields 6.2.7.1 The Annotation XmlElement 6.2.7.2 The Annotation XmlList 6.2.7.3 Class Fields as Attributes: XmlAttribute 6.2.7.4 Mapping a Class to Simple Content or Simple Type: XmlValue 6.2.7.5 Collecting Unspecified Attributes: XmlAnyAttribute 6.2.7.6 Collecting Unspecified Elements: XmlAnyElement 6.2.7.7 Wrapping Repeated Elements: XmlElementWrapper 6.2.7.8 Annotations for Mixed Content: XmlElementRef, XmlMixed 6.2.8 Annotations for Enums: XmlEnum, XmlEnumValue 6.2.9 Type Adapters: XmlJavaTypeAdapter 6.2.10 Type Mapping: XmlSchemaType 6.2.11 Annotations for Object References: XmlID, XmlIDREF

1 Introduction 1.1 About JAXB JAXB is an acronym derived from Java Architecture for XML Binding. It constitutes a convenient framework for processing XML documents, providing significant benefits as compared to previously available methods such as the one following the Document Object Model (DOM). In the DOM approach, the parser creates a tree of objects that represents the content and organization of data in the document. The application can then navigate through the tree in memory to access the data it needs. DOM data, however, is contained in objects of a single type, linked according to the XML document's structure, with individual node objects containing an element, an attribute, a CDATA section, etc. Values are invariably provided as strings. Unmarshalling an XML document with the appropriate JAXB method also results in a tree of objects, with the significant difference being that the nodes in this tree correspond to XML elements, which contain attributes and the content as instance variables and refer to child elements by object references. The most convenient way to obtain the Java type information describing the node elements is by compiling an XML schema, usually written in the W3C XML Schema Language, using the JAXB Binding Compiler xjc. The resulting set of classes defines the types required for accessing elements, attributes and other content in a typesafe way. Schemas written in the XML Schema Language can describe structural relationships and data types, with a very high level of distinctiveness. The scalar datatypes of the XML Schema Language are mapped to Java data types. Lists of values and certain element groupings are mapped to Java's java.util.List. It should be noted that the XML Schema language is capable of defining XML structures that cannot be bound by a schema compiler. In many of these cases it is possible to circumnavigate the problem by adding binding declarations to direct the schema compiler in some specific way to achieve a successful binding. The JAXB runtime library, supported with the code generated by the Binding Compiler, provides methods for unmarshalling a document from various sources as well as for marshalling a content tree to various destinations. JAXB also supports marshalling and unmarshalling for SAX, the Simple API for XML. JAXB uses Java's annotations for augmenting the generated classes with additional information that bridges the gap between what is decribed by an XML schema and the information available (via Java's reflection mechanisms) from a set of Java class definitions. Adding such annotations to existing Java classes prepares them for being used by JAXB's runtime. As of the time of this writing (March 2009) JAXB is available as version 2.1.10. Versions from 2.0 on contain bug fixes and minor additions. Version 2, as compared to version 1, was a big step ahead and has brought JAXB to a mature level. (JAXB version 1 should not be used any more.) 1.2 Overview The chapter Writing an XML Schema for JAXB discusses how JAXB represents the

various XML Schema language constructs in Java. The examples illustrate how a schema should be written to produce easy-to-use Java code. Chapters Unmarshalling and Using the Data and Building and Marshalling an XML Document describe how to convert XML document data into a content tree and vice versa. Customizing discusses the various options for augmenting and modifying schema information, influencing several aspects of the generated Java code. The chapter JAXB Annotations presents the most important JAXB annotations and examples using them on hand-written Java classes. The intention of this tutorial is to provide you with examples and guidelines for the essential features of JAXB. Much of what can be done with JAXB is not covered here. Some of these features are: -- The XML Schema generator schemagen, which derives a schema from a set of Java classes. -- The XML Schema compiler xjc may be extended with plugins - obviously an area for experts. -- Some features rely on specific implementations of JAXB. A good place for digging up remarkable tricks is the archives of Kohsuke Kawaguchi's Blog. 1.3 Hello World We'll stick with the tradition and use a sort of "Hello World" XML document to illustrate the typical scenario for creating the Java classes and their use to marshal a document. We'll not discuss any details in this subsection; it's just here to give you the overall picture. The XML Schema on hello.xsd defines the structure of our document, which is to contain a series of salutations, each of which contains a greeting (such as "Hello world") and an attribute for registering the language of the salutation. <?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" jxb:version="2.0"> <xsd:element name="Greetings" type="GreetingListType"/> <xsd:complexType name="GreetingListType"> <xsd:sequence> <xsd:element name="Greeting" type="GreetingType" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="GreetingType"> <xsd:sequence> <xsd:element name="Text" type="xsd:string"/> </xsd:sequence>

<xsd:attribute name="language" type="xsd:language"/> </xsd:complexType> </xsd:schema> Now we can call the JAXB schema compiler, defining the package name hello for the generated classes. xjc -p hello hello.xsd This generates several classes in the subdirectory hello. The class Hello shows how to use them. import java.util.*; import javax.xml.bind.*; import hello.*; public class Hello { private ObjectFactory of; private GreetingListType grList; public Hello(){ of = new ObjectFactory(); grList = of.createGreetingListType(); } public void make( String t, String l ){ GreetingType g = of.createGreetingType(); g.setText( t ); g.setLanguage( l ); grList.getGreeting().add( g ); } public void marshal() { try { JAXBElement<GreetingListType> gl = of.createGreetings( grList ); JAXBContext jc = JAXBContext.newInstance( "hello" ); Marshaller m = jc.createMarshaller(); m.marshal( gl, System.out ); } catch( JAXBException jbe ){ // ... } } } The constructor uses a method from the object factory to create an object of the document's top level XML element type, i.e., GreetingListType. The make method adds another salutation with its text element and the language attribute. Finally, with a call to marshal, the list is wrapped in its XML element, and the resulting XML document is written to the standard output stream. Here's a sequence of these calls:

Hello h = new Hello(); h.make( "Bonjour, madame", "fr" ); h.make( "Hey, you", "en" ); h.marshal(); The output is shown below, formatted, for better readability. <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Greetings> <Greeting language="fr"> <Text>Bonjour, madame</Text> </Greeting> <Greeting language="en"> <Text>Hey, you</Text> </Greeting> </Greetings>

2 Writing an XML Schema for JAXB 2.1 XML Schema Types A schema describes data types, with the intent of defining one or more hierarchical types defining XML documents. Type information deals with the definition of structure, i.e., the composition of document nodes, and the classification of scalar (or list) values for content and attributes. The XML Schema Language offers a rich set of features to achieve the required structuring and typing. A good introduction to the XML Schema language is the XML Schema Part 0: Primer, provided by the World Wide Web Consortium (W3C). Although all data in XML is text, it should generally not be defined as String in the Java classes derived from a schema. The XML Schema language provides the elementary data types for numbers, booleans, strings, URIs, dates and times, and for references and other XML constructs. Only by using these features will you receive the full benefit of JAXB, which will not only take care of all the necessary conversions to or from the textual representation in XML but also with the transformation of XML structures to Java data patterns, such as lists or maps. User-defined data types can be derived from any elementary type by adding one or more restrictions. This is done by adding so-called facets, which are available to set lower or upper bounds for values or string lengths, to limit the precision, to enumerate all legal values, and to define a pattern for a string type. JAXB uses enumerations restricting strings to define an enum type. Other facets, however, are ignored by the Schema Compiler. (Section Validation explains how to enable facet checking.) Data structuring concepts are expressed by using the complex type construct of the schema language. An XML element of some complex type may have child elements or attributes or both. For child elements, the schema's element grouping facilites <xsd:all>, <xsd:union>, <xsd:choice> and <xsd:sequence> in combination with repetition limit attributes let you define XML structures that are the equivalent of the classic concepts of array, list, structure (or record) and union. We'll discuss schema structuring and typing concepts in more detail in the next section, where examples of XML Schema language constructs are related to the Java code that the JAXB compiler uses for their representation. Please notice that the tags of schema elements are presented in the qualified form, with xsd as the namespace identifier. This (or some other name, e.g., xs) identifier must be bound to the URI identifying the XML Schema language. If used, also the jxb namespace prefix must be bound. Both is done in the schema element of the XML schema: <?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" jxb:version="2.0"> 2.2 JAXB Examples This chapter discusses various XML Schema constructs and how they are bound by

the JAXB schema compiler xjc. For brevity and clarity, the resulting Java code is generally shown without the annotations. 2.2.1 Defining an Integer Range Type The XML Schema snippet shown below defines an integer type, limiting permissible values to the range 1 to 255. <xsd:simpleType name="GroupType"> <xsd:restriction base="xsd:int"> <xsd:minInclusive value="1"/> <xsd:maxInclusive value="255"/> </xsd:restriction> </xsd:simpleType> A simple type restricting xsd:int will not result in a separate Java class being generated. The JAXB compiler will simply fall back to int (or Integer) in all the places where GroupType is used. If you peek into one of these class definitions, you'll see simple get and set methods, like in this class derived from a schema type where an element has an attribute with name Group and type GroupType: public class ElementType { // ... @XmlAttribute(name = "Group", required = true) protected int group; // ... public int getGroup() { return group; } public void setGroup(int value) { this.group = value; } // ... } Where is, you might ask, the code that ensures that the integer value is between the bounds? The short and, perhaps, disappointing anwer is that there is no such code. JAXB expects you to request detailed validation explicitly by passing a javax.xml.validation.Schema object, created from your XML schema, to the marshaller or unmarshaller used for handling your data. We'll discuss this in the section on Validation. 2.2.2 Numeric Types The schema language features a multi-tiered type hierarchy of built-in numeric datatypes. We'll discuss them briefly in this subsection. Leaving double and float aside, the root of the tree is given by xsd:decimal. According to the XML Schema definition, this data type represents decimal numbers with an unspecified range of fractional and total digits. There is one Java type providing just that: java.math.BigDecimal. Doing away with fractional digits, we

arrive at xsd:integer, which still has an unspecified number of digits; hence java.math.BigInteger must be used. Although both types can be constrained using facets to delimit the number of digits or the value range, the Java code generated by JAXB does not reflect any of this. Below the integer type, the tree branches off into a hierarchy of non-negative integers, another one for their obscure cousins, the non-positive integers and the traditional line of integer types representing the typical two's complement ranges. The types long down to byte are normally mapped to Java's eponymous simple types. Exceptions result from the property nillable being set to true for an element or attribute. This adds another value to the set of possible values, i.e., nil, indicating that the element or attribute is simply absent. Java provides null as a convenient value for this abstract nil value - but only for descendants of Object. The non-negative types comprise xsd:nonNegativeInteger and the unsigned variations of the binary integer types, from xsd:unsignedLong down to xsd:unsignedByte. Since xsd:nonNegativeInteger is defined as a restriction of xsd:integer, it has to be represented by java.math.BigInteger. For xsd:unsignedLong, there is no fitting simple type, and therefore this type maps to java.math.BigInteger, too. With xsd:unsignedInt, xsd:unsignedShort and xsd:unsignedByte, JAXB reverts to simple types, using the smallest type capable of holding all values, e.g., short for xsd:unsignedByte. The following schema snippet contains a selection of the types discussed so far. <xsd:complexType name="NumericZooType"> <xsd:sequence> <xsd:element name="decimal" type="xsd:decimal"/> <xsd:element name="integer" type="xsd:integer"/> <xsd:element name="long" type="xsd:long"/> <xsd:element name="int" type="xsd:int" default="42"/> <xsd:element name="short_nil" type="xsd:short" nillable="true"/> <xsd:element name="byte" type="xsd:byte" default="13" nillable="true"/> <xsd:element name="nonNegative" type="xsd:nonNegativeInteger"/> <xsd:element name="unsignedLong" type="xsd:unsignedLong"/> <xsd:element name="unsignedInt" type="xsd:unsignedInt"/> </xsd:sequence> </xsd:complexType> And here is the resulting Java code, simplified for better readability. public class NumericZooType { protected protected protected protected protected BigDecimal decimal; BigInteger integer; long _long; int _int; Short shortNil;

protected protected protected protected

Byte _byte; BigInteger nonNegative; BigInteger unsignedLong; long unsignedInt;

public BigDecimal getDecimal() { return decimal; } public void setDecimal(BigDecimal value) { this.decimal = value; } // All other getters and setters follow the same pattern. // ... } Well, it's quite a zoo indeed. Although applications dealing with monetary quantities prosper on BigDecimal, schema designers who just want to express a simple integer counter (with a moderate upper limit) are not at all pleased when one of the "Big" types crops up in the generated Java code. So, the question is: can you retain the more convenient simple types while defining suitable value range limits? The answer is yes, of course, and it's demonstrated in the schema snippet shown below, where a simple type is defined as a restriction of the built-in type xsd:int. <xsd:simpleType name="CounterType"> <xsd:restriction base="xsd:int"> <xsd:minInclusive value="0"/> </xsd:restriction> </xsd:simpleType> ... <xsd:element name="counter" type="CounterType"/> No separate Java class is generated for CounterType. For some element such as counter, JAXB simply generates the type suitable for the base type of the restriction. protected int counter; public int getCounter() { return counter; } public void setCounter(int value) { this.counter = value; } 2.2.3 Defining a String with Length Limits The XML Schema snippet shown below defines a string type, limiting string lengths to the range 1 to 3. <xsd:simpleType name="ShortNameType"> <xsd:restriction base="xsd:string"> <xsd:minLength value="1"/>

<xsd:maxLength value="3"/> </xsd:restriction> </xsd:simpleType> Again, this simple type doesn't warrant a class definition of its own. Java's own java.lang.String is used, and the length restriction isn't checked unless you request it. 2.2.4 Defining a String Type Restricted By Pattern A string type may also be restricted by a pattern facet. The example below defines a type for strings of arbitrary length consisting of 'L' and 'R' only. Once more, no Java class is required for DirType. <xsd:simpleType name="DirType"> <xsd:restriction base="xsd:string"> <xsd:pattern value="[LR]*"/> </xsd:restriction> </xsd:simpleType> The syntax for regular expressions in pattern facets provides the basics for repetition, alternatives and grouping. It should be noted that a regular expression is always matched against the entire string value. 2.2.5 Date and Time JAXB binds all three of the schema types xsd:date, xsd:time and xsd:dateTime to XMLGregorianCalendar. This class is in the package javax.xml.datatype. (Do not confuse this with java.util.GregorianCalendar.) There is a convenient set of methods for getting at the various components such as year or day or minute. But creating any of these values isn't quite so simple because XMLGregorianCalendar is an abstract class. We'll illustrate this with a simple example for marshalling date and time. The XML schema snippet shown below defines an element containing sub-elements with xsd:date and xsd:time. <xsd:complexType name="DateTimeType"> <xsd:sequence> <xsd:element name="Date" type="xsd:date"/> <xsd:element name="Time" type="xsd:time"/> </xsd:sequence> </xsd:complexType> The generated class contains the usual getters and setters: public class DateTimeType { protected XMLGregorianCalendar date; protected XMLGregorianCalendar time; public XMLGregorianCalendar getDate() { return date;

} public void setDate(XMLGregorianCalendar value) { this.date = value; } public XMLGregorianCalendar getTime() { return time; } public void setTime(XMLGregorianCalendar value) { this.time = value; } } However, some work remains to be done before we can call either setter. It's the class DatatypeFactory that provides the methods with which we can create the XMLGregorianCalendar objects. // Create a DateTimeType element for the current time and date. ObjectFactory of = new ObjectFactory(); DateTimeType meta = of.createDateTimeType(); GregorianCalendar now = new GregorianCalendar(); // Obtain a DatatypeFactory instance. DatatypeFactory df = DatatypeFactory.newInstance(); // Create an XMLGregorianCalendar with the current date. XMLGregorianCalendar gcDate = df.newXMLGregorianCalendarDate( now.get( Calendar.YEAR ), now.get( Calendar.MONTH ), now.get( Calendar.DAY_OF_MONTH ), DatatypeConstants.FIELD_UNDEFINED ); // Create an XMLGregorianCalendar with the current time. XMLGregorianCalendar gcTime = df.newXMLGregorianCalendarTime( now.get( Calendar.HOUR_OF_DAY ), now.get( Calendar.MINUTE ), now.get( Calendar.SECOND ), null, // no fraction DatatypeConstants.FIELD_UNDEFINED ); // Insert sub-elements into the DateTimeType element. meta.setDate( gcDate ); meta.setTime( gcTime ); You may have noticed the null argument in the method constructing an XMLGregorianCalendar with the time. This indicates that we don't care about fractions of seconds. It is, however, not possible to omit seconds entirely. The XML element produced by this code will look like this:

<DateTime> <Date>2008-07-23</Date> <Time>18:42:24</Time> </DateTime> You should notice that the date and time representations follow ISO 8601. 2.2.6 Binary Data Data that has no "natural" representation with printable characters must, for inclusion in an XML file, still be represented in printable characters. The simple technique for this consists in converting the binary byte values to their hexadecimal representations. The XML Schema datatype to use in this case is xsd:hexBinary. A sample schema declaration is shown below. <xsd:complexType name="BinaryType"> <xsd:sequence> <xsd:element name="data" type="xsd:hexBinary"/> </xsd:sequence> </xsd:complexType> The Java class produced by JAXB contains a convenient pair of getter and setter methods for accessing the instance variable (called data) that stores the binary data. Its type and the type for passing the binary data is byte[]. All conversions are handled by JAXB.

public class BinaryType { protected byte[] data; public byte[] getData() { return data; } public void setData(byte[] value) { this.data = ((byte[]) value); } } 2.2.7 Defining a List of Integers To obtain a simple type that can be used for XML element values as well as for attribute values consisting of a simple series of values, use an xsd:list, as shown below. <xsd:simpleType name="NumberListType"> <xsd:list itemType="xsd:int"/> </xsd:simpleType> The Java type used for this schema type will be List<Integer>, so again no Java class has to be generated for this simple type. Using NumberListType as an attribute

or child type results in an instance variable and a getter method in the parent class: public class ListsType { // ... protected List<Integer> numbers; // ... public List<Integer> getNumbers() { if (numbers == null) { numbers = new ArrayList<Integer>(); } return this.numbers; } // ... } The code in the getter method ensures that the List<Integer> is created. There is no corresponding setter which means that all additions or deletions of list elements have to be made on the "live" list. 2.2.8 Defining Other Lists You can use any other atomic simple type definition or built-in primitive datatype in <xsd:list itemType="..."/>. The XML representation would be a list of values of that type, separated by white space. And right here is a potential catch: what if one of these values contains a blank? Therefore, unless you can be very sure that your strings are free from spaces or any other white space, don't use anything like <xsd:simpleType name="StringListType"> <xsd:list itemType="xsd:string"/> <!-- dangerous! --> </xsd:simpleType> To be on the safe side, use a complex type that contains a sequence of string elements. 2.2.9 Defining an Enumeration If you want a data type that enumerates discrete values you should use a restriction of the schema type xsd:string, enumerating all the values as you would in a Java enum type. <xsd:simpleType name="IXLType"> <xsd:restriction base="xsd:string"> <xsd:enumeration value="eStwA"/> <xsd:enumeration value="eStwS"/> <xsd:enumeration value="SpDrL"/> <xsd:enumeration value="SpDrS"/> <xsd:enumeration value="VGS80"/> </xsd:restriction> </xsd:simpleType> The JAXB compiler generates a Java enum, but the names of the enum constants are transformed so that they conform to the style commonly accepted in the Java community. Below is the (somewhat shortened) Java code.

public enum IXLType { E_STW_A("eStwA"), E_STW_S("eStwS"), SP_DR_L("SpDrL"), SP_DR_S("SpDrS"), VGS_80("VGS80"); private final String value; IXLType(String v) { value = v; } public String value() { return value; } } If you want to use the original identifiers as enum constant names, you may resort to an explicit specification of the binding, for each enum constant name, as shown below. <xsd:simpleType name="IXLType"> <xsd:restriction base="xsd:string"> <xsd:enumeration value="eStwA"/> <xsd:annotation><xsd:appinfo> <jxb:typesafeEnumMember name="eStwA"/> </xsd:appinfo></xsd:annotation> ... </xsd:restriction> </xsd:simpleType> The generated enum class will now contain enum constant names that exactly match the original strings. public enum IXLType { eStwA, eStwS, SpDrL, SpDrS, VGS80; public String value() { return name(); } ... } There is no need now to store the XML representations along with each enum constant, and method value may now simply call name() to obtain the stringified

value. 2.2.10 Defining a Type Union A simple type may also be constructed as a union of two or more simple types. <xsd:simpleType name="SpeedOrNumberType"> <xsd:union> <xsd:simpleType> <xsd:restriction base="xsd:int"> </xsd:restriction> </xsd:simpleType> <xsd:simpleType> <xsd:restriction base="xsd:string"> <xsd:pattern value="+?d+"/> </xsd:restriction> </xsd:simpleType> </xsd:union> </xsd:simpleType> In Java, there is no convenient way of expressing unions of simple types. The JAXB compiler simply inserts Java's String type wherever the union type is used and leaves it up to the application programmer to handle the rest. Try to avoid xsd:union. 2.2.11 Defining Types for XML Elements Without Content Types for XML elements are constructed using xsd:complexType, even if they do not have content. The snippet below defines a simple element with two attributes and no sub-elements. <xsd:complexType name="RouteType"> <xsd:attribute name="Pos" type="xsd:int" use="optional" default="1"/> <xsd:attribute name="Dir" type="DirType" use="required"/> </xsd:complexType> The compiler generates a class RouteType with getters and setters for the attributes. public class RouteType { protected Integer pos; protected String dir; public int getPos() { if (pos == null) { return 1; } else { return pos; } } public void setPos(Integer value) { this.pos = value;

} public String getDir() { return dir; } public void setDir(String value) { this.dir = value; } } The absence of a value for the optional attribute Pos is represented by an object where the instance variable pos remains at null. Method getPos takes care of supplying the default value if the variable is null. 2.2.12 Defining Types for XML Elements With Content 2.2.12.1 Content: A Value The content of an XML element may be some value, or one or more subordinate elements, or even a combination of both. Let's look at an XML element with a value of some type. This is defined by a schema construct like this: <xsd:element name="Quantity" type="xsd:int"/> This does not define another type, but it may occur as some part of a complex type definition that describes the structure and attributes of the containing element, this element itself and its siblings. The xsd:element defines the XML tag, so that an example of this XML element is bound to look like this: <Quantity>144</Quantity> The Java code resulting from such an embedded element definition is part of some class definition, i.e., the one describing the containing element, and it consists of the declaration of an instance variable, a getter method (here: int getQuantity()) and, except for list types, a setter method (here: void setQuantity(int value)). An element definition like this may also be provided for specifying the root element of an XML document. Obviously, such an element cannot be part of yet another type definition describing the structure of an enclosing element, simply because there is no such element. The code generated for a stand-alone element definition can be found in the class ObjectFactory which is generated along with all the classes derived from your schema's type definitions. So, from any stand-alone element definition that looks like this <xsd:element name="Doc" type="DocType"/> you may expect the generated class ObjectFactory to contain public class ObjectFactory { private final static QName _Doc_QNAME = new QName("", "Doc"); //... public JAXBElement<DocType> createDoc(DocType value) {

return new JAXBElement<DocType>(_Doc_QNAME, DocType.class, null, value); } // ... } (We'll have a closer look at the other methods in this factory class in the section The Object Factory.) Notice that you are not restricted to a single document root element. The following subsections describe the structuring facilities of the XML Schema language for defining element content. 2.2.12.2 Content: An Ordered Set of Elements The schema element xsd:sequence defines that the enclosed set of elements should occur in the given order and according to the specified minimum and maximum repetition counts. (The default for both is 1.) The following complex type defines a set of two coordinates. <xsd:complexType name="PointType"> <xsd:sequence> <xsd:element name="X" type="xsd:int"/> <xsd:element name="Y" type="xsd:int"/> </xsd:sequence> </xsd:complexType> The resulting Java code is straightforward. public class PointType { protected int x; protected int y; public int getX() { return x; } public void setX(int value) { this.x = value; } public int getY() { return y; } public void setY(int value) { this.y = value; } } 2.2.12.3 Content: An Unordered Set of Elements Content consisting of a set of elements that may occur in any order within its parent

XML element can be defined by using the schema element xsd:all. There is, however, a severe restriction: the maxOccurs may not have a value greater than 1. Here is the definition for an XML element describing the courses of a dinner which does not permit repetitions of any course, but you may omit all courses except for the main dish. <xsd:complexType name="DinnerType"> <xsd:all> <xsd:element name="Starter" type="xsd:string" minOccurs="0"/> <xsd:element name="Soup" type="xsd:string" minOccurs="0"/> <xsd:element name="Entree" type="xsd:string"/> <xsd:element name="Dessert" type="xsd:string" minOccurs="0"/> </xsd:all> </xsd:complexType> The generated Java conforms to the structure of a JavaBean: public class LunchType { protected protected protected protected String String String String starter; soup; entree; dessert;

public String getStarter() { return starter; } public void setStarter( String value ) { this.starter = value; } // ...(more getters and setters) } Here, the getters for the optional child elements may return null to distinguish "not present" from any possible value. 2.2.12.4 Content: Alternative Elements The schema element xsd:choice lets you define a type for an XML element which has a content of exactly one element from a given set of alternatives. <xsd:complexType name="CommType"> <xsd:choice> <xsd:element name="SMS" type="xsd:string"/> <xsd:element name="MMS" type="xsd:string"/> <xsd:element name="Email" type="xsd:string"/> </xsd:choice> </xsd:complexType> Although only one out of the three elements will actually be present, the generated Java class provides instance variables and getters and setters for all alternatives.

public class CommType { protected String sms; protected String mms; protected String email; public String getSMS() { return sms; } public void setSMS(String value) { this.sms = value; } // ...(more getters and setters) } Although a handful of unused references isn't all that expensive, a Java class like this just doesn't have a nice feeling about it. Also, using such a class may easily lead to errors that are hard to track down. There is, for instance, nothing in the generated code that will keep you from calling more than one setter. Object oriented languages have no unions because a set of alternative structures is meant to be implemented by a set of subclasses. This topic is discussed in the section Defining Subtypes. 2.2.12.5 Content: A Homogeneous List of Elements To define an element where some sub-element occurs repeatedly, we make use of the optional attributes minOccurs and maxOccurs. Various combinations are possible, permitting the definition of a list that may be empty, may contain any number of elements, or a fixed number. The definition of an unbounded list with at least two elements is given below. (PointType is shown in subsection Content: An Ordered Set of Elements.) <xsd:complexType name="PolygonType"> <xsd:sequence> <xsd:element name="Points" type="PointType" minOccurs="2" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> The resulting Java code does not express the required minimum of two points in a polygon. Here, and for all similar element lists, a java.util.List is used. Therefore the generated code will always be as simple as the one shown below. public class PolygonType { protected List<PointType> points; public List<PointType> getPoints() { if (points == null) {

points = new ArrayList<PointType>(); } return this.points; } } The Javadoc documentation (omitted here) emphasizes that getPoints returns a reference to the actual list while making sure that the list is created. All methods defined in java.util.List may be applied to the returned value.Most importantly, code like this polygon.getPoints().add( new PointType( 4, 9 ) ); adds another point. The list can be added to one by one, or you may use addAll for bulk additions, and you could remove or even clear to delete elements. With all of these possibilities there is just no need for a setter for the entire list. 2.2.12.6 Content: A Mixed List of Elements To define an element type where the element should have a content consisting of a mixed list of elements use the schema element xsd:choice with the attribute maxOccurs="unbounded" or some value greater than 1. (Using xsd:choice as the sole element within a xsd:sequence would result in the same structure definition and, therefore, in the same Java code.) <xsd:complexType name="MixType"> <xsd:choice maxOccurs="unbounded"> <xsd:element name="Text" type="xsd:string"/> <xsd:element name="Number" type="xsd:int"/> <xsd:element name="Point" type="PointType"/> </xsd:choice> </xsd:complexType> The generated Java class has an instance variable for a mixed list of such elements. Obviously, the generic parameter of the List object must refer to some superclass of all the element types. Sometimes only java.lang.Object will do. Other possibilities are java.lang.Serializable, or a user-defined type from which all the types in the choice set have been derived by subclassing. public class MixType { protected List<Object> textOrNumberOrPoint; public List<Object> getTextOrNumberOrPoint() { if (textOrNumberOrPoint == null) { textOrNumberOrPoint = new ArrayList<Object>(); } return this.textOrNumberOrPoint; } } Note well that this technique does not retain an indication of the XML tag in the objects created during unmarshalling as long as the types of the choices are distinct.

You must distinguish individual elements by testing a list element with the instanceof operator, e.g.: for( Object o: mix.getTextOrNumberOrPoint() ){ if( o instanceof String ){ // ... cast o to String and process } else if( o instanceof Integer ){ // ... cast o to Integer and process } else if( o instanceof Point ){ // ... cast o to Point and process } else { throw new IllegalArgumentException( "class " + o.getClass() ); } } It's a good idea to use a third test to guard against the class not being one of the three expected ones. For one thing, the instanceof test avoids the compiler warning. Also, even though a failure of the cast would show that something went wrong, we can produce a more significant error message in the exception we throw in the final else branch. Writing lengthy if statement cascades like this isn't considered to be good object oriented style. The preferred implementation technique is to map element classes to distinct objects created from subclasses of some element handler class hierarchy. Section Using the Element Tree contains a detailed example illustrating this approach. If we add another element of, say, type xsd:string, the schema definition might then look like this: <xsd:complexType name="Mix4Type"> <xsd:choice maxOccurs="unbounded"> <xsd:element name="Text" type="xsd:string"/> <xsd:element name="Number" type="xsd:int"/> <xsd:element name="Point" type="PointType"/> <xsd:element name="Token" type="xsd:string"/> </xsd:choice> </xsd:complexType> Now the JAXB compiler is forced to use an artificial construct of type javax.xml.bind.JAXBElement as a container for each of the elements within MixType. The class Mix4Type reflects this by the generic list type being <JAXBElement<?>>. (Notice that the agglomeation of the list field's name stops, mercifully, after the third sub-element.) public class Mix4Type { protected List<JAXBElement<?>> textOrNumberOrPoint; public List<JAXBElement<?>> getTextOrNumberOrPoint() { if (textOrNumberOrPoint == null) { textOrNumberOrPoint = new ArrayList<JAXBElement<?>>(); }

return this.textOrNumberOrPoint; } } Consequently, a pass through the list would have to be changed as shown below, where the tag and the value are retrieved from the container of type JAXBElement<?>. for( JAXBElement je: mix.getTextOrNumberOrPoint() ){ String tag = je.getName().getLocalPart(); if( "Text".equals( Tag ) ){ String text = (String)je.getValue(); // ... (process) } else if( "Number".equals( Tag ) ){ Integer number = (Integer)je.getValue(); // ... (process) } else if( //... // ... (other alternatives) } } Again, the cascading if statements aren't exactly the bee's knees. See section Using the Element Tree for a better way of dealing with tags to distinguish between elements. 2.2.12.7 Mixed Content Mixed content lets you embed child elements into the value of an element. One example for the natural application of mixed content would be the representation of text, where parts of a paragraph's text value might have some specific property such as boldface or italic. These stretches are best represented as children of the paragraph element. Here is an example written in some simple markup similar to HTML: <P> <B>Mixed content</B> lets you embed <I>child elements</I> into the value of an element. </P> To see how JAXB handles mixed content, we define a schema for our very simple text markup language. We'll have chunks of text that may be used as an entire paragraph as well as part of a paragraph, to be rendered in boldface, in italics or underlined. The complex type ChunkType has its attribute mixed set to true since we'll want to have plain text as well, and an unbounded repetition of choices as child elements. <xsd:complexType name="ChunkType" mixed="true"> <xsd:choice maxOccurs="unbounded"> <xsd:element name="B" type="ChunkType"/> <xsd:element name="I" type="ChunkType"/> <xsd:element name="U" type="ChunkType"/> </xsd:choice> </xsd:complexType>

<xsd:complexType name="TextType"> <xsd:sequence> <xsd:element name="P" type="ChunkType" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> The generated Java code is somewhat opaque, as ChunkType features just one method getContent, apparently the Swiss army knife for slicing a chunk of text. The generic list type now happens to be java.lang.Serializable, which is just another way of saying "(almost) anything goes". public class TextType { protected List<ChunkType> p; public List<ChunkType> getP() { if (p == null) { p = new ArrayList<ChunkType>(); } return this.p; } } public class ChunkType { protected List<Serializable> content; public List<Serializable> getContent() { if (content == null) { content = new ArrayList<Serializable>(); } return this.content; } } The documentation JAXB generates is kind enough to inform us that the elements in the list returned by getContent are either of type String or of type JAXBElement<ChunkType>. As we already know, this is the wrapper class JAXB uses whenever elements have to be distinguished by their tags, and, indeed, we did use ChunkType with B, I and U. Having penetrated this slight obfuscation, we can now write code to process a text as a list of paragraphs. The content list of a text chunk yields plain and decorated chunks in any order. private static void dumpChunk( ChunkType c ){ for( Serializable s: c.getContent() ){ if( s instanceof String ){ System.out.print( (String)s ); } else { String tag = ((JAXBElement)s).getName().getLocalPart(); ChunkType chunk = (ChunkType)((JAXBElement)s).getValue(); System.out.print( "(" + tag + ":" ); dumpChunk( chunk ); System.out.print( ":" + tag + ")" ); }

} } //...(process a text) TextType text = ...; for( ChunkType c: text.getP() ){ dumpChunk( c ); } 2.2.12.8 No Value XML can express the absence of a value in different ways. Let's look at the complex type defined like this: <xsd:complexType name="DemoType"> <xsd:sequence> <xsd:element name="A" type="xsd:string"/> <xsd:element name="B" type="xsd:string" minOccurs="0"/> <xsd:element name="C" type="xsd:string" nillable="true"/> </xsd:sequence> </xsd:complexType> Element <A> must be present, even though its value could be the empty string, the characterless thing. However, using the empty string as an indication for the absence of a value is, in general, not a good idea. A better solution is provided by the definition of element <B>, where its absence can be expressed by simply omitting it from its parent element, in accordance with the attribute minOccurs="0". Yet another possibility is shown with element <C>, which can not be omitted, but its attribute nillable="true" permits the usage of an XML element that doesn't even contain the empty string but uses the attribute xsi:nil, as shown in this valid example for a DemoType element: (The prefix xsi must be bound to http://www.w3.org/2001/XMLSchema-instance.) <demo> <A></A> <!-- no element <B> here --> <C xsi:nil="true"/> </demo> The declarations, and the getters and setters for all three fields are identical. JAXB distinguishes between the three representations by attaching suitable annotations. Although we are going to discuss annotations in more detail later on, we'll have a peek at the crucial ones right now. public class DemoType { @XmlElement(name = "A", required = true) protected String a; @XmlElement(name = "B") protected String b; @XmlElement(name = "C", required = true, nillable = true) protected String c;

public String getA() { return a; } public void setA(String value) { this.a = value; } // ... (more getters and setters like this) } 2.2.13 Defining Subtypes Although object orientation isn't a key feature of XML or the XML Schema language, it's still possible to apply the fundamental OO paradigm when designing a schema: inheritance. This is based on the schema element xsd:extension which lets you add both child elements and attributes to some elsewhere defined type acting as the base type. The example given below presents the components for defining a simple menu (this time it's for a graphical user interface) where menu entries may come in several flavours: simple items, check boxes, radio buttons and sub-menus. <xsd:complexType name="EntryType"> <xsd:attribute name="Text" type="xsd:string"/> </xsd:complexType> <xsd:complexType name="ItemType"> <xsd:complexContent> <xsd:extension base="EntryType"> <xsd:sequence> <xsd:element name="Command" type="xsd:string"/> </xsd:sequence> </xsd:extension> </xsd:complexContent> </xsd:complexType> <xsd:complexType name="CheckBoxType"> <xsd:complexContent> <xsd:extension base="ItemType"> <xsd:attribute name="State" type="xsd:boolean"/> </xsd:extension> </xsd:complexContent> </xsd:complexType> <xsd:complexType name="RadioButtonType"> <xsd:complexContent> <xsd:extension base="ItemType"> <xsd:attribute name="Group" type="xsd:string"/> <xsd:attribute name="State" type="xsd:boolean"/> <xsd:attribute name="Value" type="xsd:string"/> </xsd:extension> </xsd:complexContent> </xsd:complexType> <xsd:complexType name="MenuType">

<xsd:complexContent> <xsd:extension base="EntryType"> <xsd:choice maxOccurs="unbounded"> <xsd:element name="Item" type="ItemType"/> <xsd:element name="CheckBox" type="CheckBoxType"/> <xsd:element name="RadioButton" type="RadioButtonType"/> <xsd:element name="Menu" type="MenuType"/> </xsd:choice> </xsd:extension> </xsd:complexContent> </xsd:complexType> The base class EntryType is extended in several ways: -- ItemType adds a command definition to the base type. -- CheckBoxType extends ItemType, inheriting the command and adding an attribute for the initial state of the check box. -- RadioButtonType is another extension of ItemType, again adding some attributes. Group is the button group's identification, and Value defines the string to be used for indicating the selection. -- MenuType reflects the recursive structure of menus by being both another subclass of ItemType (so that it may represent cascades) as well as a container for all kinds of menu entries, including itself. Before we look at the generated Java code, we should note that the definition of MenuType isn't quite what an OO aficionado would expect. After all the pains taken to establish this little class hierarchy, one still must explicitly put all the subclasses into the choice list. Using just the supertype EntryType in an xsd:sequence would result in very dull menus. The JAXB compiler, however, rewards you with a set of class definitions that uses extends wherever we have xsd:extension in the schema. A look at the (much abbreviated) code shows the expected inheritance structure. public class EntryType { protected String text; // ...(getText, setText) } public class ItemType extends EntryType { protected String command; // ...(getCommand, setCommand) } public class CheckBoxType extends ItemType { protected Boolean state; // ...(isState, setState) } public class RadioButtonType extends ItemType {

protected String group; protected Boolean state; protected String value; // ...(getters and setters) } Finally there is MenuType, which contains a java.util.List<EntryType>. JAXB has briefly reflected upon the element types bunched into the choice and has, literally, reverse engineered the common superclass. A reminder that the list is a mixture is embedded in the name of the getter which is made up from the first three tags. public class MenuType extends EntryType { protected List<EntryType> itemOrCheckBoxOrRadioButton; public List<EntryType> getItemOrCheckBoxOrRadioButton() { if (itemOrCheckBoxOrRadioButton == null) { itemOrCheckBoxOrRadioButton = new ArrayList<EntryType>(); } return this.itemOrCheckBoxOrRadioButton; } } 2.2.14 Substitution Groups A substitution group lets you write schema structures that reference one element but permit the substitution of any other element from the substitution group in an instance document. Below is a simple example, defining a complex type for a binary arithmetic operation. The substitution group is headed by the global operand element, which is referenced from the group members constant and variable. <xsd:complexType name="BinopType"> <xsd:sequence> <xsd:element ref="operand"/> <xsd:element ref="operand"/> </xsd:sequence> <xsd:attribute name="operator" type="xsd:string"/> </xsd:complexType> <xsd:element name="operand" type="xsd:string"/> <xsd:element name="constant" type="xsd:string" substitutionGroup="operand"/> <xsd:element name="variable" type="xsd:string" substitutionGroup="operand"/> <xsd:element name="binop" type="BinopType"/> The benefit of this schema definition is that it permits you to create binop elements consisting of any combination of constant and variable elements. The generated Java code shouldn't surprise you; the field content must act as a portmanteau for all possible operand pairs, and that's why we have to be content with a list. public class BinopType { protected List<JAXBElement<String>> content; protected String operator;

public List<JAXBElement<String>> getContent() { if (content == null) { content = new ArrayList<JAXBElement<String>>(); } return this.content; } public String getOperator() { return operator; } public void setOperator(String value) { this.operator = value; } } Creating an element from a substitution group is slightly more complex now because such elements have to be represented by an object from some parameterized JAXBElement<?> class. This is illustrated in the Java code snippet shown below that demonstrates the assembly of a well-known formula. JAXBContext ctxt = JAXBContext.newInstance( "generated" ); Marshaller m = ctxt.createMarshaller(); m.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, true ); ObjectFactory of = new ObjectFactory(); BinopType bt = of.createBinopType(); bt.setOperator( "*" ); JAXBElement<String> op1 = of.createConstant( "3.14" ); JAXBElement<String> op2 = of.createVariable( "d" ); bt.getContent().add( op1 ); bt.getContent().add( op2 ); JAXBElement<BinopType> jbe = of.createBinop( bt ); m.marshal( jbe, System.out ); And here is the resulting instance document: <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <binop operator="*"> <constant>3.14</constant> <variable>d</variable> </binop> Another example illustrates the usage of a substitution group with complex schema types. The elements of the group may have different types, but they must be derived from the same base type, either by restriction or by extension. A typical scenario would be the use of a base type in the head element and various extensions for the other elements. This is what we have in the example, where ItemType is the base type and BookType and DiskType are the subtypes. A PosType element represents a position in an order. It is defined as containing one element of ItemType. This type, however, is conceptually an abstract type, which should be expressed by the attribute setting abstract="true".

<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"> <xs:annotation> <xs:appinfo> <jaxb:schemaBindings> <jaxb:package name="acme.item"/> </jaxb:schemaBindings> </xs:appinfo> </xs:annotation> <xs:element name="item" type="ItemType"/> <xs:element name="book" type="BookType" substitutionGroup="item"/> <xs:element name="disk" type="DiskType" substitutionGroup="item"/> <xs:complexType name="ItemType" abstract="true"> <xs:sequence> <xs:element name="title" type="xs:string"/> <xs:element name="price" type="xs:int"/> </xs:sequence> </xs:complexType> <xs:complexType name="BookType"> <xs:complexContent> <xs:extension base="ItemType"> <xs:sequence> <xs:element name="pages" type="xs:int"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="DiskType"> <xs:complexContent> <xs:extension base="ItemType"> <xs:sequence> <xs:element name="duration" type="xs:int"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="PosType"> <xs:sequence> <xs:element ref="item"/> <xs:element name="quantity" type="xs:int"/> </xs:sequence> </xs:complexType> <xs:complexType name="OrderType"> <xs:sequence>

<xs:element name="pos" type="PosType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:element name="order" type="OrderType"/> </xs:schema> The interesting sections of the generated code are outlined below. We see the abstract base class ItemType with its extensions for books and disks, and its use as the generic type parameter, where the wildcard ? is suitably restricted to subtypes of ItemType. public abstract class ItemType { protected String title; protected int price; // ... (getters and setters) } public class BookType extends ItemType { protected int pages; // ... (getters and setters) } public class DiskType extends ItemType { protected int duration; // ... (getters and setters) } public class PosType { protected JAXBElement<? extends ItemType> item; protected int quantity; public JAXBElement<? extends ItemType> getItem() { return item; } public void setItem(JAXBElement<? extends ItemType> value) { this.item = ((JAXBElement<? extends ItemType> ) value); } // ... (more getters and setters) } Once again, element construction is a tad more complicated. The ObjectFactory provides create methods for a surprisingly large number of elements. There are methods returning elements of one of the plain types BookType and DiskType. Also, we can create an element by calling a method that returns an object of type JAXBElement, parameterized with BookType or DiskType, each of which requires an argument of the parameter type. And finally there is createItem, returning an object whose type is ItemType. Here is the skeleton of this class:

public class ObjectFactory { public ObjectFactory() { } public BookType createBookType() { ... } public DiskType createDiskType() { ... } public OrderType createOrderType() { ... } public PosType createPosType() { ... } public JAXBElement<OrderType> createOrder(OrderType value) { ... } public JAXBElement<ItemType> createItem(ItemType value) { ... } public JAXBElement<DiskType> createDisk(DiskType value) { ... } public JAXBElement<BookType> createBook(BookType value) { ... } } The table below shows where each of these lements can be used. Method createBookType createDiskType createBook createDisk createItem Result Type BookType DiskType JAXBElement<BookType> JAXBElement<DiskType> JAXBElement<ItemType> Use as argument of createBook() createDisk() PosType.setItem() PosType.setItem() PosType.setItem()

Looking at this table, you may wonder why there are three methods to create an item in a PosType element. Some experimenting exhibits that indeed all three can be used: ObjectFactory of = new ObjectFactory(); // Create an order OrderType st = of.createOrderType(); List<PosType> listPos = st.getPos(); // Order two copies of a book. PosType p1 = of.createPosType(); listPos.add( p1 ); BookType bk = of.createBookType(); bk.setTitle( "The Joy of JAXB" ); bk.setPages( 832 ); bk.setPrice( 120 ); p1.setItem( of.createItem( bk ) ); // createItem for BookType p1.setQuantity( 2 ); // Order a disk. PosType p2 = of.createPosType(); listPos.add( p2 ); DiskType dk = of.createDiskType(); dk.setTitle( "Keyclick Calypso" ); dk.setDuration( 50 ); dk.setPrice( 20 ); p2.setItem( of.createDisk( dk ) ); // createDisk p2.setQuantity( 1 );

JAXBElement<OrderType> jbe = of.createOrder( st ); The marshalled XML text shows that the generic element tag item can indeed be instantiated (even though its schema type ItemType is abstract) but at a price: The actual type of the element has to be specified using the XML instance attribute xsi:type="BookType", along with the lengthy namespace declaration. The subtype element tagged disk does not require this burden as its tag is unambiguous. <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <order> <pos> <item xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="BookType"> <title>Inside JAXB</title> <price>120</price> <pages>832</pages> </item> <quantity>2</quantity> </pos> <pos> <disk> <title>Keyclick Calypso</title> <price>20</price> <duration>50</duration> </disk> <quantity>1</quantity> </pos> </order> Unmarshalling requires an additional call to get at the value wrapped in a JAXBElement<? extends ItemType>, but common subelements can be accessed via calls of ItemType methods. JAXBElement<?> jbe = (JAXBElement<?>)u.unmarshal( new FileInputStream( "order.xml" ) ); OrderType order = (OrderType)jbe.getValue(); for( PosType p: order.getPos() ){ ItemType item = p.getItem().getValue(); String tag = p.getItem().getName().getLocalPart(); System.out.println( item.getClass().getSimpleName() ); System.out.println( tag + " " + item.getTitle() + " " + p.getQuantity() ); } In addition to using the standard Java technique for determining an object's class we can also extract the tag by calling method getName() on the JAXBElement containing the ItemType object. The tag is represented as an object of class javax.xml.namespace.QName which contains the simple name as well as the namespace prefix. In spite of the restrictions and the slightly more complex element construction, substitution groups are an adequate technique for representing object hierarchies.

2.2.15 Referring to Another XML Element Among the data types of the XML Schema language there is an inseparable pair of types operating complementary to each other: xsd:ID and xsd:IDREF. They let you represent references to XML elements. This can be put to good use in several circumstances, i.e., whenever you need linkage in addition to the natural parent-tochild relationship. Our first example uses references for factoring out frequently occuring elements. Below is a schema snippet defining XML elements dealing with airports and flights, which are scheduled from one airport to another one. A naive schema definition would simply have two AirportType sub-elements for each flight: <xsd:complexType name="AirportType"> <xsd:attribute name="LocId" type="xsd:string" use="required"/> <xsd:attribute name="Name" type="xsd:string" use="required"/> </xsd:complexType> <xsd:complexType name="FlightType"> <xsd:all> <xsd:element name="From" type="AirportType"/> <xsd:element name="To" type="AirportType"/> <xsd:element name="Carrier" type="xsd:string"/> <xsd:element name="DepTime" type="xsd:time"/> <xsd:element name="ArrTime" type="xsd:time"/> </xsd:all> <xsd:attribute name="Number" type="xsd:int" use="required"/> </xsd:complexType> Instead of copying an element of class AirportType (biggish, aren't they) into all places where it is used, we'll now change our schema to employ element linkage. An AirportType element is presented only once, in full, and a reference is inserted for the From and To sub-elements of FlightType where the original element was. Our document type should be defined along the lines of TimetableType, bundling the actual AirportType elements and the list of flights. <xsd:complexType name="AirportType"> <xsd:attribute name="LocId" type="xsd:ID" use="required"/> <xsd:attribute name="Name" type="xsd:string" use="required"/> </xsd:complexType> <xsd:complexType name="FlightType"> <xsd:all> <xsd:element name="From" type="xsd:IDREF"/> <xsd:element name="To" type="xsd:IDREF"/> <xsd:element name="Carrier" type="xsd:string"/> <xsd:element name="DepTime" type="xsd:time"/> <xsd:element name="ArrTime" type="xsd:time"/> </xsd:all> <xsd:attribute name="Number" type="xsd:int" use="required"/> </xsd:complexType> <xsd:complexType name="TimetableType">

<xsd:sequence> <xsd:element name="Airports" type="AirportType" maxOccurs="unbounded"/> <xsd:element name="Flight" type="FlightType" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> The only change required within AirportType is the definition of the attribute Id as xsd:ID, and FlightType has xsd:IDREF as the type for From and To. We'll continue to use the IATA Location Identifier, which we would have used as an airport identification anyway, as the string implementing the XML link. (If there is no attribute that could serve as an identification right away, it may very well be possible to compose one from the element's other attributes. Otherwise you'll just have to use some synthetic key.) The resulting Java code for AirportType has the usual JavaBean layout. More interesting is the code for the class FlightType: public class FlightType { protected protected protected protected protected protected Object from; Object to; String carrier; XMLGregorianCalendar depTime; XMLGregorianCalendar arrTime; int number;

public Object getFrom() { return from; } public void setFrom(Object value) { this.from = value; } public Object getTo() { return to; } public void setTo(Object value) { this.to = value; } // ...(more getters and setters) } The elements From and To are now represented as Object references. So, to retrieve the origin of some flight, all you'll have to code is (AirportType)flight.getFrom() The destination's IATA Location Identifier is obtained by ((AirportType)flight.getTo()).getLocId() Don't blame JAXB for not making the From and To sub-elements AirportType

references. The XML type xsd:ID is a universal reference type, and xsd:IDREF is the union of all reference values. Nevertheless, unmarshalling will automatically create FlightType objects that are actually linked to their airports, saving you the hassle of establishing this linkage yourself. Notice that by dropping the necessity to have a full-blown XML element for From and To, we could now define this value pair as a couple of attributes. Keep in mind that XML requires the values of xsd:ID (or, same thing, the ones of xsd:IDREF) to be unique across all of your XML document. As soon as we begin to think about adding bookings to our XML data, flight identifiers would have to make their appearance as another class of values for xsd:ID. There is a good chance that location identifiers and flight identifiers (a concatenation of the carrier id and some number) don't clash, but you'd better research this thoroughly before you commit yourself. Another excellent reason for using references is the representation of linked data structures such as trees, lists or, in general, graphs. The example given below is for railway buffs. It demonstrates how a track layout can be represented by linking elements such as sets of points (or switches) and tracks to each other, creating the graph that represents the topology of a shunting yard. (Signals are omitted for brevity's sake.) <xsd:simpleType name="GroupType"> <xsd:restriction base="xsd:string"> <xsd:enumeration value="SWITCH"/> <xsd:enumeration value="TRACK"/> </xsd:restriction> </xsd:simpleType> <xsd:complexType name="ElementType"> <xsd:attribute name="Id" type="xsd:ID" use="required"/> <xsd:attribute name="Group" type="GroupType" use="required"/> <xsd:attribute name="Number" type="xsd:int" use="required"/> <xsd:attribute name="Name" type="xsd:string" use="optional" default=""/> </xsd:complexType> <xsd:complexType name="PointLeftRightType"> <xsd:complexContent> <xsd:extension base="ElementType"> <xsd:attribute name="point" type="xsd:IDREF"/> <xsd:attribute name="left" type="xsd:IDREF"/> <xsd:attribute name="right" type="xsd:IDREF"/> </xsd:extension> </xsd:complexContent> </xsd:complexType> <xsd:complexType name="EastWestType"> <xsd:complexContent> <xsd:extension base="ElementType"> <xsd:attribute name="east" type="xsd:IDREF"/> <xsd:attribute name="west" type="xsd:IDREF"/> </xsd:extension>

</xsd:complexContent> </xsd:complexType> <xsd:complexType name="ShuntingYardType"> <xsd:choice maxOccurs="unbounded"> <xsd:element name="Switch" type="PointLeftRightType"/> <xsd:element name="Track" type="EastWestType"/> </xsd:choice> </xsd:complexType> From the generated classes, we select EastWestType for a closer inspection. Again, there is Object as the type used in the getters and setters for the attributes linking to the neighbours. public class EastWestType extends ElementType { protected Object east; protected Object west; public Object getEast() { return east; } public void setEast(Object value) { this.east = value; } public Object getWest() { return west; } public void setWest(Object value) { this.west = value; } } But wait - what do we do with dead-end tracks? Or with tracks that lead out of the shunting yard, i.e., line tracks? We'll need some sort of replacement for Java's null. Simply using "null" or "" as an IDREF value will cause problems as soon as the XML is validated, because, by definition, there must be some element where that string is an id value. One solution would be to define all the link attributes as optional, but this makes it difficult to discriminate an inadvertently dropped element from an intentionally omitted one. One solution that avoids this ambiguity is to use a single artificial element, perhaps in a category of its own, as the "null" element. We extend ShuntingYardType accordingly: <xsd:complexType name="NullType"> <xsd:attribute name="Id" type="xsd:ID" use="required"/> </xsd:complexType> <xsd:complexType name="ShuntingYardType"> <xsd:choice maxOccurs="unbounded"> <xsd:element name="Switch" type="PointLeftRightType"/> <xsd:element name="Track" type="EastWestType"/> <xsd:element name="Null" type="NullType"/> </xsd:choice>

</xsd:complexType> This will give you a class NullType, and one element of that type with an arbitrary Id value - perhaps Id="null" - provides a null element that is comfortably distinguishable from all the actual trackside equipment by class as well as by its Id value. Here is the Java code JAXB generates for it: public class NullType extends ElementType { } No, this is no typesetting accident: this class is indeed empty because it doesn't need any additions to its base class. Its name is distinction enough. In the XML file you would have one extra element, e.g., the Null element as shown below. <Track Id="TRACK_168" Group="TRACK" Number="168" Name="b101" east="SWITCH_42" west="null"/> <Null Id="null" Group="NULL" Number="0"/> The generic element attributes Group and Number could be set to arbitrary values, but we might just as well use some null values there, too. 2.2.16 Elements With Any Type 2.2.16.1 DOM Elements The XML Schema language provides xsd:anyType which is the equivalent of java.lang.Object, i.e., it can be envisaged as the base type from which all simple and complex types are derived. To see how this is handled in JAXB, we define the complex type BagType which is nothing but a wrapper for any content. <xsd:complexType name="BagType"> <xsd:sequence> <xsd:element name="Content" type="xsd:anyType"/> </xsd:sequence> </xsd:complexType> The class that is generated by JAXB shouldn't come as a surprise: public class BagType { protected Object content; public Object getContent() { return content; } public void setContent(Object value) { this.content = value; } } But what will be the class of the Content - if not java.lang.Object (which would be

obtuse), then what? Well, the actual class doesn't really matter - the important thing is that it implements org.w3c.dom.Element, which is a subinterface of org.w3c.dom.Node. This means that, if you really have to, you can leave the cushy and plushy JAXB environment and continue with traditional DOM processing methods, e.g.: Element content = (Element)bag.getContent(); String tag = content.getTagName(); Node<List> = content.getChildNodes(); // ...more DOM accesses... If you need to marshal arbitrary content you'll have to create a content tree according to org.w3c.dom. Sun's JAXB currently uses the implementation from Apache's Xerces, i.e., class apache.xerces.internal.dom.ElementNSImpl. 2.2.16.2 Another Content Tree as Element It's also possible to insert an arbitrary content tree as an element. We'll assume that we have several document definitions, like this: <xsd:complexType name="HearsayType"> <xsd:sequence> <xsd:element name="text" type="xsd:string"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="GrapevineType"> <xsd:sequence> <xsd:element name="text" type="xsd:string"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="RumourType"> <xsd:sequence> <xsd:element name="text" type="xsd:string"/> </xsd:sequence> </xsd:complexType> We want any of these nice documents to be envelopped by a container document: <xsd:complexType name="CommType"> <xsd:sequence> <xsd:element name="source" type="xsd:string"/> <xsd:element name="comm" type="xsd:anyType"/> </xsd:sequence> </xsd:complexType> There is no surprise in the classes generated by the JAXB compiler. (The comm subelement of CommType has the type java.lang.Object.) So we can write some code to marshal such an XML communication. ObjectFactory of = new ObjectFactory();

// Create the container object. CommType comm = of.createCommType(); comm.setSource( "Ms Jones" ); // Let's have some hearsay. HearsayType hearsay = of.createHearsayType(); hearsay.setText( "Mr. Harper does naughty things." ); comm.setComm( hearsay ); // Prepare a JAXBElement, ready for marshalling. QName qn = new QName( "comm" ); JAXBElement<CommType> je = new JAXBElement<CommType>( qn, CommType.class, comm ); The JAXBElement is now ready to be passed to a Marshaller. The resulting XML text looks like this: <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <comm> <source>Ms Jones</source> <comm xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="HearsayType"> <text>Mr. Harper does naughty things.</text> </comm> </comm> It should be satsifying to note that JAXB has annotated the comm element with xsi:type="HearsayType" which is going to help a lot during the inverse process. In fact, all you have to do to get this document unmarshalled into a content tree and to access the nested contents is this: File f = new File( ... ); JAXBElement<CommType> je = (JAXBElement<CommType>)u.unmarshal( f ); CommType comm = (CommType)je.getValue(); if( comm.getComm() instanceof HearsayType ){ HearsayType hearsay = (HearsayType)comm.getComm(); } else { // ...(investigate other possibilities)... } 2.2.17 Image Data An element containing a JPEG image has an XML schema definition like this: <?xml version="1.0"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://example.com/know-type" xmlns:xmime="http://www.w3.org/2005/05/xmlmime" targetNamespace="http://example.com/know-type"> <xs:import namespace="http://www.w3.org/2005/05/xmlmime" schemaLocation="http://www.w3.org/2005/05/xmlmime"/>

<xs:complexType name="ItemType"> <xs:sequence> <xs:element name="JPEGPicture" type="xs:base64Binary" xmime:expectedContentTypes="image/jpeg"/> </xs:sequence> </xs:complexType> <xs:element name="Picture" type="ItemType"/> </xs:schema> The <xs:import> element is not required; JAXB appears to "know" about this namespace. The schema type xs:base64binary is the type best suited for representing image data. To create XML content and to marshal an instance document containing an image you can write code to create an object of type Image and set its reference in the appropriate element of the content tree: BufferedImage bimg = ImageIO.read( imgFile ); Image img = bimg.getScaledInstance( 512, -1, Image.SCALE_DEFAULT ); // Create the Item element and store the image reference ItemType itemEl = of.createItemType(); itemEl.setJPEGPicture( img ); JAXBElement<ItemType> jbe = of.createPicture( itemEl ); Unmarshalling is just as simple. You extract the Image object from its parent element and call Graphics.drawImage() with this object as the first argument. // Get the image from the content tree. JAXBElement<ItemType> jbe = ...; Image img = jbe.getValue().getJPEGPicture(); // Draw it Graphics g = ...; g.drawImage( img, 0, 0, null ); Well, and here she is: <<<picture deleted>>> 2.3 Hints on Writing XML Schemas 2.3.1 Don't Use Anonymous Types The XML Schema language lets you define XML types anonymously. But when you're using JAXB to generate Java classes, it's preferable to define all schema types explicitly. For one thing, this means that you will be able to re-use the type within your schema. More importantly, the resulting Java class will be given the name defined in the schema rather than a name selected by JAXB. Moreover, anonymous types result in some inner class. Consider the following XML schema snippet: <xsd:complexType name="PurchaseOrderType"> <xsd:sequence>

<xsd:element name="shipTo" type="AddressType"/> <xsd:element name="billTo" type="AddressType"/> <xsd:element name="item" minOccurs="0" maxOccurs="unbounded"> <xsd:complexType> <xsd:sequence> <xsd:element name="productName" type="xsd:string"/> <xsd:element name="quantity" type="xsd:positiveInteger"/> <xsd:element name="price" type="xsd:decimal"/> </xsd:sequence> <xsd:attribute name="partNum" type="xsd:string" use="required"/> </xsd:complexType> </xsd:element> </xsd:sequence> <xsd:attribute name="orderDate" type="xsd:date"/> </xsd:complexType> The relevant parts of the generated class PurchaseOrderType are presented below. Note that PurchaseOrderType.Item is the somewhat unwieldy name of the class for an order item as it results from an inlined schema type. public class PurchaseOrderType { protected AddressType shipTo; protected AddressType billTo; protected List<PurchaseOrderType.Item> item; protected XMLGregorianCalendar orderDate; // ...(getters and setters) public List<PurchaseOrderType.Item> getItem() { if (item == null) { item = new ArrayList<PurchaseOrderType.Item>(); } return this.item; } public static class Item { protected String productName; protected BigInteger quantity; protected BigDecimal price; protected String partNum; // ...(getters and setters) } 2.3.2 Common Schema Definitions Different document types (within one project) require different schemas. If the documents share common XML types, they should be written once, in a separate schema file, and re-used from there wherever they are required. The common definitions could be assembled into a namespace of their own, to avoid any conflicts with type or element names in the schemas where they are used. The XML schema snippets given below illustrate this approach.

<?xml version="1.0" encoding="utf-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://astronomy.org/common" xmlns:ast="http://astronomy.org/common"> <xsd:complexType name="BodyType"> </xsd:sequence> <xsd:element name="name" type="xsd:ID"> <xsd:element name="mass" type="xsd:float"> <xsd:element name="radius" type="xsd:float"> </xsd:sequence> </xsd:complexType> </xsd:schema> The definitions from this schema can be used by importing the schema file, e.g.: <?xml version="1.0" encoding="utf-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ast="http://astronomy.org/common" targetNamespace="http://astronomy.org/solarsystem" xmlns:ss="http://astronomy.org/solarsystem"> <xsd:import namespace="http://astronomy.org/common" schemaLocation="common.xsd"/> <xsd:complexType name="MoonType"> <xsd:extension base="ast:BodyType"> </xsd:sequence> <xsd:element name="planet" type="xsd:IDREF"> </xsd:sequence> </xsd:complexType> <xsd:complexType name="PlanetType"> <xsd:extension base="ast:BodyType"> </xsd:sequence> <xsd:element name="moon" type="ss:MoonType" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> </xsd:schema> The schema compiler derives the package names from the URIs given in the namespace definitions, resulting in org.astronomy.common and org.astronomy.solarsystem. It should also be noted that it is not necessary to have one schema file for each document type. Any top-level element definition (by some xsd:element schema element) is a candidate for a root element, and you may have as many as you like within a single schema. The previous schema snippet might be extended with the following element definitions: <xsd:schema ...> ...

<xsd:element name="planet" type="ss:PlanetType"/> <xsd:element name="solarSystem"> <xsd:complexType> <xsd:sequence> <xsd:element name="planet" type="ss:PlanetType" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema> Marshalling either element is possible with a marshaller created from the context based on the package org.astronomy.solarsystem. Marshaller m = context.createMarshaller(); ObjectFactory of = new ObjectFactory(); // Create a single planet instance document. PlanetType planet = of.createPlanetType(); //... Add attributes and moons JAXBElement<PlanetType> jbe = of.createPlanet( planet ); m.marshal( jbe, System.out ); // Create a solar system. SolarSystem sol = of.createSolarSystem(); //... Add planets. m.marshal( sol, System.out ); 2.3.3 A Note on Groups The XML Schema language provides the constructs xs:group and xs:attributeGroup. They let you put a name to a structured group of elements or attributes, respectively. To insert the elements or attributes in some other place, use the attribute ref="..." specifying the group's given name. This feature is useful if your elements have common subsets of elements or attributes, but it does not affect the Java code generated by JAXB's schema compiler xjc. This may be regretted, since groups or group combinations might provide a basis for adding interface definitions to the generated set of classes. 2.3.4 Conserving Compatibility One of the advantages of XML is that data may be omitted wherever a default is acceptable. If an XML schema is extended, you have the option of making existing XML files compatible with the new version, e.g., by defining new attributes with use="optional" and providing a default. 2.3.5 Spurious Classes It's not necessary to define a separate type for a list resulting from a maxOccurs="unbounded" attribute attached to some element if this element occurs in an xsd:sequence group. Given the complex type ItemType, it is possible to define

another type, say ItemListType, as a list of items. <xsd:complexType name="ItemType"> <xsd:sequence> ... </xsd:sequence> </xsd:complexType> <xsd:complexType name="ItemListType"> <xsd:sequence> <xsd:element name="Items" type="ItemType" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> Within some other type definition it is equally possible to use either ItemListType, or ItemType with the attribute maxOccurs="unbounded": <xsd:complexType name="WrapItemType"> <xsd:sequence> <xsd:element name="Items" type="ItemType" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="WrapItemListType"> <xsd:sequence> <xsd:element name="ItemList" type="ItemListType"/> </xsd:sequence> </xsd:complexType> The code for WrapItemType contains a list of ItemType objects, providing immediate access to the list: public class WrapItemType { protected List<ItemType> items; public List<ItemType> getItems() { if (items == null) { items = new ArrayList<ItemType>(); } return this.items; } } With the additional type definition in the schema you get an additional Java class. public class ItemListType { protected List<ItemType> items; public List<ItemType> getItems() { if (item == null) { item = new ArrayList<ItemType>(); }

return this.item; } } public class WrapItemListType { protected ItemListType itemList; public ItemListType getItemList() { return itemList; } public void setItemList(ItemListType value) { this.itemList = value; } } The additional class layer requires an additional getter call to retrieve an item, e.g., a.getItemList().getItems(). We note that the XML text is verboser, too. The additional type and class requires an additional tag, bracketing the list. <A> <ItemList> <Item>...</Item> <Item>...</Item> ... </ItemList> </A> This isn't required in the simpler variant: <B> <Item>...</Item> <Item>...</Item> ... </B> Notice, however, that having the <ItemList> element in place has some advantages, too. For one thing, even an empty list of items appears visibly, and may evoke some processing triggered by the empty wrapper element. Also, it is now possible to insert a complete item list in one fell swoop into the parent element, since now there is a setItemList setter. This may help when one object tree is assembled from another one. 2.3.6 Avoid Unnecessary JAXBElement<?> Try to avoid JAXBElement<?> as type of list elements. JAXB has to use this auxiliary type for elements if you have a complex element that contains a sequence consisting of elements with different tags but identical types. But you can always create distinct subtypes for each tag, even if the extension does not add anything. This means that, at the price of a few additional empty type definitions in your schema, you can avoid the bother resulting from distiguishing elements retrieved from a list not only by their class but also by their tag.

3 Unmarshalling and Using the Data 3.1 Unmarshalling A simple approach for unmarshalling an XML document consists of the creation of a JAXB context and the call to unmarshal the document. A JAXBContext object provides the entry point to the JAXB API and maintains the binding information between XML and Java. One way of creating a context instance is by calling the static method newInstance with a list of colon separated names of the packages containing the JAXB schema-derived classes. From this context, an Unmarshaller object is obtained, which functions as the driver for processing an XML text to create the equivalent set of Java objects. It offers several unmarshal methods, accepting a wide range of object types as the source for XML text data. The method shown below illustrates this with a single package containing the class of the type defining the top level element of the XML document. public <T> T unmarshal( Class<T> docClass, InputStream inputStream ) throws JAXBException { String packageName = docClass.getPackage().getName(); JAXBContext jc = JAXBContext.newInstance( packageName ); Unmarshaller u = jc.createUnmarshaller(); JAXBElement<T> doc = (JAXBElement<T>)u.unmarshal( inputStream ); return doc.getValue(); } The return value of the call to JAXB's unmarshal is a representation of the root node of the parsed XML document in an instance of JAXBElement<T>. If we're not interested in the tag of the root element we might just as well return the extracted content value. 3.2 Using the Element Tree The javadoc contained within the classes generated from an XML schema documents all the getters for accessing an XML element's attributes and child elements. A good approach is to implement a set of handler classes, one for each schema element type. Its handle method retrieves attributes and child elements, for which it invokes the handle method in turn. This corresponds to a depth-first traversal of the document tree.The example assumes that there is a simple set of schema types: <xsd:complexType name="PersonType"> <xsd:sequence> <xsd:element name="Name" type="NameType"> <xsd:element name="Addr" type="AddrType" minOccurs="0"> <xsd:element name="Child" type="ChildType" minOccurs="0" maxOccurs="unbounded"> </xsd:sequence> <xsd:attribute name="resident" type="xsd:boolean"/> </xsd:complexType> <xsd:complexType name="ChildType"> <xsd:complexContent> <xsd:extension base="PersonType"/>

</xsd:complexContent> </xsd:complexType> Below is the essential Java code for a handler class hierachy. Note that delegation to some handler for a sub-element or attribute depends on the item having a specific class. abstract class Handler { protected static Map<Class<?>,Handler> ourClass2Conv = new HashMap<Class<?>,Handler>(); static { ourClass2Conv.put( ourClass2Conv.put( ourClass2Conv.put( ourClass2Conv.put( //... }

PersonType.class, new PersonHandler() ); NameType.class, new NameHandler() ); AddrType.class, new AddrHandler() ); ChildType.class, new ChildHandler() );

public abstract void handle( Object o ); protected void process( Object obj ){ if( obj != null ){ Handler h = ourClass2Conv.get( obj.getClass() ); if( h != null ){ h.handle( obj ); } } } protected <T> void processList( List<T> list ){ for( T obj: list ){ Handler h = this.getHandler( obj ); h.process( obj ); } } } class PersonHandler extends Handler { public void handle( Object o ){ PersonType p = (PersonType)o; process( p.getName() ); if( p.isResident() ){ process( p.getAddr() ); } processList( p.getChild ); } } Not all subclasses of Handler will be quite so simple. There is one noteworthy complication that arises if subordinate elements have to be distinguished by their tag. Let's assume a small change in the definition of PersonType.

<xsd:complexType name="PersonType"> <xsd:sequence> <xsd:element name="Name" type="xsd:string"/> <xsd:element name="Addr" type="xsd:string" minOccurs="0"/> <xsd:choice minOccurs="0" maxOccurs="unbounded"> <xsd:element name="Boy" type="ChildType"/> <xsd:element name="Girl" type="ChildType"/> </xsd:choice> </xsd:sequence> <xsd:attribute name="resident" type="xsd:boolean"/> </xsd:complexType> To get at a person's children, we now have (in class PersonType) a method getBoyOrGirl(), that returns a List<JAXBElement<ChildType>>. All we have to do is a slight extension of the generic method processList, to access the JAXBElement object and continue to use its value attribute instead of the object obtained from the list. protected <T> void processList( List<T> list ){ for( T obj: list ){ if( obj instanceof JAXBElement ){ obj = ((JAXBElement<?>)obj).getValue(); } Handler h = this.getHandler( obj ); h.process( obj ); } } Finally, if the tag is required for processing as well, the methods process and handle would have to be extended by an additional String parameter. The value is obtained by a call of the JAXBElement method getName(). An additional lookup table mapping tag names to handlers might be required as well. This is best put into the handler class hosting the list. Don't make such a map global, because XML tags need not be unique across the various element types. 3.3 Validation A considerable part of the XML Schema language deals with facets, enabling the programmer to restrict the basic datatypes. We have seen that the JAXB compiler doesn't care much about these facets as it just translates the basic datatype into one of Java's built-in types. A meticulous interpretation of these facets for checking that the XML data meets the constraints must be done during a schema validation. If you want to validate your document before it is unmarshalled, JAXB lets you request validation by passing an object of the class javax.xml.validation.Schema to the Unmarshaller object. First, you create this schema object by setting up a schema factory for the schema language of your choice. Then you create the Schema object by calling the factory's method newSchema: Schema mySchema; SchemaFactory sf = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI ); try {

mySchema = sf.newSchema( file ); } catch( SAXException saxe ){ // ...(error handling) mySchema = null; } After the Unmarshaller object has been established, you pass it the schema. JAXBContext jc = JAXBContext.newInstance( packagePath ); Unmarshaller u = jc.createUnmarshaller(); u.setSchema( mySchema ); Basically that's all there is to it. If the XML data validation fails, an UnmarshalException (from javax.xml.bind) is thrown. Make sure to let the user of your program see the exception message so that the problem can be fixed. If you'd like to create your own error messages, you can pass a ValidationEventCollector to the unmarshaller which will store validation events into it so that you can retrieve an event and query its individual attributes. Insert these lines before you call the unmarshal method: ValidationEventCollector vec = new ValidationEventCollector(); u.setEventHandler( vec ); The best place for checking the event collector is in the finally phrase of the try statement wrapping all of this: if( vec != null && vec.hasEvents() ){ for( ValidationEvent ve: vec.getEvents() ){ String msg = ve.getMessage(); ValidationEventLocator vel = ve.getLocator(); int line = vel.getLineNumber(); int column = vel.getColumnNumber(); System.err.println( origin + ": " + line + "." + column + ": " + msg ); } } Now this looks as if the validation process would be kind enough to present you with all the errors in your XML document, or at least as many as possible but, alas, it appears that the validation process throws an exception as soon as the first deviation is detected. If you want to continue as long as possible, you'll have to catch all errors with a ValidationEventHandler, as explained in the next section. 3.4 Validation Event Handling The interface javax.xml.bind.ValidationEventHandler is quite simple. Implementing classes must provide a single method to catch a ValidationEvent as we've seen it in the previous section. boolean handleEvent( ValidationEvent event ) To register, the Unmarshaller method setEventHandler is called. If the calling object is implementing the event handler interface, we might write:

Unmarshaller u = jc.createUnmarshaller(); u.setEventHandler( this ); 3.5 The JAXB Context As we have seen, earlier in this chapter, an object of the class JAXBContext must be constructed as a starting point for other operations. One way is to create a context from a colon separated list of packages. JAXBContext ctxt = JAXBContext.newInstance( "some foo:more.bar" ); Each package must contain its own class ObjectFactory or a file named jaxb.index. An ObjectFactory class is generated by the XML schema compiler, and therefore this form of newInstance is usually used in connection with schema derived classes. For JAXB annotated Java code, you may use the package path form as well, either with a hand-written ObjectFactory class or with a jaxb.index resource file containing a list of the class names to be considered by JAXB. This file simply lists the class names relative to the package where it occurs, e.g.: # package some.foo # class some.foo.Foo Foo # inner class some.foo.Foo.Boo Foo.Boo An alternative form of the newInstance method lists all classes that the new context should recognize. JAXBContext ctxt = JAXBContext.newInstance( Foo.class, Bar.class ); Usually, the top level classes are sufficient since JAXB will follow, recursively, all static references, such as the types of instance variables. Subclasses, however, are not included. (But see the section Class Inclusion: XmlSeeAlso about the annotation XmlSeeAlso, which provides a way of extending the closure of recognized classes.) If packages or classes are associated with namespaces, the packages or classes associated with a JAXB context also determine the namespace declarations written as attributes into the top-level element of the generated XML document.

4 Building and Marshalling an XML Document 4.1 The Object Factory Usually hidden in the middle of the list of the classes derived from the types defined in an XML schema there will be one class called ObjectFactory. It's convenient to use the methods of this class because they provide an easy way of creating elements that have to be represented by a JAXBElement<?> object. Given that the top-level element of a document is represented as a JAXBElement<RulebaseType> with the tag "rulebase", one such doument object can be created by code as shown below. ObjectFactory objFact = new ObjectFactory(); RulebaseType rulebase = objFact.createRulebaseType(); JAXBElement<RulebaseType> doc = objFact.createRulebase( rulebase ); A simple element that does not require a JAXBElement<?> wrapper is created by a straightforward method call. ModuleType module = objFact.createModuleType(); A JAXBElement<?> is also required for element sequences containing elements of the same type but with differing tags. Here is a schema snippet: <xsd:complexType name="FooBarListType"> <xsd:sequence> <xsd:choice minOccurs="0" maxOccurs="unbounded"> <xsd:element name="foo" type="FooBarType"/> <xsd:element name="bar" type="FooBarType"/> </xsd:choice> </xsd:sequence> </xsd:complexType> The ObjectFactory would now contain several methods for creating a FooBarListType and its offsprings. A possible sequence of calls is shown in the Java code below. FooBarListType fblElem = objFact.createFooBarListType(); List<JAXBElement<FooBarType>> fbList = fblElem.getFooOrBar(); // create a "foo" element FooBarType foo = objFact.createFooBarType(); // ...(add attributes and components to foo) // Create the element <foo>...</foo> JAXBElement<FooBarType> fooElem = objFact.createFooBarTypeFoo( foo ); // Add it to its parent's list. fbList.add( fooElem ); // create a "bar" element FooBarType bar = objFact.createFooBarType(); // ...(add attributes and components to bar) // Create the element <bar>...</bar> JAXBElement<FooBarType> barElem = objFact.createFooBarTypeBar( bar ); // Add it to its parent's list. fbList.add( barElem );

You may avoid these complications by subtyping FooBarType into identical types FooType and BarType. 4.2 Assembling Document Tree Nodes Neither the methods of the element object factory nor the constructors of the classes derived from the types defined in the XML schema require that you have any of an element's child elements or attributes at the time of the call. (The single exception is the set of factory methods creating a JAXBElement<?>, but their arguments may be "empty" element objects, without any actual XML content.) This gives you maximum freedom to design your tree-building algorithm. Usually it will be the structure of the input material that advocates some specific approach. Building the document tree from comparable hierarchical structures is the easiest way, as you can create, insert and fill the elements as you traverse the existing structure. Sequential orderings that correspond to one of the basic tree traversal orders can be handled with elementary techniques. If, for instance, the data is in post-order, you might use a stack to keep assembled XML elements until their parent element becomes eligible for construction. If the data isn't arranged in one of the tree traversal orders you could set up two or more "cursors" that point into the emerging tree so that you might add to several places in parallel. The frequently used construction method that proceeds from the tree root towards the leaves may be written according to two typical scenarios for the construction of an element. We'll illustrate these with a skeleton layout for a product order. <xsd:complexType name="CustomerType"> <xsd:sequence> <xsd:element name="id" type="xsd:int"/> <xsd:element name="name" type="xsd:string"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="ItemType"> <xsd:sequence> <xsd:element name="id" type="xsd:string"/> <xsd:element name="quantity" type="xsd:int"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="OrderType"> <xsd:sequence> <xsd:element name="customer" type="CustomerType"/> <xsd:element name="items" type="ItemType" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> <xsd:element name="folder"> <xsd:complexType> <xsd:sequence> <xsd:element name="orders" </xsd:sequence> </xsd:complexType>

type="OrderType" maxOccurs="unbounded"/>

</xsd:element> Assuming that we are about to add the content for a "current" element, the sequence for adding a solitary subordinate element of type X goes like this: Create the subordinate element xElem via a call to factory method createX. Add this object to the current element, with a setter call current.setX( xElem ). Make the new element the current element and repeat this process recursively for the new element's offsprings. This is, of course, simply to be repeated for other child elements. If the subordinate element occurs repeatedly, we extend this algorithmic outline somewhat: Create the subordinate element xElem via a call to factory method createX. Obtain the reference to the subordinate List<X>, with a call to the getter current.getX(). For each subordinate element: Create it using the factory method createX. Append (add) it to the List<X>. Make the new element the current element and repeat this process recursively for the new element's offsprings. It may be a good strategy to insert a newly created element immediately after its creation. It reduces the risk that this essential operation is left out. You should now have no problems understanding the Java code that creates an order element according to the previously given schema snippet. // Data for an order int custId = ...; String custName = ...; Item[] items = ...; // Create order and insert in top-level document, a list of orders OrderType orderElem = objFact.createOrderType(); folder.getOrders().add( orderElem ); // Create and insert the customer element. CustomerType custElem = objFact.createCustomerType(); orderElem.setCustomer( custElem ); // Complete customer. custElem.setId( custId ); custElem.setName( custName ); // Create and add item elements. List<ItemType> itemList = orderElem.getItems(); for( Item item: items ){ ItemType itemElem = objFact.createItemType(); itemList.add( itemElem ); itemElem.setId( item.id ); itemElem.setQuantity( item.qtty ); }

Another thing that can be gleaned from these lines is the danger of confusion. On the one hand, we have the classes representing XML elements, and, on the other hand, the data for the XML document is likely to be around in a more or less similar set of objects, and their classes are bound to have names that aren't entirely different from the ones coming from the schema. (In the example there is ItemType and Item.) The counter-strategy to adopt here is to enforce a rigid naming convention which should not only deal with class names but also include naming rules for the temporary variables referencing objects of classes from either group. 4.3 Assembling Data with Links (ID, IDREF) 4.3.1 One Element per Identification It is not unusual that the data that is to be represented as XML contains elements repeatedly that are either identical or equal. You may, of course, decide to emit each of these occurrences in full, but this has obvious disadvantages: It increases the volume of the XML text. There will be duplicated objects when the unmarshalled data is transferred into application objects. The XML Schema language provides the schema data types xsd:ID and xsd:IDREF, which we've already discussed in the section Referring to Another XML Element. Recalling briefly that a key element or attribute with type xsd:ID has to be added to the element that is to be referenced from elsewhere and that a simple element or attribute with type xsd:IDREF is used in place of occurrences of the full element, we'll proceed to discuss the techniques for assembling a document tree where elements are linked in this way. Our example is a variation of the order data. Here, an order may either contain a full customer XML element, or a reference to a customer element that is in some other place. <xsd:complexType name="CustomerType"> <xsd:sequence> <xsd:element name="id" type="xsd:ID"/> <xsd:element name="name" type="xsd:string"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="OrderType"> <xsd:sequence> <xsd:choice> <xsd:element name="customer" type="CustomerType"/> <xsd:element name="custref" type="xsd:IDREF"/> </xsd:choice> <xsd:element name="items" type="ItemType" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> The Java code for OrderType deserves a quick inspection. We now have getters and setters for a CustomerType, i.e., the full, inline customer element, or for a customer reference. The Java type JAXB uses for the reference is plain Object, even though

we'll only use objects of type CustomerType here, too. public class OrderType { protected CustomerType customer; protected Object custref; protected List items; public CustomerType getCustomer() { return customer; } public void setCustomer(CustomerType value) { this.customer = value; } public Object getCustref() { return custref; } public void setCustref(Object value) { this.custref = value; } public List getItems() { if (items == null) { items = new ArrayList(); } return this.items; } } The XML element may contain full elements and references in two slightly different arrangements. The first possibility replaces all occurrences with references. This means that the full elements must be added separately, and in a way that is not to be confused with the actual document. The other option is to leave the first occurrence of a specific element in place and replace all duplicates. Notice that "first occurrence" is not necessarily the foremost element in the final XML text. Both ways you'll have to keep track of the association between keys and element references. Continuing our example, where we'll use the second method, we'll look at a method that adds the customer to an order. private ObjectFactory oFact = new ObjectFactory(); Map<String,CustomerType> id2cust = new HashMap<String,CustomerType>(); public void addCust( OrderType order, String custId, String custName ){ CustomerType cust = id2cust.get( custId ); if( cust == null ){ // Create and insert customer. cust = oFact.createCustomerType(); order.setCustomer( cust ); // complete customer cust.setId( custId );

cust.setName( custName ); // save in map id2cust.put( custId, cust ); } else { order.setCustref( cust ); } } If the lookup in the mapping of customer ids to customer elements returns null, then we meet a customer for the first time. We create a CustomerType object, and make sure that the assembly of this element includes a call to the setter for the key element, i.e., the "id" string. This key is also used as a key in the map, where we keep that element for future reference. If the customer lookup returns an object, we simply use the object reference value of the full element as an argument to the alternative setter for the custref element. JAXB takes care of generating the XML text representing the reference. Here is a look into a folder containing two orders to the same customer. <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <folder> <orders> <customer> <id>c12789</id> <name>Smith</name> </customer> <items> <id>12</id> <quantity>1</quantity> </items> <items> <id>24</id> <quantity>100</quantity> </items> </orders> <orders> <custref>c12789</custref> <items> <id>35</id> <quantity>10</quantity> </items> </orders> </folder> Don't be confused when you look at the generated XML code and detect that the value in the "custref" element is nothing but a string. Memory addresses - the convenient material for references - aren't useful in an XML text file. JAXB, however, hides this as long as possible by letting you handle references implemented as addresses, changing them magically to the corresponding string values. 4.3.2 Preserving Object Identity In the previous section we have tacitly assumed that there is one and only one object with a certain identification which is readily available from the object. But

what do you do if there is no such identification? Generating synthetic identifications isn't a problem, but how does this help to avoid generating full XML text for each occurrence? Should we use the equals(Object o) method for identifying objects that deserve the same synthetic identifier? The answer is that with a little extra effort you can still preserve object identity so that the same number of objects can be reconstructed when the XML data is read and unmarshalled back into memory. Object identity can be tested by applying the operator == to any two objects. Keeping a list of marshalled elements and searching through it isn't attractive. Luckily there is a better way: we can use an instance of an IdentityHashMap (from java.util) to register marshalled elements. This map uses the object's default hash code, even if hashCode has been overridden. Also, we have to add an (artificial) identification to our objects as this is required as the xsd:ID value. For an example we extend the schema describing orders with an additional AddressType and use this, once for a shipping address and once for a billing address. <xsd:complexType name="AddressType"> <xsd:sequence> <xsd:element name="street" type="xsd:string"/> <xsd:element name="city" type="xsd:string"/> <xsd:element name="country" type="xsd:string"/> <xsd:element name="zip" type="xsd:int"/> </xsd:sequence> <xsd:attribute name="id" type="xsd:ID"/> </xsd:complexType> <xsd:complexType name="AddrOrRefType"> <xsd:choice> <xsd:element name="addr" type="AddressType"/> <xsd:element name="addrRef" type="xsd:IDREF"/> </xsd:choice> </xsd:complexType> <xsd:complexType name="OrderType"> <xsd:sequence> <xsd:choice> <xsd:element name="customer" type="CustomerType"/> <xsd:element name="custref" type="xsd:IDREF"/> </xsd:choice> <xsd:element name="shipTo" type="AddrOrRefType"/> <xsd:element name="billTo" type="AddrOrRefType"/> <xsd:element name="items" type="ItemType" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> The generated class AddrOrRefType enables us to choose between an address in full or a reference to such an XML element.of type AddressType. To see how this works, we assume that we have addresses in objects of type Address. The code below creates another XML element for AddressType from an Address object. Map<Address,AddressType> pojo2elem = new IdentityHashMap<Address,AddressType>();

int refcount = 0; private String makeNextId(){ return "a" + refcount++; } public AddrOrRefType makeAddrOrRefElement( ObjectFactory objFact, Address addrPojo ){ AddrOrRefType arElem = objFact.createAddrOrRefType(); AddressType addrElem = pojo2elem.get( addrPojo ); if( addrElem == null ){ // First time: generate the full XML element... addrElem = objFact.createAddressType(); // ...and insert it into its parent. arElem.setAddr( addrElem ); // Set the xsd:ID attribute. addrElem.setId( makeNextId() ); // ...(Copy attributes from addrPojo into addrElem.)... // Register the object - id pair in the identity hash map. pojo2elem.put( addrPojo, addrElem ); } else { // We've had this one before: insert its reference. arElem.setAddrRef( addrElem ); } return arElem; } Using Address objects as keys, we map these to assembled AddressType objects. Whenever we encounter a new object of class Address, we enter it into the map and generate an AddrOrRef element containing the full AddressType element. For an encore, the AddrOrRef receives the reference to the previously created AddressType element. 4.4 Last Resort: Assembling a Java Object With all the features XML schema provides and JAXB translates you might think that including arbitrary Java objects in an XML document won't ever be necessary. But the need does arise occasionally. Special dumps of application data, for instance, may have to use this rather extreme technique. All in all, it is surprisingly simple, provided that the class of the object implements the java.util.Serializable interface. The schema element that is to contain the serialized binary data should be declared with a type of xsd:hexBinary. The schema snippet shows a simple container for some such object. <xsd:complexType name="JavaObjectType"> <xsd:sequence> <xsd:element name="data" type="xsd:hexBinary"/> </xsd:sequence> </xsd:complexType> <xsd:element name="container" type="JavaObjectType"/> The generated Java class JavaObjectType has a field byte[] data, which is just what

we need for calling the java.io.ObjectOutputStream methods writeObject and readObject. The code required to serialize a Java object into a XML element is shown below. JavaObjectType makePojoElem( ObjectFactory objFact, Object pojo ) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream ooStream = new ObjectOutputStream( baos ); ooStream.writeObject( pojo ); ooStream.flush(); JavaObjectType joElem = objFact.createJavaObjectType(); joElem.setData( baos.toByteArray() ); ooStream.close(); return joElem; } The generated XML text is verbose and lengthy, since all object data required for a full reconstruction is included in the serialized data. Here it is, omitting a few hundred hexadecimal digits: <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <container xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="serial.xsd"> <data>ACED00057372...7878</data> </container> The reverse process is even simpler. The byte array returned by the getter for the data element is fed to the ObjectInputStream which smartly returns the original object. Object getPojo( JavaObjectType joElem ) throws IOException, ClassNotFoundException { ByteArrayInputStream bais = new ByteArrayInputStream( joElem.getData() ); ObjectInputStream oiStream = new ObjectInputStream( bais ); Object pojo = oiStream.readObject(); oiStream.close(); return pojo; } 4.5 Calling marshal Only a handful of source code lines is required to make a JAXB Marshaller object write a document tree as an XML file. First you obtain a Marshaller from a JAXBContext. Then, you might set a number of properties, such as the one that's used below, which requests nice formatting of the XML text. Other properties concern the inclusion of a schema location as an attribute in the top-level element, or the encoding in the XML prolog. The first argument must be an object that is either a root element, as defined by your schema, or a JAXBElement<?>. import java.io.*; import javax.xml.bind.* void writeDocument( Object document, String pathname )

throws JAXBException, IOException { Class<T> clazz = document.getValue().getClass(); JAXBContext context = JAXBContext.newInstance( clazz.getPackage().getName() ); Marshaller m = context.createMarshaller(); m.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE ); m.marshal( document, new FileOutputStream( pathname ) ); } Sometimes marshalling needs to be done not only for one or two root documents but for objects of many different schema types. You could, of course, add xsd:element definitions for all of them to the top level xsd:schema element, but this is cumbersome. A generic solution is presented below. The method wraps an arbitrary element of some type T into a JAXBElement<T>. <T> JAXBElement<T> wrap( String ns, String tag, T o ){ QName qtag = new QName( ns, tag ); Class<?> clazz = o.getClass(); @SuppressWarnings( "unchecked" ) JAXBElement<T> jbe = new JAXBElement( qtag, clazz, o ); return jbe; } To use it, you must create a context capable of handling all the classes that might crop up as instantiations for T. (Creating a JAXBContext for several packages or classes is explained in section The JAXB Context.) With a Marshaller m obtained from this context, the application of wrap is as simple as this: SomeType st = ...; JAXBElement<SomeType> jbx = wrap( "http://www.acme.com", "someTag", st ); m.marshal( jbx, System.out );

5 Customizing 5.1 Reasons for Customizing It may not always be possible for the JAXB Schema compiler to determine all details of the generated Java code from the XML schema alone. Several customizing features are provided for adding information to the compiler's output, and for overriding the compiler's defaults for binding schema definitions to Java classes. The main reasons for customizing are: providing meaningful package names overriding the default class name (to avoid name clashes) overriding the default names for enum constants adding documentation associating a specific Java class with an XML Schema built-in type Customizing can be added inline to the schema, or it can be written on a separate file that is passed to the schema compiler. We'll see these techniques in the succeeding subsections. 5.2 Defining Package Names Some Java entities don't have a counterpart in an XML schema. One of these things is the package name. By default, JAXB uses the somewhat unimaginative package name generated. You can set a more appropriate package name in the call of the JAXB compiler, in addition to the option defining the root directory for the generated source files.: xjc -p jess.ruleml -d gen-src RuleML.xsd This, however, is neither flexible enough nor easy to maintain. A better place would be in the schema file itself where you may write an xsd:annotation element containing an xsd:appinfo sub-element: <xsd:annotation> <xsd:appinfo> <jaxb:schemaBindings> <jaxb:package name="jess.ruleml"/> </jaxb:schemaBindings> </xsd:appinfo> </xsd:annotation> If you don't want to burden your XML schema with these annotations you can collect this and other customizing directives in a separate file, ususally of file type .xjb. This XML file uses elements from the jaxb namespace. Its outermost element is jaxb:bindings, where you would indicate the namespace URI: <?xml version="1.0" encoding="UTF-8"?> <jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="2.0"> ... </jaxb:bindings>

You pass the file name to the schema compiler: xjc -b RuleML.xjb -d gen-src RuleML.xsd To put all of your classes into the same package you define the package name in a jaxb:schemaBindings element at the outermost level: <?xml version="1.0" encoding="UTF-8"?> <jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="2.0"> <jaxb:schemaBindings> <jaxb:package name="jess.ruleml"/> </jaxb:schemaBindings> </jaxb:bindings> A slightly more complicated element structure is necessary if you want to compile several schema files in one run and the classes resulting from different schemata should emerge in separate packages. Here is an example: <?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" jaxb:version="2.0"> <jaxb:bindings schemaLocation="Flight.xsd" node="/xsd:schema"> <jaxb:schemaBindings> <jaxb:package name="travel.flight"/> </jaxb:schemaBindings> </jaxb:bindings> <jaxb:bindings schemaLocation="Hotel.xsd" node="/xsd:schema"> <jaxb:schemaBindings> <jaxb:package name="travel.hotel"/> </jaxb:schemaBindings> </jaxb:bindings> </jaxb:bindings> Now we have nested jaxb:bindings elements, with the inner ones being associated with some xsd:schema element, the outermost element of an XML schema. The value of the node attribute is an XPath expression referring to that outermost element. Notice that it's necessary to define the mapping of the XML Schema namespace prefix (here: xsd) to its URI in the top-level jaxb:bindings element. 5.3 Overriding Names Overriding the name of a class or of an element's child is something you may have to do to avoid name clashes. Usually it is more convenient to fix the XML schema, but you may not always be at liberty to do so. Let's assume that you have a schema where a complex type has been given the uninspired name List: <xsd:complexType name="List"> <xsd:sequence>

<xsd:element name="items" type="ItemType" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> JAXB's schema compiler circumnavigates the threatening name clash between this class and java.util.List, required within the generated class code for declaring the field items. But wherever this class is used it is potentially in conflict with its namesake from java.util. To avoid having to use the full class name for one of these two classes, you might override the class name for the generated class: <xsd:complexType name="List"> <xsd:annotation> <xsd:appinfo> <jxb:class name="MyListType"/> </xsd:appinfo> </xsd:annotation> <xsd:sequence> <xsd:element name="items" type="ItemType" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> Another unlucky choice for the name of an element or attribute would be Class. For this one, JAXB's workaround is the standard programmer's choice, i.e., it is replaced by Clazz. If you don't fancy this, you can request your own substitute, using an jxb:property element, like this: <xsd:complexType name="School"> <xsd:sequence> <xsd:element name="class" type="ClassType"> <xsd:annotation> <xsd:appinfo> <jxb:property name="klass"/> </xsd:appinfo> </xsd:annotation> </xsd:element> </xsd:sequence> </xsd:complexType> Other Java keywords won't constitute a problem. The instance variable will be given a name consisting of an underscore followed by the letters of the keyword. Yet another reason for changing a name arises from the use of the same name for a sub-element and an attribute within the same complex type definition. (Arguably this isn't good XML design. But, believe me, it does happen.) <xsd:complexType name="ClassType"> <xsd:sequence> <xsd:element name="grade" type="xsd:string" minOccurs="0"/> </xsd:sequence> <xsd:attribute name="grade" type="xsd:string" use="optional"/> </xsd:complexType>

We'll resolve this conflict by renaming the attribute to gradeAttr, this time by specifying the property name in the bindings file. <?xml version="1.0" encoding="UTF-8"?> <jaxb:bindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsd="http://www.w3.org/2001/XMLSchema" jxb:version="2.0"> <jxb:bindings schemaLocation="School.xsd" node="/xsd:schema"> <jxb:bindings node="//xsd:attribute[@name='grade']"> <jxb:property name="gradeAttr"/> </jxb:bindings> </jxb:bindings> </jxb:bindings> XML Schema even lets you define a sequence where two individual elements have the same tag <xsd:complexType name="StrangeType"> <xsd:sequence> <xsd:element name="taga" type="xsd:string"/> <xsd:element name="tagb" type="xsd:string"/> <xsd:element name="taga" type="xsd:string"/> </xsd:sequence> </xsd:complexType> There is no such thing as a Java class that has two distinct fields with the same name. You must help the schema compiler to resolve this conflict, by renaming either element: ... <xsd:element name="taga" type="xsd:string"> <xsd:annotation> <xsd:appinfo> <jxb:property name="taga2"/> </xsd:appinfo> </xsd:annotation> </xsd:element> ... 5.4 Adding Documentation Both the readers of your XML schema and the users of the generated Java classes will be more than grateful for each morsel of documentation. JAXB does a good job by providing most if not all of the Javadoc that can be generated automatically. While this is good at describing the relation between the generated Java code and the originating chunks of the XML schema, it conveys nothing about the intentions behind the schema itself. Documentation is probably best written inline, as part of the type definition in your schema. This way it remains close to the schema text it refers to and documents (not quite perfectly) the XML schema itself. Here is one way of adding some documentation for a class derived from a complex type definition:

<xsd:complexType name="GlobalType"> <xsd:annotation> <xsd:appinfo> <jxb:class> <jxb:javadoc> A &lt;code>GlobalType&lt;/code> object represents a single defglobal variable definition. The variable name must begin and end with an asterisk ('*'). </jxb:javadoc> </jxb:class> </xsd:appinfo> </xsd:annotation> <xsd:complexContent> <xsd:extension base="AssignmentType"/> </xsd:complexContent> </xsd:complexType> Notice that any XML markup requires the escaping of all less-than and ampersand characters, i.e., "<" and "&" must be written as "&lt;" and "&amp;". (Another possibility is writing the text as a CDATA section, see below.) The text is added up front to the Javadoc text JAXB will provide anyway. Your browser will show you this text as the head of the documentation for the class GlobalType: public class GlobalType extends AssignmentType A GlobalType object represents a single defglobal variable definition. The variable name must begin and end with an asterisk ('*'). Java class for GlobalType complex type. ... Documentation for elements and attributes is added in a similar manner. For either of these schema components, you add a child as shown in the example below. <xsd:element name="elemA" type="xsd:string"> <xsd:annotation> <xsd:appinfo> <jxb:property> <jxb:javadoc> This documents a property which happens to be an XML Schema element. </jxb:javadoc> </jxb:property> </xsd:appinfo> </xsd:annotation> </xsd:element> Finally, we'll look at a snippet as it might be included to appear as package level documentation. It can be written at the outermost level of the schema. <xsd:schema>

... <xsd:annotation> <xsd:appinfo> <jxb:schemaBindings> <jxb:package name="com.jessrules.jessml"> <jxb:javadoc> <![CDATA[<body>This package contains classes derived from the XML schema JessML2_0. They represent XML element content for Jess constructs and function calls, including their subordinate elements. Two documents are supported: <ol> <li>rulebase documents containing Jess constructs and function calls <li>fact-list documents containing the result of a call to <code>save-facts-xml</code> </ol> </body>]]> </jxb:javadoc> </jxb:package> </jxb:schemaBindings> </xsd:appinfo> </xsd:annotation> This example features the XML technique for including arbitrary content as a CDATA section. It enables you to write HTML tags in a more readable way. 5.5 Interning Strings If your XML data contains a large number of strings with many repetitions it may be well worth interning these strings. Calling the intern() method on a String returns a string that has the same contents as this string, but is guaranteed to be from a pool of unique strings. This may reduce your memory footprint considerably. So, is there a simple method for interning all strings resulting from unmarshalling? There is only two things to do. First, we customize a small change for the mapping of xsd:string to String, to sneak in our own method for parsing the XML string data to a Java string. <jaxb:globalBindings> <jaxb:javaType name="String" xmlType="xsd:string" parseMethod="faststring.StringInterner.parseStringToString"/> </jaxb:globalBindings> The other thing is to write the class StringInterner which contains a tiny wrapper for the method parseString from DatatypeConverter: package faststring; import javax.xml.bind.DatatypeConverter; public class StringInterner { public static String parseStringToString( String value ){ return DatatypeConverter.parseString( value ).intern(); }

} Peeking at the implementation of DatatypeConverter reveals that parseString just returns its argument. But its a good strategy to go by the book and call the basic conversion except when we are prepared to do it all on our own, as in the next example. 5.6 Overriding the Datatype 5.6.1 Replacing the Conversions Most of the time JAXB's mapping of XML Schema types to Java datatypes will meet your expectations, and the standard conversion of values between binary and string is just what you need. In those rare cases where this is not adequate, it is possible to customize the datatype binding. We'll illustrate this by a simple example where a xsd:simpleType for roman numbers is defined like this: <xsd:simpleType name="RomanNumberType"> <xsd:restriction base="xsd:string"> <xsd:pattern value="M*D?C{,4}L?X{,4}V?I{,4}"/> <xsd:minLength value="1"/> </xsd:restriction> </xsd:simpleType> (The pattern does not cover the subtractive notation which wasn't used in ancient times anyway.) Although the XML type is xsd:string, we'd like to have these values represented by Java's int. This means that we'll also have to supply the conversions between the Roman number as a string of letters and as an integer value. For this, we have to write a simple class like the one given below. package util.roman; import java.util.HashMap; import java.util.Map; public class RomanNumberConverter { private static Map<Character,Integer> rom2int = new HashMap<Character,Integer>(); private static Map<Integer,Character> int2rom = new HashMap<Integer,Character>(); private static int[] digits = new int[]{ 1000, 500, 100, 50, 10, 5, 1 }; static { rom2int.put( 'I', 1 ); rom2int.put( 'V', 5 ); rom2int.put( 'X', 10 ); rom2int.put( 'L', 50 ); rom2int.put( 'C', 100 ); rom2int.put( 'D', 500 ); rom2int.put( 'M', 1000 ); for( Map.Entry<Character,Integer> entry: rom2int.entrySet() ){ int2rom.put( entry.getValue(), entry.getKey() ); }

} public static int parseStringToInt( String value ){ int result = 0; for( int i = 0; i < value.length(); i++ ){ result += rom2int.get( value.charAt( i ) ); } return result; } public static String printIntToString( int value ){ StringBuilder sb = new StringBuilder(); for( int d: digits ){ while( value > d ){ value -= d; sb.append( int2rom.get( d ) ); } } return sb.toString(); } } There is a useful class that supports the writing of convertes such as this one: javax.xml.bind.DatatypeConverter provides a rich set of methods that come in handy whenever the XML representation must follow the specifications in XML Schema Part 2: Datatypes. The essential methods are the ones we'll have to announce to JAXB, so that it will call our methods for the to and fro between the representations. You may choose any names you like, but the methods must be static. The customizing entry supplied in a bindings file should then look like the one given below, with a threefold nesting of <jaxb:bindings> providing the level where you define the schema position with an XPATH expression. <?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" jaxb:version="1.0"> <jaxb:bindings schemaLocation="roman.xsd" node="/xsd:schema"> <jaxb:bindings node="//xsd:simpleType[@name='RomanNumberType']"> <jaxb:javaType name="int" parseMethod="util.roman.RomanNumberConverter.parseStringToInt" printMethod="util.roman.RomanNumberConverter.printIntToString"/> </jaxb:bindings> </jaxb:bindings> </jaxb:bindings> 5.6.2 Replacing a Simple Type Replacing a simple schema type such as string by some user defined Java type is a little more complicated than what we have seen in the previous section. We'll discuss the proceedings on the basis of this type definition of a complex type meant to describe integer variables.

<xsd:complexType name="VariableType"> <xsd:sequence> <xsd:element name="Value" type="xsd:int"/> </xsd:sequence> <xsd:attribute name="Impl" type="xsd:string"/> </xsd:complexType> The type we want to replace by customization is the one for the attribute Impl which is to be represented by the following enum type. package impl; public enum ImplType { UINT8( 1, false ), INT8( 1, true ), // ... UINT64(4,false), INT3644,true); private final int bytes; private final boolean signed; ImplType( int b, boolean s ) { bytes = b; signed = s; } } The utility class providing the conversions between a string representation and the enum constants is easy. package impl; import java.util.*; public class ImplConv { public static ImplType parseStringToEnum( String value ){ return ImplType.valueOf( ImplType.class, value ); } public static String printEnumToString( ImplType impl ){ return impl.toString(); } } Now we are prepared to set up the bindings file such as the one shown below, in full. Notice the progressive restriction of the scope for the binding specifications, first restricted to a specific schema (i.e., signal.xsd, then to the complex type definition for VariableType, and finally to its Impl attribute node. Also, the binding syntax requires that now, when we're substituting a type of our own for a base type, the <jaxb:javaType> element must be enclosed in a <jaxb:baseType>, and this, in turn, must be wrapped by a <jaxb:property element. <?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" jaxb:version="2.0"> <jaxb:bindings schemaLocation="signal.xsd" node="/xsd:schema"> <jaxb:schemaBindings>

<jaxb:package name="signal"/> </jaxb:schemaBindings> <jaxb:bindings node="//xsd:complexType[@name='VariableType']"> <jaxb:bindings node="./xsd:attribute[@name='Impl']"> <jaxb:property> <jaxb:baseType> <jaxb:javaType name="impl.ImplType" parseMethod="impl.ImplConv.parseStringToEnum" printMethod="impl.ImplConv.printEnumToString"/> </jaxb:baseType> </jaxb:property> </jaxb:bindings> </jaxb:bindings> </jaxb:bindings> </jaxb:bindings> You can glean the reward of your pains from looking at the generated code for the impl field of VariableType which lets you now deal with this attribute via ImplType enums, e.g.,: ObjectFactory of = new ObjectFactory(); VariableType var = of.createVariableType(); var.setValue( 42 ); var.setImpl( ImplType.INT16 );

6 JAXB Annotations 6.1 How a Schema Mapping Is Implemented The Java code generated by the JAXB schema compiler contains annotations providing metadata on packages, classes, fields and methods. Together, this metadata is intended to reflect the information contained in an XML schema, of which only a very small part can be expressed by the actual Java code. Annotations can be easily retrieved from their target construct with methods contained in classes such as java.lang.Class or java.lang.reflect.Field. Each annotation type has its own set of attributes, which are accessed in the usual way. Given some class, an annotation of type XmlType can be retrieved with Class clazz = ...; XmlType typeAnn = clazz.getAnnotation( XmlType.class ); If the result of the annotation getter is not null, annotation element values may be obtained by calling methods on the returned XmlType object. To retrieve the name of the corresponding XML Schema type you would write String schemaName = typeAnn.name(); Classes that can be used for marshalling and unmarshalling XML need not be generated by the JAXB schema compiler. It is equally possible to write these classes by hand, adding the JAXB annotations. We'll discuss some basic annotations in the next section. 6.2 A Survey Of JAXB Annotations 6.2.1 Top-level Elements: XmlRootElement A class that describes an XML element that is to be a top-level element, i.e., one that can function as an XML document, should be annotated with XmlRootElement. Its optional elements are name and namespace. By default, the class name is used as the name. This annotation corresponds to an xsd:element construct being used at the outermost level of an XML schema. The sequence of Java, XML and schema snippets given below illustrates this relation. @XmlRootElement( name="doc" ) public class Document { @XmlElement protected Foo foo; // ... } <?xml version="1.0" encoding="UTF-8"?> <doc> <foo>...</foo> </doc>

<?xml version="1.0" encoding="UTF-8"?> <xsd:complexType name="Foo"> ... </xsd:complexType> <xsd:complexType name="Document"> <xsd:sequence> <xsd:element name="foo" type="Foo"/> </xsd:sequence> </xsd:complexType> <xsd:element name="doc" type="Document"/> It's a surprising fact that if all of your Java classes permit a straightforward mapping to XML Schema, XmlRootElement may be the only annotation you have to make! Here's a small set of classes, that is even capable of marshalling a Map<K,V>. import java.util.HashMap; import java.util.Map; import javax.xml.bind.annotation.*; @XmlRootElement(name="doc") public class DocType { public Map<KeyType,EntryType> key2entry = new HashMap<KeyType,EntryType>(); public DocType(){ } } import javax.xml.datatype.*; public class KeyType { public String event; public XMLGregorianCalendar datetime; public KeyType(){} public KeyType( String event, XMLGregorianCalendar datetime ){ this.event = event; this.datetime = datetime; } } public class EntryType { public String program; public String artists; public EntryType(){} public EntryType( String artists, String program ){ this.artists = artists; this.program = program; } } Applying the usual incantations for creating and marshalling content, you could produce XML data like so: <doc>

<key2entry> <entry> <key> <event>Soiree</event> <datetime>2008-08-23T20:00:00</datetime> </key> <value> <program>Man on the Moon</program> <artists>R.E.M</artists> </value> </entry> </key2entry> </doc> The XMLGregorianCalendar is mapped to xsd:dateTime, and the 'T' between the date and the time is just right, according to the Schema Datatypes specification. You can see that JAXB had to "invent" a few tag names for the intermediary element levels separating map entries from each other, and key data from value data, but you'd have to do something similar if you'd design it yourself. 6.2.2 Annotation for Classes: XmlType This annotation adds information that would be available from a schema type, but isn't implied by a Java class declaration. The annotation has several attributes: factoryClass and factoryMethod define the class containing a no-argument method for creating an instance of this class as the equivalent of an empty XML element. The attribute name provides the XML schema name if you don't want to use the class name. The namespace attribute provides the name of the target namespace. The string array value defined by propOrder establishes an ordering of the subelements. (It's pretty obvious that there can't be a connection between the textual order of items in a class definition and the order its fields are returned by reflection methods.) Here is an example for XmlType, requesting that the elements title, items and cluster should appear in the given order: @XmlRootElement @XmlType( propOrder={ "title", "items", "cluster" } ) public class Document { ... } 6.2.3 Annotations for the Schema: XmlSchema This annotation can only be used with a package. It defines parameters that are derived from the xsd:schema element. It must be written on a file package-info.java situated in the package. Below is an example, specifying the namespace and elementFormDefault elements. @javax.xml.bind.annotation.XmlSchema( namespace = "http://www.laune.at/hospital",

elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) package hospital; This annotation is equivalent to an xs:schema element <xs:schema elementFormDefault="qualified" targetNamespace="http://www.laune.at/hospital" xmlns:tns="http://www.laune.at/hospital" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" > For defining namespace prefixes you use the xmlns element of the XmlSchema annotation. It contains an array of XmlNs annotations, each of which contains a prefix and a namespaceURI element. The previous example is extended with a namespace definition for the prefix med: @javax.xml.bind.annotation.XmlSchema( namespace = "http://www.laune.at/hospital", xmlns = { @javax.xml.bind.annotation.XmlNs( prefix = "med", namespaceURI = "http://www.laune.at/med" ) }, elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) package hospital; This corresponds to using xmlns:med="http://www.laune.at/med" as an attribute in the xs:schema element. 6.2.4 The Object Factory: XmlRegistry, XmlElementDecl To be able to create objects from XML elements, the unmarshaller must have an object factory with methods for creating all sorts of objects. Therefore, each package containing JAXB classes must contain one class ObjectFactory, annotated with XmlRegistry. @XmlRegistry public class ObjectFactory { ... } Most objects require nothing but a simple create method. But whenever an element has to be represented as a JAXBElement<?>, an additional factory method for wrapping the "pure" Java object of some class Foo into an element of class JAXBElement<Foo> must be provided. This method is then annotated with XmlElementDecl, providing the components of the element's tag name through the attributes namespace and name. This is a snippet from some object factory where an element of TreeType is wrapped into a JAXBElement<TreeType>: @XmlElementDecl(namespace = "", name = "tree") public JAXBElement<TreeType> createTree( TreeType value) { return new JAXBElement<TreeType>(_Tree_QNAME, TreeType.class, null, value); }

6.2.5 Controlling Element Selection: XmlAccessorType, XmlTransient If JAXB binds a class to XML, then, by default, all public members will be bound, i.e., public getter and setter pairs, or public fields. Any protected, package-visible or private member is bound if it is annotated with a suitable annotation such as XmlElement or XmlAttribute. You have several possibilities to influence this default behaviour. You can annotate a package or a top level class with XmlAccessorType, setting its value element to one of the enum constants FIELD, PROPERTY, PUBLIC_MEMBER or NONE. If FIELD is set every non static, non transient field will be automatically bound. PROPERTY instructs JAXB to do this for getter and setter pairs. NONE suppresses bind except for explicitly annotated fields or properties. A class without this annotation inherits the XmlAccessorType setting either from its superclass or from the package setting. The other annotation to be mentioned in this context is XmlTransient. It suppresses binding for its target which can be an entire class or a field or a method. This is also useful if you have a name clash resulting from a public field, say foo, and methods getFoo and setFoo. The first class illustrates a class that restricts the set of XML elements from an accessor type setting of PUBLIC_MEMBER. Member getB is blocked from being bound. @XmlAccessorType( XmlAccessType.PUBLIC_MEMBER ) public class SomeClass { private String a; private String b; public SomeClass(){ ... } public String getA(){ ... } public void setA( String value ){ ... } @XmlTransient public String getB(){ ... } public void setB( String value ){ ... } } The corresponding XML schema type definition looks like this: <xs:complexType name="someClass"> <xs:sequence> <xs:element name="a" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:complexType> The second example illustrates the reverse process. It shows a class with the most restrictive accessor type setting, with one member explicitly annotated as an element. @XmlAccessorType( XmlAccessType.NONE )

public class OtherClass { private String a; private String b; public OtherClass(){ ... } public String getA(){ ... } public void setA( String value ){ ... } @XmlElement( required = true ) public String getB(){ ... } public void setB( String value ){ ... } } Since we have set the annotation element required to true, the generated schema snippet is slightly different: <xs:complexType name="otherClass"> <xs:sequence> <xs:element name="b" type="xs:string"/> </xs:sequence> </xs:complexType> The final example for this topic demonstrates using these annotations in somewhat special circumstances. First, XmlTransient is used on the public field to avoid the name clash with the method pair. Second, XmlElement is used to request binding for getB, which doesn't have its setB spouse. (The getter follows the standard pattern of the JAXB generated Java code for elements bound to List<?>, with changes being made on the list object.) @XmlAccessorType( XmlAccessType.PUBLIC_MEMBER ) public class SpecialClass { @XmlTransient public String a; private List<String> b; public SpecialClass(){ ... } public String getA(){ ... } public void setA( String value ){ ... } @XmlElement public List<String> getB(){ if( b == null ) b = new ArrayList<String>(); return b; } } The generated complex type features both elements. <xs:complexType name="specialClass"> <xs:sequence> <xs:element name="a" type="xs:string" minOccurs="0"/>

<xs:element name="b" type="xs:string" maxOccurs="unbounded" minOccurs="0"/> </xs:sequence> </xs:complexType> Taken together, this means that you can, either at package level or at some superclass, define the strategy for all classes within the package or for all subclasses, respectively. This strategy may be generally permissive, oriented on fields or properties, or restrictive, permitting nothing by default. Within a class, you may extend a restrictive setting by adding XmlElement or XmlAttribute, or you may inhibit bindings using the XmlTransient annotation. 6.2.6 Class Inclusion: XmlSeeAlso The annotation XmlSeeAlso instructs JAXB to include the specified classes in the set of recognized classes, i.e., the ones that are bound to schema elements. The typical case where this is required is for the subclasses of some class that is included, in contrast to those classes that are statically referenced, e.g., because they are used as types for a field. You use XmlSeeAlso on some class, as shown in the example below: @XmlSeeAlso( {Dog.class, Cat.class} ) class Animal { //... } 6.2.7 Annotations for Fields Fields of a class may correspond to XML elements. Once more, there is a gap between what can be defined in an XML schema and the information available from field definitions within a Java class. 6.2.7.1 The Annotation XmlElement The basic annotation for a field that's intended to be an element is XmlElement. It permits you to define the XML element name, the namespace, whether it is optional or nillable, a default value and the Java class. Here are two annotated fields, and below is the corresponding schema snippet. @XmlElement(name = "Preamble", required = true) protected PreambleType preamble; @XmlElement(name = "Workplace", required = true) protected List<SysWorkplaceType> workplace; <xsd:sequence> <xsd:element name="Preamble" type="com:PreambleType"/> <xsd:element name="Workplace" type="SysWorkplaceType" minOccurs="1" maxOccurs="unbounded"/> </xsd:sequence> If a field has some collection type, more than one @XmlElement may have to be associated with this field. This requires that these annotations are assembled in a XmlElements (not the plural "s") annotation that merely acts as a container. In the

class definition below, the field entryOrChoiceOrCascade is a collection composed from objects of three different classes. @XmlType(name = "MenuType") public class MenuType extends ItemType { @XmlElements({ @XmlElement(name = "Item", type = ItemType.class), @XmlElement(name = "CheckBox", type = CheckBoxType.class), @XmlElement(name = "Menu", type = MenuType.class) }) protected List entryList; } As a bonus you may avoid the complicated name for the list element that JAXB concocts from the first three possibles. 6.2.7.2 The Annotation XmlList The attribute XmlList instructs JAXB that a list value is to be represented as a blank separated list of values of some simple type rather than a list of individual child elements. The annotated class Sentence @XmlType class Sentence { @XmlElement List<String> word; } produces XML such as <sentence> <word>This</word> <word>is</word> <word>verbose</word> </sentence> In contrast, the addition of XmlList @XmlType class Sentence { @XmlElement @XmlList List<String> word; } results in <sentence> <word>This is terse</word> </sentence> Needless to say, using the XML representation of lists for strings is risky unless you

can be sure that no string value contains a blank. Also, remember the restriction for XML Schema's xsd:list, which is only valid for types that are simple according to XML Schema rules. A class such as Paragraph @XmlType class Paragraph { @XmlElement @XmlList // Not valid - Sentence isn't a simple type. List<Sentence> word; } is bound to fail as soon as JAXB inspects the annotations. (The Java compiler has no way of knowing that something is amiss here.) 6.2.7.3 Class Fields as Attributes: XmlAttribute Provided that XML lets you represent a data item as a single value, there is no cutand-dried rule for deciding between using an element or an attribute. (If you look for guidance, the schema describing the XML Schema language itself, making judicious use of both, is a good example.) JAXB, of course, has to be told when to make a field into an XML attribute. The annotation for creating an XML attribute is XmlAttribute. Its elements correspond to what can be defined in an XML schema: -- name defines the namestring for the attribute, the default being the class field's name. -- namespace specifies the XML target namespace to be used for the attribute's name. -- A "true" value of required is the same as using the XML Schema definition's attribute use="required". If you ask about some way for defining the equivalent for the XML Schema attribute default="value", then the simple answer is: "Do it yourself." Just write the getter so that it returns the default value if the field's value is null. It's possible to annotate a static final field with XmlAttribute. This has the same effect as an XML Schema definition where the attribute element's attribute fixed is set to that value. @XmlAttribute final static int answer = 42; 6.2.7.4 Mapping a Class to Simple Content or Simple Type: XmlValue Usually a Java class results in a complex type, with one element or attribute for each field. Now consider this simple Java class with a single instance variable: public class Price { private BigDecimal amount; public Price(){} @XmlElement

public BigDecimal getAmount(){ return amount; } public void setAmount( BigDecimal value ){ this.amount = value; } } If this type is used for some field, the result will be according to this XML Schema type definition: <xs:complexType name="price"> <xs:sequence> <xs:element name="amount" type="xs:decimal" minOccurs="0"/> </xs:sequence> </xs:complexType> The marshalled XML data is unnecessarily complicated due to an addtional element layer, e.g.: <price> <amount>123.45</amount> </price> What is required here is a way of telling JAXB to map class Price to a simple schema type. This is done by annotating the single field amount with XmlValue instead of XmlElement: public class Price { // ... @XmlValue public BigDecimal getAmount(){ return amount; } // ... } This is now equivalent to this simple type definition: <xs:simpleType name="price"> <xs:restriction base="xs:decimal"/> </xs:simpleType> The XML data is pleasantly reduced to: <price>123.45</price> Notice that fields of type Price could now be mapped to an XML attribute, too. 6.2.7.5 Collecting Unspecified Attributes: XmlAnyAttribute An XML element may carry attributes which aren't defined in the XML schema, or have no explicit mapping to some field in the Java class defining the element type.

It's possible to collect these unspecified attributes into a map with the type Map<QName,Object>. Here is an example using the annotation XmlAnyAttribute: public class MixtureType { private Map<QName,Object> any; private String title; public MixtureType(){} @XmlAnyAttribute public Map<QName,Object> getAny(){ if( any == null ){ any = new HashMap<QName,Object>(); } return any; } @XmlElement public String getTitle(){ return title; } public void setTitle( String value ){ title = value; } } Let's assume that the top level element of type DocumentType contains nothing but one MixtureType element. Then, an XML data file that can be unmarshalled into an object of this class would look like this: <document> <mixture foo="a foo attribute" bar="attribute of bar"> <title>A mixture of elements</title> </mixture> </document> After unmarshalling this into a DocumentType object, the sub-element and its spurious attributes can be extracted like this: JAXBElement<DocumentType> jbe = (JAXBElement)u.unmarshal( new File( "mixture.xml" ) ); DocumentType doc = jbe.getValue(); MixtureType mix = doc.getMixture(); System.out.println( "Title: " + mix.getTitle() ); Map<QName,Object> amap = mix.getAny(); for( Map.Entry<QName,Object> e: amap.entrySet() ){ System.out.println( e.getKey() + "="" + e.getValue() + """ ); } This is the resulting output: A mixture of elements foo="a foo attribute"

bar="attribute of bar" 6.2.7.6 Collecting Unspecified Elements: XmlAnyElement Arbitrary content is indicated by the XML Schema type xsd:anyType. (We have already seen that this corresponds to an object of type org.w3c.dom.Element, cf. subsection DOM Elements.) The annotation XmlAnyElement instructs JAXB to map a field to a DOM Element object, or an array or list of such elements. Let's say that we want to unmarshal XML data with arbitrary tags and some text content, e,g,: <document> <zoo> <a>Anaconda</a> <b>Buffalo</b> <c>Chameleon</c> <d>Dromedar</d> </zoo> </document> The interesting class is ZooType, defining the structure of the element tagged zoo as a list of DOM elements: import java.util.*; import org.w3c.dom.Element; import javax.xml.bind.annotation.*; public class ZooType { protected List<Element> animals; public ZooType(){ } @XmlAnyElement public List<Element> getAnimals(){ if( animals == null ) animals = new ArrayList<Element>(); return animals; } public void setAnimals( List value ){ animals = value; } } Unmarshalling and accessing this data is done like this: JAXBContext jc = JAXBContext.newInstance( DocumentType.class ); Unmarshaller u = jc.createUnmarshaller(); DocumentType doc = (DocumentType)u.unmarshal( f ); for( Element el: doc.getZoo().getAnimals() ){ System.out.println( el.getNodeName() + "->" + el.getTextContent() ); }

The resulting output looks like this: a->Anaconda b->Buffalo c->Chameleon d->Dromedar 6.2.7.7 Wrapping Repeated Elements: XmlElementWrapper With a repeatable XML element you may want to distinguish between a list that is absent and an empty list. For this, you need some additional element bracketing, or "wrapping", for the repeated element, as indicated in the XML snippet below. <parent> <wrapper> <item>A</item> <item>B</item> <item>C</item> </wrapper> </parent> You instruct JAXB to generate this additional element by adding the annotation XmlElementWrapper to a collection type attribute. @XmlType( name="ParentType" ) public class ParentType { protected List item; public ParentType(){ ... } @XmlElement( name="item" ) @XmlElementWrapper( name="wrapper" ) public List getItem(){ if( item == null ) item = new ArrayList(); return item; } } 6.2.7.8 Annotations for Mixed Content: XmlElementRef, XmlMixed An XML complex type with mixed content, i.e., child elements embedded in the element's own data, cannot be bound to a class in the usual bean style, with one field for each element and attribute, and another one for the content text. Doing so would lose the order of the sub-elements and the chunks of content text wherein they are embedded. JAXB binds such a type to a class containing a single list attribute typed List<JAXBElement>. Here is a schema snippet for a complex type with mixed content: <xs:complexType name="MessageType" mixed="true"> <xs:sequence> <xs:element name="id" type="xs:int"/> <xs:element name="code" type="CodeType"/> </xs:sequence> </xs:complexType>

To achieve the same effect with an annotated class, you would write an annotated Java class like this: @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "MessageType", propOrder = { "content" }) public class MessageType { @XmlElementRefs( { @XmlElementRef(name = "code", type = JAXBElement.class), @XmlElementRef(name = "id", type = JAXBElement.class) }) @XmlMixed protected List<Serializable> content; public List<Serializable> getContent() { if (content == null) { content = new ArrayList<Serializable>(); } return this.content; } } The generic parameter for the content list is Serializable, slightly more specific than Object. When you process the elements of the content list after unmarshalling, you'll have to distinguish between JAXBElement objects for the sub-elements and String objects for the chunks of the content of the element itself. A similar but rarely encountered situation is created by duplicating an element in a sequence. Below is a slightly modified version of the schema snippet for the complex type MessageType, which doesn't have mixed content any more, but contains a repetition of element id (ours not to worry why): <xs:complexType name="MessageType"> <xs:sequence> <xs:element name="id" type="xs:int"/> <xs:element name="code" type="CodeType"/> <xs:element name="id" type="xs:int"/> </xs:sequence> </xs:complexType> The annotated Java code would be similar to the one shown previously, except that XmlMixed is omitted and the generic parameter for List should be JAXBElement<?>. @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Message", propOrder = { "content" } ) public class Message { @XmlElementRefs({ @XmlElementRef(name = "id", type = JAXBElement.class), @XmlElementRef(name = "code", type = JAXBElement.class), @XmlElementRef(name = "id", type = JAXBElement.class) }) protected List<JAXBElement<?>> content; public List<JAXBElement<?>> getContent() {

if (content == null) { content = new ArrayList<JAXBElement<?>>(); } return this.content; } } This does, in fact, marshal or unmarshal many more sub-element sequences than the one shown in the schema snippet, with arbitrary alternations of all three elements. 6.2.8 Annotations for Enums: XmlEnum, XmlEnumValue An enum type is annotated with XmlEnum. It has an optional element value of type java.lang.Class which defines the class used for the values used in the XML representation. Usually, and by default, this is java.lang.String but other types, even numeric ones, are equally possible. For a straightforward enum type, this is sufficient: @XmlEnum public enum SubElemType { //...(enum definition) } Individual enum constants have to be annotated if there is a difference between the Java name and the string used to represent the value in XML. This is defined with an @XmlEnumValue annotation that is attached to individual enum constants. Its required element defines the XML representation string. If it might be useful for the Java application to have support for the conversion between Java values and XML representations as well, the enum type might define the XML representation as a parameter for the constructor, provide a getter for the XML string and perhaps even a lookup function (fromValue) to convert a string to the enum constant. Such a deluxe version of an enum type is shown below. @XmlEnum public enum SubElemType { @XmlEnumValue("PrMaSig") PR_MA_SIG("PrMaSig"), @XmlEnumValue("Track1") TRACK_1("Track1"), // ...(more enum constant definitions) private final String value; SubElemType(String v) { value = v; } public String value() { return value; } public static SubElemType fromValue(String v) {

for (SubElemType c: SubElemType.values()) { if (c.value.equals(v)) { return c; } } throw new IllegalArgumentException(v.toString()); } } 6.2.9 Type Adapters: XmlJavaTypeAdapter For some Java container types JAXB has no built-in mapping to an XML structure. Also, you may want to represent Java types in a way that is entirely different from what JAXB is apt to do. Such mappings require an adapter class, written as an extension of XmlAdapter<XmlType,ApplType> from the package javax.xml.bind.annotation.adapters. The annotation XmlJavaTypeAdapter is provided for announcing the adapter in the desired place. We'll illustrate adapters by defining a substitution of a map for an array. Here is an XML example of the data we have to deal with. <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <ns:training xmlns:ns="http://foo/bar"> <brochure> <course price="123.45" id="c1"> <name>Course 1</name> </course> <course price="123.45" id="c0"> <name>Course 0</name> </course> </brochure> </ns:training> The course elements could be represented as a list or array, but we would like to process this data in our application as a map of the id attribute to the Course object. Although JAXB is capable of handling maps, we have seen (in section Top-level Elements: XmlRootElement) that the resulting XML structure isn't as simple as possible. To achieve our goal, we write a class Brochure containing the map we have in mind and declare that this is the one that has to be adapted to something JAXB knows how to handle, i.e., the class Courses containing a simple array of Course objects. @XmlRootElement(name="training") public class Training { @XmlElement public Brochure brochure; public Training(){} public Training( Brochure b ){ brochure = b; } } @XmlJavaTypeAdapter(BrochureAdapter.class)

public class Brochure { Map<String,Course> courses; public Brochure() { courses = new HashMap<String, Course>(); } } public class Courses { @XmlElement(name="course") public Course[] carray; } public class Course { @XmlAttribute String id; @XmlElement String name; @XmlAttribute Price price; } Class Brochure is annotated with XmlJavaTypeAdapter, defining class BrochureAdapter as its adapter, and this is, of course, the interesting class. It has to override methods unmarshal and marshal. public class BrochureAdapter extends XmlAdapter<Courses,Brochure> { @Override public Brochure unmarshal( Courses value ){ Brochure b = new Brochure(); for( Course c : value.carray ) b.courses.put( c.id, c ); return b; } @Override public Courses marshal( Brochure b ){ Courses courses = new Courses(); Collection<Course> c = b.courses.values(); courses.carray = c.toArray(new Course[c.size()]); return courses; } } Courses is a class JAXB knows how to handle with respect to XML data, and the result of JAXB's innate capabilities is passed to the adaption for unmarshalling. In this method, we convert the data to a structure according to the desired class Brochure with its map. The reverse marshalling process has to convert a Brochure object with its map to a Courses object, which is easily done by putting the map values into an array. To summarize: XML binding happens against the class Courses, whereas application programming uses the Map type field courses in class Brochure.

6.2.10 Type Mapping: XmlSchemaType The annotation XmlSchemaType defines a mapping between an arbitrary Java type and a simple schema built-in type. Most of the time the default mapping is satisfactory, but every now and then an alternative may be more convenient. Let's assume that the processing of chunks of text requires their extension, either after unmarshalling or before the emitting marshalling. For this, a StringBuffer is better than String, which is the default mapping for xs:string. Below are the essential Java classes, one defining TextType as a container for a string, and the type adapter class for the simple conversion between String and StringBuffer. Notice that the latter class is specified in a separate annotation, i.e., XmlJavaTypeAdapter. public class TextType { @XmlElement @XmlSchemaType(name="string") @XmlJavaTypeAdapter( String2StrBuf.class ) public StringBuffer strbuf; } public class String2StrBuf extends XmlAdapter<String,StringBuffer> { @Override public String marshal( StringBuffer strbuf ){ return strbuf.toString(); } @Override public StringBuffer unmarshal( String string ){ return new StringBuffer( string ); } } Within the Java code that unmarshals or marshals an instance document, TextType elements are now StringBuffers, e.g.: TextType text = new TextType(); text.strbuf = new StringBuffer( "This is the house" ); // ... text.strbuf.append( " that Jack built." ); Such a type mapping can be defined either for an individual element or for all occurrences within a package. If you need multiple mappings at package level, you'll have to bundle the XmlSchemaType annotations in an XmlSchemaTypes (note the plural) annotation, and the XmlJavaTypeAdapter annotiations are packed into a single XmlJavaTypeAdapters annotation. 6.2.11 Annotations for Object References: XmlID, XmlIDREF The section Referring to Another XML Element describes the usefulness of using references rather than repeatedly serialized content. Two annotations instruct JAXB to use references: XmlID must define a field of some class with type java.lang.String that is suited to be used as a key, and XmlIDREF is attached to any field that references objects of that class. Both annotations may be used in addition to XmlElement.

We'll illustrate an application of these annotations in a somewhat more sophisticated pattern resulting from the possibility of attaching XmlIDREF to a field of some collection type. In this case, the collection item type must contain an id field. Below is a group of Java classes defining an Item class and a Document class. The latter contains a list of existing items and a Cluster object that wraps a Set<Item> field containing references to some of the items from the list. import javax.xml.bind.annotation.*; public class Item { private String id; private String name; public Item(){} @XmlID public String getId(){ ... } public void setId( String value ){ ... } @XmlElement public String getName(){ ... } public void setName( String value ){ ... } } import java.util.HashSet; import java.util.Set; import javax.xml.bind.annotation.*; public class Cluster { private Set<Item> items; private String title; public Cluster(){ ... } @XmlIDREF public Set<Item> getItems(){ ... } } package elset; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.*; @XmlRootElement public class Document {

private Cluster cluster; private String title; private List<Item> items; public Document(){ ... } @XmlElement public Cluster getCluster(){ ... } public void setCluster( Cluster value ){ ... } @XmlElement public String getTitle(){ ... } public void setTitle( String value ){ ... } @XmlElement public List<Item> getItems(){ ... } }

--- END ---

You might also like