This section explains some core JAXB customization concepts:
Inline and external customizations
Scope, inheritance, and precedence
Customization syntax
Customization namespace prefix
Customizations to the default JAXB bindings are made in the form of binding declarations passed to the JAXB binding compiler. These binding declarations can be made in either of two ways:
As inline annotations in a source XML schema
As declarations in an external binding customizations file
For some people, using inline customizations is easier because you can see your customizations in the context of the schema to which they apply. Conversely, using an external binding customization file enables you to customize JAXB bindings without having to modify the source schema, and enables you to easily apply customizations to several schema files at once.
You can combine the two types of customizations. For example, you could include a reference to an external binding customizations file in an inline annotation. However, you cannot declare both an inline and external customization on the same schema element.
Each of these types of customization is described in more detail below.
Customizations to JAXB bindings made by means of inline binding declarations in an XML schema file take the form of <xsd:appinfo> elements embedded in schema <xsd:annotation> elements (xsd: is the XML schema namespace prefix, as defined in W3C XML Schema Part 1: Structures). The general form for inline customizations is shown below.
<xs:annotation> <xs:appinfo> . . binding declarations . . </xs:appinfo> </xs:annotation>
Customizations are applied at the location at which they are declared in the schema. For example, a declaration at the level of a particular element would apply to that element only. Note that the XMLSchema namespace prefix must be used with the <annotation> and <appinfo> declaration tags. In the example above, xs: is used as the namespace prefix, so the declarations are tagged <xs:annotation> and <xs:appinfo>.
Customizations to JAXB bindings made by means of an external file containing binding declarations take the general form shown below.
<jxb:bindings schemaLocation = "xs:anyURI"> <jxb:bindings node = "xs:string">* <binding declaration> <jxb:bindings> </jxb:bindings>
schemaLocation is a URI reference to the remote schema.
node is an XPath 1.0 expression that identifies the schema node within schemaLocation to which the given binding declaration is associated.
For example, the first schemaLocation/node declaration in a JAXB binding declarations file specifies the schema name and the root schema node:
<jxb:bindings schemaLocation="po.xsd" node="/xs:schema">
A subsequent schemaLocation/node declaration, say for a simpleType element named ZipCodeType in the above schema, would take the form:
<jxb:bindings node="//xs:simpleType[@name=’ZipCodeType’]">
Binding customization files should be straight ASCII text. The name or extension does not matter, although a typical extension, used in this chapter, is .xjb.
Customization files containing binding declarations are passed to the JAXB Binding compiler, xjc, using the following syntax:
xjc -b file schema
where file is the name of binding customization file, and schema is the name of the schema or schemas you want to pass to the binding compiler.
You can have a single binding file that contains customizations for multiple schemas, or you can break the customizations into multiple bindings files; for example:
xjc schema1.xsd schema2.xsd schema3.xsd -b bindings123.xjb xjc schema1.xsd schema2.xsd schema3.xsd -b bindings1.xjb -b bindings2.xjb -b bindings3.xjb
Note that the ordering of schema files and binding files on the command line does not matter, although each binding customization file must be preceded by its own -b switch on the command line.
For more information about xjc compiler options in general, see JAXB Compiler Options.
There are several rules that apply to binding declarations made in an external binding customization file that do not apply to similar declarations made inline in a source schema:
The binding customization file must begin with the jxb:bindings version attribute, plus attributes for the JAXB and XMLSchema namespaces:
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
The remote schema to which the binding declaration applies must be identified explicitly in XPath notation by means of a jxb:bindings declaration specifying schemaLocation and node attributes:
schemaLocation specifies a URI reference to the remote schema.
node specifies an XPath 1.0 expression that identifies the schema node within schemaLocation to which the given binding declaration is associated; in the case of the initial jxb:bindings declaration in the binding customization file, this node is typically "/xs:schema".
Similarly, individual nodes within the schema to which customizations are to be applied must be specified using XPath notation; for example:
<jxb:bindings node="//xs:complexType[@name=’USAddress’]">
In such cases, the customization is applied to the node by the binding compiler as if the declaration was embedded inline in the node’s <xs:appinfo> element.
To summarize these rules, the external binding element <jxb:bindings> is only recognized for processing by a JAXB binding compiler in three cases:
When its parent is an <xs:appinfo> element.
When it is an ancestor of another <jxb:bindings> element.
When it is the root element of a document. An XML document that has a <jxb:bindings> element as its root is referred to as an external binding declaration file.
Default JAXB bindings can be customized or overridden at four different levels, or scopes.
Figure 17–3 illustrates the inheritance and precedence of customization declarations. Specifically, declarations towards the top of the pyramid inherit and supersede declarations below them. For example, Component declarations inherit from and supersede Definition declarations; Definition declarations inherit and supersede Schema declarations; and Schema declarations inherit and supersede Global declarations.
The syntax for the four types of JAXB binding declarations, as well as the syntax for the XML-to-Java data type binding declarations and the customization namespace prefix, are described below.
Global scope customizations are declared with <globalBindings>. The syntax for global scope customizations is as follows:
<globalBindings> [ collectionType = "collectionType" ] [ fixedAttributeAsConstantProperty = "true" | "false" | "1" | "0" ] [ generateIsSetMethod = "true" | "false" | "1" | "0" ] [ enableFailFastCheck = "true" | "false" | "1" | "0" ] [ choiceContentProperty = "true" | "false" | "1" | "0" ] [ underscoreBinding = "asWordSeparator" | "asCharInWord" ] [ typesafeEnumBase = "typesafeEnumBase" ] [ typesafeEnumMemberName = "generateName" | "generateError" ] [ enableJavaNamingConventions = "true" | "false" | "1" | "0" ] [ bindingStyle = "elementBinding" | "modelGroupBinding" ] [ <javaType> ... </javaType> ]* </globalBindings>
collectionType can be either indexed or any fully qualified class name that implements java.util.List.
fixedAttributeAsConstantProperty can be either true, false, 1, or 0. The default value is false.
generateIsSetMethod can be either true, false, 1, or 0. The default value is false.
enableFailFastCheck can be either true, false, 1, or 0. If enableFailFastCheck is true or 1 and the JAXB implementation supports this optional checking, type constraint checking is performed when setting a property. The default value is false. Please note that the JAXB implementation does not support failfast validation.
choiceContentProperty can be either true, false, 1, or 0. The default value is false. choiceContentProperty is not relevant when the bindingStyle is elementBinding. Therefore, if bindingStyle is specified as elementBinding, then the choiceContentProperty must result in an invalid customization.
underscoreBinding can be either asWordSeparator or asCharInWord. The default value is asWordSeparator.
typesafeEnumBase can be a list of QNames, each of which must resolve to a simple type definition. The default value is xs:NCName. See Typesafe Enumeration Binding Declarations for information about localized mapping of simpleType definitions to Java typesafe enum classes.
typesafeEnumMemberName can be either generateError or generateName. The default value is generateError.
enableJavaNamingConventions can be either true, false, 1, or 0. The default value is true.
bindingStyle can be either elementBinding, or modelGroupBinding. The default value is elementBinding.
<javaType> can be zero or more javaType binding declarations. For more information, see javaType Binding Declarations.
<globalBindings> declarations are only valid in the annotation element of the top-level schema element. There can only be a single instance of a <globalBindings> declaration in any given schema or binding declarations file. If one source schema includes or imports a second source schema, the <globalBindings> declaration must be declared in the first source schema.
Schema scope customizations are declared with <schemaBindings>. The syntax for schema scope customizations is:
<schemaBindings> [ <package> package </package> ] [ <nameXmlTransform> ... </nameXmlTransform> ]* </schemaBindings> <package [ name = "packageName" ] [ <javadoc> ... </javadoc> ] </package> <nameXmlTransform> [ <typeName [ suffix="suffix" ] [ prefix="prefix" ] /> ] [ <elementName [ suffix="suffix" ] [ prefix="prefix" ] /> ] [ <modelGroupName [ suffix="suffix" ] [ prefix="prefix" ] /> ] [ <anonymousTypeName [ suffix="suffix" ] [ prefix="prefix" ] /> ] </nameXmlTransform>
As shown above, <schemaBinding> declarations include two subcomponents:
<package>...</package> specifies the name of the package and, if desired, the location of the API documentation for the schema-derived classes.
<nameXmlTransform>...</nameXmlTransform> specifies customizations to be applied.
The <class> binding declaration enables you to customize the binding of a schema element to a Java content interface or a Java Element interface. <class> declarations can be used to customize:
A name for a schema-derived Java interface
An implementation class for a schema-derived Java content interface
The syntax for <class> customizations is:
<class [ name = "className"] [ implClass= "implClass" ] > [ <javadoc> ... </javadoc> ] </class>
name is the name of the derived Java interface. It must be a legal Java interface name and must not contain a package prefix. The package prefix is inherited from the current value of package.
implClass is the name of the implementation class for className and must include the complete package name.
The <javadoc> element specifies the Javadoc tool annotations for the schema-derived Java interface. The string entered here must use CDATA or < to escape embedded HTML tags.
The <property> binding declaration enables you to customize the binding of an XML schema element to its Java representation as a property. The scope of customization can either be at the definition level or component level depending upon where the <property> binding declaration is specified.
The syntax for <property> customizations is:
<property [ name = "propertyName"] [ collectionType = "propertyCollectionType" ] [ fixedAttributeAsConstantProperty = "true" | "false" | "1" | "0" ] [ generateIsSetMethod = "true" | "false" | "1" | "0" ] [ enableFailFastCheck ="true" | "false" | "1" | "0" ] [ <baseType> ... </baseType> ] [ <javadoc> ... </javadoc> ] </property> <baseType> <javaType> ... </javaType> </baseType>
name defines the customization value propertyName; it must be a legal Java identifier.
collectionType defines the customization value propertyCollectionType, which is the collection type for the property. propertyCollectionType. If specified, can be either indexed or any fully-qualified class name that implements java.util.List.
fixedAttributeAsConstantProperty defines the customization value fixedAttributeAsConstantProperty. The value can be either true, false, 1, or 0.
generateIsSetMethod defines the customization value of generateIsSetMethod. The value can be either true, false, 1, or 0.
enableFailFastCheck defines the customization value enableFailFastCheck. The value can be either true, false, 1, or 0. Please note that the JAXB implementation does not support failfast validation.
<javadoc> customizes the Javadoc tool annotations for the property’s getter method.
The <javaType> declaration provides a way to customize the translation of XML data types to and from Java data types. XML provides more data types than Java, and so the <javaType> declaration lets you specify custom data type bindings when the default JAXB binding cannot sufficiently represent your schema.
The target Java data type can be a Java built-in data type or an application-specific Java data type. If an application-specific data type is used as the target, your implementation must also provide parse and print methods for unmarshalling and marshalling data. To this end, the JAXB specification supports a parseMethod and printMethod:
The parseMethod is called during unmarshalling to convert a string from the input document into a value of the target Java data type.
The printMethod is called during marshalling to convert a value of the target type into a lexical representation.
If you prefer to define your own data type conversions, JAXB defines a static class, DatatypeConverter, to assist in the parsing and printing of valid lexical representations of the XML Schema built-in data types.
The syntax for the <javaType> customization is:
<javaType name= "javaType" [ xmlType= "xmlType" ] [ hasNsContext = "true" | "false" ] [ parseMethod= "parseMethod" ] [ printMethod= "printMethod" ]>
name is the Java data type to which xmlType is to be bound.
xmlType is the name of the XML Schema data type to which javaType is to be bound; this attribute is required when the parent of the <javaType> declaration is <globalBindings>.
hasNsContext allows a namespace context to be specified as a second parameter to a print or a parse method; can be either true, false, 1, or 0. By default, this attribute is false, and in most cases you will not need to change it.
parseMethod is the name of the parse method to be called during unmarshalling.
printMethod is the name of the print method to be called during marshalling.
The <javaType> declaration can be used in:
A <globalBindings> declaration
An annotation element for simple type definitions, GlobalBindings, and <basetype> declarations
A <property> declaration
See MyDatatypeConverter Class for an example of how <javaType> declarations and the DatatypeConverterInterface interface are implemented in a custom data type converter class.
The typesafe enumeration declarations provide a localized way to map XML simpleType elements to Java typesafe enum classes. There are two types of typesafe enumeration declarations you can make:
<typesafeEnumClass> lets you map an entire simpleType class to typesafe enum classes.
<typesafeEnumMember> lets you map just selected members of a simpleType class to typesafe enum classes.
In both cases, there are two primary limitations on this type of customization:
Only simpleType definitions with enumeration facets can be customized using this binding declaration.
This customization only applies to a single simpleType definition at a time. To map sets of similar simpleType definitions on a global level, use the typesafeEnumBase attribute in a <globalBindings> declaration, as described in Global Binding Declarations.
The syntax for the <typesafeEnumClass> customization is:
<typesafeEnumClass [ name = "enumClassName" ] [ <typesafeEnumMember> ... </typesafeEnumMember> ]* [ <javadoc> enumClassJavadoc </javadoc> ] </typesafeEnumClass>
name must be a legal Java Identifier, and must not have a package prefix.
You can have zero or more <typesafeEnumMember> declarations embedded in a <typesafeEnumClass> declaration.
<javadoc> customizes the Javadoc tool annotations for the enumeration class.
The syntax for the <typesafeEnumMember> customization is:
<typesafeEnumMember name = "enumMemberName"> [ value = "enumMemberValue" ] [ <javadoc> enumMemberJavadoc </javadoc> ] </typesafeEnumMember>
name must always be specified and must be a legal Java identifier.
value must be the enumeration value specified in the source schema.
<javadoc> customizes the Javadoc tool annotations for the enumeration constant.
For inline annotations, the <typesafeEnumClass> declaration must be specified in the annotation element of the <simpleType> element. The <typesafeEnumMember> must be specified in the annotation element of the enumeration member. This allows the enumeration member to be customized independently from the enumeration class.
For information about typesafe enum design patterns, see the sample chapter of Joshua Bloch’s Effective Java Programming on the Java Developer Connection.
The <javadoc> declaration lets you add custom Javadoc tool annotations to schema-derived JAXB packages, classes, interfaces, methods, and fields. Note that <javadoc> declarations cannot be applied globally; they are only valid as sub-elements of other binding customizations.
The syntax for the <javadoc> customization is:
<javadoc> Contents in <b>Javadoc<\b> format. </javadoc>
or
<javadoc> <<![CDATA[ Contents in <b>Javadoc<\b> format ]]> </javadoc>
Note that documentation strings in <javadoc> declarations applied at the package level must contain <body> open and close tags; for example:
<jxb:package name="primer.myPo"> <jxb:javadoc> <![CDATA[<body>Package level documentation for generated package primer.myPo.</body>]]> </jxb:javadoc> </jxb:package>
All standard JAXB binding declarations must be preceded by a namespace prefix that maps to the JAXB namespace URI (http://java.sun.com/xml/ns/jaxb). For example, in this sample, jxb: is used. To this end, any schema you want to customize with standard JAXB binding declarations must include the JAXB namespace declaration and JAXB version number at the top of the schema file. For example, in po.xsd for the Customize Inline example, the namespace declaration is as follows:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" jxb:version="1.0">
A binding declaration with the jxb namespace prefix would then take the form:
<xsd:annotation> <xsd:appinfo> <jxb:globalBindings binding declarations /> <jxb:schemaBindings> . . binding declarations . . </jxb:schemaBindings> </xsd:appinfo> </xsd:annotation>
Note that in this example, the globalBindings and schemaBindings declarations are used to specify, respectively, global scope and schema scope customizations. These customization scopes are described in more detail in Scope, Inheritance, and Precedence.