Chapter 38. Customizing How Types are Generated

Abstract

The default JAXB mappings address most of the cases encountered when using XML Schema to define the objects for a Java application. For instances where the default mappings are insufficient, JAXB provides an extensive customization mechanism.

38.1. Basics of Customizing Type Mappings

Overview

The JAXB specification defines a number of XML elements that customize how Java types are mapped to XML Schema constructs. These elements can be specified in-line with XML Schema constructs. If you cannot, or do not want to, modify the XML Schema definitions, you can specify the customizations in external binding document.

Namespace

The elements used to customize the JAXB data bindings are defined in the namespace http://java.sun.com/xml/ns/jaxb. You must add a namespace declaration similar to the one shown in Example 38.1, “JAXB Customization Namespace”. This is added to the root element of all XML documents defining JAXB customizations.

Example 38.1. JAXB Customization Namespace

xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"

Version declaration

When using the JAXB customizations, you must indicate the JAXB version being used. This is done by adding a jaxb:version attribute to the root element of the external binding declaration. If you are using in-line customization, you must include the jaxb:version attribute in the schema element containing the customizations. The value of the attribute is always 2.0.

Example 38.2, “Specifying the JAXB Customization Version” shows an example of the jaxb:version attribute used in a schema element.

Example 38.2. Specifying the JAXB Customization Version

< schema ...
        jaxb:version="2.0">

Using in-line customization

The most direct way to customize how the code generators map XML Schema constructs to Java constructs is to add the customization elements directly to the XML Schema definitions. The JAXB customization elements are placed inside the xsd:appinfo element of the XML schema construct that is being modified.

Example 38.3, “Customized XML Schema” shows an example of a schema containing an in-line JAXB customization.

Example 38.3. Customized XML Schema

<schema targetNamespace="http://widget.com/types/widgetTypes"
        xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
        jaxb:version="2.0">
  <complexType name="size">
    <annotation> <appinfo> <jaxb:class name="widgetSize" /> </appinfo> </annotation>
    <sequence>
      <element name="longSize" type="xsd:string" />
      <element name="numberSize" type="xsd:int" />
    </sequence>
  </complexType>
<schema>

Using an external binding declaration

When you cannot, or do not want to, make changes to the XML Schema document that defines your type, you can specify the customizations using an external binding declaration. An external binding declaration consists of a number of nested jaxb:bindings elements. Example 38.4, “JAXB External Binding Declaration Syntax” shows the syntax of an external binding declaration.

Example 38.4. JAXB External Binding Declaration Syntax

<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="schemaUri" | wsdlLocation="wsdlUri">
    <jaxb:bindings node="nodeXPath">
      binding declaration
    </jaxb:bindings>
    ...
  </jaxb:bindings>
<jaxb:bindings>

The schemaLocation attribute and the wsdlLocation attribute are used to identify the schema document to which the modifications are applied. Use the schemaLocation attribute if you are generating code from a schema document. Use the wsdlLocation attribute if you are generating code from a WSDL document.

The node attribute is used to identify the specific XML schema construct that is to be modified. It is an XPath statement that resolves to an XML Schema element.

Given the schema document widgetSchema.xsd, shown in Example 38.5, “XML Schema File”, the external binding declaration shown in Example 38.6, “External Binding Declaration” modifies the generation of the complex type size.

Example 38.5. XML Schema File

<schema targetNamespace="http://widget.com/types/widgetTypes"
        xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
        version="1.0">
  <complexType name="size">
    <sequence>
      <element name="longSize" type="xsd:string" />
      <element name="numberSize" type="xsd:int" />
    </sequence>
  </complexType>
<schema>

Example 38.6. External Binding Declaration

<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="wsdlSchema.xsd">
    <jaxb:bindings node="xsd:complexType[@name='size']">
        <jaxb:class name="widgetSize" />
    </jaxb:bindings>
  </jaxb:bindings>
<jaxb:bindings>

To instruct the code generators to use the external binging declaration use the wsdl2java tool’s -b binding-file option, as shown below:

wsdl2java -b widgetBinding.xml widget.wsdl

38.2. Specifying the Java Class of an XML Schema Primitive

Overview

By default, XML Schema types are mapped to Java primitive types. While this is the most logical mapping between XML Schema and Java, it does not always meet the requirements of the application developer. You might want to map an XML Schema primitive type to a Java class that can hold extra information, or you might want to map an XML primitive type to a class that allows for simple type substitution.

The JAXB javaType customization element allows you to customize the mapping between an XML Schema primitive type and a Java primitive type. It can be used to customize the mappings at both the global level and the individual instance level. You can use the javaType element as part of a simple type definition or as part of a complex type definition.

When using the javaType customization element you must specify methods for converting the XML representation of the primitive type to and from the target Java class. Some mappings have default conversion methods. For instances where there are no default mappings, Apache CXF provides JAXB methods to ease the development of the required methods.

Syntax

The javaType customization element takes four attributes, as described in Table 38.1, “Attributes for Customizing the Generation of a Java Class for an XML Schema Type”.

Table 38.1. Attributes for Customizing the Generation of a Java Class for an XML Schema Type

AttributeRequiredDescription

name

Yes

Specifies the name of the Java class to which the XML Schema primitive type is mapped. It must be either a valid Java class name or the name of a Java primitive type. You must ensure that this class exists and is accessible to your application. The code generator does not check for this class.

xmlType

No

Specifies the XML Schema primitive type that is being customized. This attribute is only used when the javaType element is used as a child of the globalBindings element.

parseMethod

No

Specifies the method responsible for parsing the string-based XML representation of the data into an instance of the Java class. For more information see the section called “Specifying the converters”.

printMethod

No

Specifies the method responsible for converting a Java object to the string-based XML representation of the data. For more information see the section called “Specifying the converters”.

The javaType customization element can be used in three ways:

  • To modify all instances of an XML Schema primitive type — The javaType element modifies all instances of an XML Schema type in the schema document when it is used as a child of the globalBindings customization element. When it is used in this manner, you must specify a value for the xmlType attribute that identifies the XML Schema primitive type being modified.

    Example 38.7, “Global Primitive Type Customization” shows an in-line global customization that instructs the code generators to use java.lang.Integer for all instances of xsd:short in the schema.

    Example 38.7. Global Primitive Type Customization

    <schema targetNamespace="http://widget.com/types/widgetTypes"
            xmlns="http://www.w3.org/2001/XMLSchema"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
            jaxb:version="2.0">
      <annotation>
        <appinfo>
          <jaxb:globalBindings ...>
            <jaxb:javaType name="java.lang.Integer"
                           xmlType="xsd:short" />
          </globalBindings
        </appinfo>
      </annotation>
      ...
    </schema>
  • To modify a simple type definition — The javaType element modifies the class generated for all instances of an XML simple type when it is applied to a named simple type definition. When using the javaType element to modify a simple type definition, do not use the xmlType attribute.

    Example 38.8, “Binding File for Customizing a Simple Type” shows an external binding file that modifies the generation of a simple type named zipCode.

    Example 38.8. Binding File for Customizing a Simple Type

    <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 wsdlLocation="widgets.wsdl">
        <jaxb:bindings node="xsd:simpleType[@name='zipCode']">
            <jaxb:javaType name="com.widgetVendor.widgetTypes.zipCodeType"
                           parseMethod="com.widgetVendor.widgetTypes.support.parseZipCode"
                           printMethod="com.widgetVendor.widgetTypes.support.printZipCode" />
        </jaxb:bindings>
      </jaxb:bindings>
    <jaxb:bindings>
  • To modify an element or attribute of a complex type definition — The javaType can be applied to individual parts of a complex type definition by including it as part of a JAXB property customization. The javaType element is placed as a child to the property’s baseType element. When using the javaType element to modify a specific part of a complex type definition, do not use the xmlType attribute.

    Example 38.9, “Binding File for Customizing an Element in a Complex Type” shows a binding file that modifies an element of a complex type.

    Example 38.9. Binding File for Customizing an Element in a Complex Type

    <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="enumMap.xsd">
        <jaxb:bindings node="xsd:ComplexType[@name='widgetOrderInfo']">
          <jaxb:bindings node="xsd:element[@name='cost']">
            <jaxb:property>
              <jaxb:baseType>
                <jaxb:javaType name="com.widgetVendor.widgetTypes.costType"
                                parseMethod="parseCost"
                                printMethod="printCost" >
              </jaxb:baseType>
            </jaxb:property>
          </jaxb:bindings>
        </jaxb:bindings>
      </jaxb:bindings>
    <jaxb:bindings>

    For more information on using the baseType element see Section 38.6, “Specifying the Base Type of an Element or an Attribute”.

Specifying the converters

The Apache CXF cannot convert XML Schema primitive types into random Java classes. When you use the javaType element to customize the mapping of an XML Schema primitive type, the code generator creates an adapter class that is used to marshal and unmarshal the customized XML Schema primitive type. A sample adapter class is shown in Example 38.10, “JAXB Adapter Class”.

Example 38.10. JAXB Adapter Class

public class Adapter1 extends XmlAdapter<String, javaType>
{
  public javaType unmarshal(String value)
  {
    return(parseMethod(value));
  }

  public String marshal(javaType value)
  {
    return(printMethod(value));
  }
}

parseMethod and printMethod are replaced by the value of the corresponding parseMethod attribute and printMethod attribute. The values must identify valid Java methods. You can specify the method’s name in one of two ways:

  • A fully qualified Java method name in the form of packagename.ClassName.methodName
  • A simple method name in the form of methodName

    When you only provide a simple method name, the code generator assumes that the method exists in the class specified by the javaType element’s name attribute.

Important

The code generators do not generate parse or print methods. You are responsible for supplying them. For information on developing parse and print methods see the section called “Implementing converters”.

If a value for the parseMethod attribute is not provided, the code generator assumes that the Java class specified by the name attribute has a constructor whose first parameter is a Java String object. The generated adapter’s unmarshal() method uses the assumed constructor to populate the Java object with the XML data.

If a value for the printMethod attribute is not provided, the code generator assumes that the Java class specified by the name attribute has a toString() method. The generated adapter’s marshal() method uses the assumed toString() method to convert the Java object to XML data.

If the javaType element’s name attribute specifies a Java primitive type, or one of the Java primitive’s wrapper types, the code generators use the default converters. For more information on default converters see the section called “Default primitive type converters”.

What is generated

As mentioned in the section called “Specifying the converters”, using the javaType customization element triggers the generation of one adapter class for each customization of an XML Schema primitive type. The adapters are named in sequence using the pattern AdapterN. If you specify two primitive type customizations, the code generators create two adapter classes: Adapter1 and Adapter2.

The code generated for an XML schema construct depends on whether the effected XML Schema construct is a globally defined element or is defined as part of a complex type.

When the XML Schema construct is a globally defined element, the object factory method generated for the type is modified from the default method as follows:

  • The method is decorated with an @XmlJavaTypeAdapter annotation.

    The annotation instructs the runtime which adapter class to use when processing instances of this element. The adapter class is specified as a class object.

  • The default type is replaced by the class specified by the javaType element’s name attribute.

Example 38.11, “Customized Object Factory Method for a Global Element” shows the object factory method for an element affected by the customization shown in Example 38.7, “Global Primitive Type Customization”.

Example 38.11. Customized Object Factory Method for a Global Element

 @XmlElementDecl(namespace = "http://widgetVendor.com/types/widgetTypes", name = "shorty")
 @XmlJavaTypeAdapter(org.w3._2001.xmlschema.Adapter1.class)
 public JAXBElement<Integer> createShorty(Integer value) {
     return new JAXBElement<Integer>(_Shorty_QNAME, Integer.class, null, value);
 }

When the XML Schema construct is defined as part of a complex type, the generated Java property is modified as follows:

  • The property is decorated with an @XmlJavaTypeAdapter annotation.

    The annotation instructs the runtime which adapter class to use when processing instances of this element. The adapter class is specified as a class object.

  • The property’s @XmlElement includes a type property.

    The value of the type property is the class object representing the generated object’s default base type. In the case of XML Schema primitive types, the class is String.

  • The property is decorated with an @XmlSchemaType annotation.

    The annotation identifies the XML Schema primitive type of the construct.

  • The default type is replaced by the class specified by the javaType element’s name attribute.

Example 38.12, “Customized Complex Type” shows the object factory method for an element affected by the customization shown in Example 38.7, “Global Primitive Type Customization”.

Example 38.12. Customized Complex Type

public class NumInventory {

    @XmlElement(required = true, type = String.class) @XmlJavaTypeAdapter(Adapter1.class) @XmlSchemaType(name = "short") protected Integer numLeft;
    @XmlElement(required = true)
    protected String size;

    public Integer getNumLeft() {
        return numLeft;
    }

    public void setNumLeft(Integer value) {
        this.numLeft = value;
    }

    public String getSize() {
        return size;
    }

    public void setSize(String value) {
        this.size = value;
    }

}

Implementing converters

The Apache CXF runtime does not know how to convert XML primitive types to and from the Java class specified by the javaType element, except that it should call the methods specified by the parseMethod attribute and the printMethod attribute. You are responsible for providing implementations of the methods the runtime calls. The implemented methods must be capable of working with the lexical structures of the XML primitive type.

To simplify the implementation of the data conversion methods, Apache CXF provides the javax.xml.bind.DatatypeConverter class. This class provides methods for parsing and printing all of the XML Schema primitive types. The parse methods take string representations of the XML data and they return an instance of the default type defined in Table 34.1, “XML Schema Primitive Type to Java Native Type Mapping”. The print methods take an instance of the default type and they return a string representation of the XML data.

The Java documentation for the DatatypeConverter class can be found at https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/DatatypeConverter.html.

Default primitive type converters

When specifying a Java primitive type, or one of the Java primitive type Wrapper classes, in the javaType element’s name attribute, it is not necessary to specify values for the parseMethod attribute or the printMethod attribute. The Apache CXF runtime substitutes default converters if no values are provided.

The default data converters use the JAXB DatatypeConverter class to parse the XML data. The default converters will also provide any type casting necessary to make the conversion work.

38.3. Generating Java Classes for Simple Types

Overview

By default, named simple types do not result in generated types unless they are enumerations. Elements defined using a simple type are mapped to properties of a Java primitive type.

There are instances when you need to have simple types generated into Java classes, such as is when you want to use type substitution.

To instruct the code generators to generate classes for all globally defined simple types, set the globalBindings customization element’s mapSimpleTypeDef to true.

Adding the customization

To instruct the code generators to create Java classes for named simple types add the globalBinding element’s mapSimpleTypeDef attribute and set its value to true.

Example 38.13, “in-Line Customization to Force Generation of Java Classes for SimpleTypes” shows an in-line customization that forces the code generator to generate Java classes for named simple types.

Example 38.13. in-Line Customization to Force Generation of Java Classes for SimpleTypes

<schema targetNamespace="http://widget.com/types/widgetTypes"
        xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
        jaxb:version="2.0">
  <annotation>
    <appinfo>
      <jaxb:globalBindings mapSimpleTypeDef="true" />
    </appinfo>
  </annotation>
  ...
</schema>

Example 38.14, “Binding File to Force Generation of Constants” shows an external binding file that customizes the generation of simple types.

Example 38.14. Binding File to Force Generation of Constants

<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="types.xsd">
    <jaxb:globalBindings mapSimpleTypeDef="true" />
  <jaxb:bindings>
<jaxb:bindings>
Important

This customization only affects named simple types that are defined in the global scope.

Generated classes

The class generated for a simple type has one property called value. The value property is of the Java type defined by the mappings in Section 34.1, “Primitive Types”. The generated class has a getter and a setter for the value property.

Example 38.16, “Customized Mapping of a Simple Type” shows the Java class generated for the simple type defined in Example 38.15, “Simple Type for Customized Mapping”.

Example 38.15. Simple Type for Customized Mapping

<simpleType name="simpleton">
  <restriction base="xsd:string">
    <maxLength value="10"/>
  </restriction>
</simpleType>

Example 38.16. Customized Mapping of a Simple Type

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "simpleton", propOrder = {"value"})
public class Simpleton {

    @XmlValue
    protected String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

}

38.4. Customizing Enumeration Mapping

Overview

If you want enumerated types that are based on a schema type other than xsd:string, you must instruct the code generator to map it. You can also control the name of the generated enumeration constants.

The customization is done using the jaxb:typesafeEnumClass element along with one or more jaxb:typesafeEnumMember elements.

There might also be instances where the default settings for the code generator cannot create valid Java identifiers for all of the members of an enumeration. You can customize how the code generators handle this by using an attribute of the globalBindings customization.

Member name customizer

If the code generator encounters a naming collision when generating the members of an enumeration or if it cannot create a valid Java identifier for a member of the enumeration, the code generator, by default, generates a warning and does not generate a Java enum type for the enumeration.

You can alter this behavior by adding the globalBinding element’s typesafeEnumMemberName attribute. The typesafeEnumMemberName attribute’s values are described in Table 38.2, “Values for Customizing Enumeration Member Name Generation”.

Table 38.2. Values for Customizing Enumeration Member Name Generation

ValueDescription

skipGeneration(default)

Specifies that the Java enum type is not generated and generates a warning.

generateName

Specifies that member names will be generated following the pattern VALUE_N. N starts off at one, and is incremented for each member of the enumeration.

generateError

Specifies that the code generator generates an error when it cannot map an enumeration to a Java enum type.

Example 38.17, “Customization to Force Type Safe Member Names” shows an in-line customization that forces the code generator to generate type safe member names.

Example 38.17. Customization to Force Type Safe Member Names

<schema targetNamespace="http://widget.com/types/widgetTypes"
        xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
        jaxb:version="2.0">
  <annotation>
    <appinfo>
      <jaxb:globalBindings typesafeEnumMemberName="generateName" />
    </appinfo>
  </annotation>
  ...
</schema>

Class customizer

The jaxb:typesafeEnumClass element specifies that an XML Schema enumeration should be mapped to a Java enum type. It has two attributes that are described in Table 38.3, “Attributes for Customizing a Generated Enumeration Class”. When the jaxb:typesafeEnumClass element is specified in-line, it must be placed inside the xsd:annotation element of the simple type it is modifying.

Table 38.3. Attributes for Customizing a Generated Enumeration Class

AttributeDescription

name

Specifies the name of the generated Java enum type. This value must be a valid Java identifier.

map

Specifies if the enumeration should be mapped to a Java enum type. The default value is true.

Member customizer

The jaxb:typesafeEnumMember element specifies the mapping between an XML Schema enumeration facet and a Java enum type constant. You must use one jaxb:typesafeEnumMember element for each enumeration facet in the enumeration being customized.

When using in-line customization, this element can be used in one of two ways:

  • It can be placed inside the xsd:annotation element of the enumeration facet it is modifying.
  • They can all be placed as children of the jaxb:typesafeEnumClass element used to customize the enumeration.

The jaxb:typesafeEnumMember element has a name attribute that is required. The name attribute specifies the name of the generated Java enum type constant. It’s value must be a valid Java identifier.

The jaxb:typesafeEnumMember element also has a value attribute. The value is used to associate the enumeration facet with the proper jaxb:typesafeEnumMember element. The value of the value attribute must match one of the values of an enumeration facets' value attribute. This attribute is required when you use an external binding specification for customizing the type generation, or when you group the jaxb:typesafeEnumMember elements as children of the jaxb:typesafeEnumClass element.

Examples

Example 38.18, “In-line Customization of an Enumerated Type” shows an enumerated type that uses in-line customization and has the enumeration’s members customized separately.

Example 38.18. In-line Customization of an Enumerated Type

<schema targetNamespace="http://widget.com/types/widgetTypes"
        xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
        jaxb:version="2.0">
  <simpleType name="widgetInteger">
    <annotation>
      <appinfo>
        <jaxb:typesafeEnumClass />
      </appinfo>
    </annotation>
    <restriction base="xsd:int">
      <enumeration value="1">
        <annotation>
          <appinfo>
            <jaxb:typesafeEnumMember name="one" />
          </appinfo>
        </annotation>
      </enumeration>
      <enumeration value="2">
        <annotation>
          <appinfo>
            <jaxb:typesafeEnumMember name="two" />
          </appinfo>
        </annotation>
      </enumeration>
      <enumeration value="3">
        <annotation>
          <appinfo>
            <jaxb:typesafeEnumMember name="three" />
          </appinfo>
        </annotation>
      </enumeration>
      <enumeration value="4">
        <annotation>
          <appinfo>
            <jaxb:typesafeEnumMember name="four" />
          </appinfo>
        </annotation>
      </enumeration>
    </restriction>
  </simpleType>
<schema>

Example 38.19, “In-line Customization of an Enumerated Type Using a Combined Mapping” shows an enumerated type that uses in-line customization and combines the member’s customization in the class customization.

Example 38.19. In-line Customization of an Enumerated Type Using a Combined Mapping

<schema targetNamespace="http://widget.com/types/widgetTypes"
        xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
        jaxb:version="2.0">
  <simpleType name="widgetInteger">
    <annotation>
      <appinfo>
        <jaxb:typesafeEnumClass>
            <jaxb:typesafeEnumMember value="1" name="one" />
            <jaxb:typesafeEnumMember value="2" name="two" />
            <jaxb:typesafeEnumMember value="3" name="three" />
            <jaxb:typesafeEnumMember value="4" name="four" />
        </jaxb:typesafeEnumClass>
      </appinfo>
    </annotation>
    <restriction base="xsd:int">
      <enumeration value="1" />
      <enumeration value="2" />
      <enumeration value="3" />
      <enumeration value="4" >
    </restriction>
  </simpleType>
<schema>

Example 38.20, “Binding File for Customizing an Enumeration” shows an external binding file that customizes an enumerated type.

Example 38.20. Binding File for Customizing an Enumeration

<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="enumMap.xsd">
    <jaxb:bindings node="xsd:simpleType[@name='widgetInteger']">
        <jaxb:typesafeEnumClass>
            <jaxb:typesafeEnumMember value="1" name="one" />
            <jaxb:typesafeEnumMember value="2" name="two" />
            <jaxb:typesafeEnumMember value="3" name="three" />
            <jaxb:typesafeEnumMember value="4" name="four" />
        </jaxb:typesafeEnumClass>
    </jaxb:bindings>
  </jaxb:bindings>
<jaxb:bindings>

38.5. Customizing Fixed Value Attribute Mapping

Overview

By default, the code generators map attributes defined as having a fixed value to normal properties. When using schema validation, Apache CXF can enforce the schema definition (see Section 24.3.4.7, “Schema Validation Type Values”). However, using schema validation increases message processing time.

Another way to map attributes that have fixed values to Java is to map them to Java constants. You can instruct the code generator to map fixed value attributes to Java constants using the globalBindings customization element. You can also customize the mapping of fixed value attributes to Java constants at a more localized level using the property element.

Global customization

You can alter this behavior by adding the globalBinding element’s fixedAttributeAsConstantProperty attribute. Setting this attribute to true instructs the code generator to map any attribute defined using fixed attribute to a Java constant.

Example 38.21, “in-Line Customization to Force Generation of Constants” shows an in-line customization that forces the code generator to generate constants for attributes with fixed values.

Example 38.21. in-Line Customization to Force Generation of Constants

<schema targetNamespace="http://widget.com/types/widgetTypes"
        xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
        jaxb:version="2.0">
  <annotation>
    <appinfo>
      <jaxb:globalBindings fixedAttributeAsConstantProperty="true" />
    </appinfo>
  </annotation>
  ...
</schema>

Example 38.22, “Binding File to Force Generation of Constants” shows an external binding file that customizes the generation of fixed attributes.

Example 38.22. Binding File to Force Generation of Constants

<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="types.xsd">
    <jaxb:globalBindings fixedAttributeAsConstantProperty="true" />
  <jaxb:bindings>
<jaxb:bindings>

Local mapping

You can customize attribute mapping on a per-attribute basis using the property element’s fixedAttributeAsConstantProperty attribute. Setting this attribute to true instructs the code generator to map any attribute defined using fixed attribute to a Java constant.

Example 38.23, “In-Line Customization to Force Generation of Constants” shows an in-line customization that forces the code generator to generate constants for a single attribute with a fixed value.

Example 38.23. In-Line Customization to Force Generation of Constants

<schema targetNamespace="http://widget.com/types/widgetTypes"
        xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
        jaxb:version="2.0">
  <complexType name="widgetAttr">
    <sequence>
      ...
    </sequence>
    <attribute name="fixer" type="xsd:int" fixed="7">
      <annotation> <appinfo> <jaxb:property fixedAttributeAsConstantProperty="true" /> </appinfo> </annotation>
     </attribute>
  </complexType>
  ...
</schema>

Example 38.24, “Binding File to Force Generation of Constants” shows an external binding file that customizes the generation of a fixed attribute.

Example 38.24. Binding File to Force Generation of Constants

<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="types.xsd">
    <jaxb:bindings node="xsd:complexType[@name='widgetAttr']">
      <jaxb:bindings node="xsd:attribute[@name='fixer']">
            <jaxb:property fixedAttributeAsConstantProperty="true" />
        </jaxb:bindings>
    </jaxb:bindings>
  </jaxb:bindings>
<jaxb:bindings>

Java mapping

In the default mapping, all attributes are mapped to standard Java properties with getter and setter methods. When this customization is applied to an attribute defined using the fixed attribute, the attribute is mapped to a Java constant, as shown in Example 38.25, “Mapping of a Fixed Value Attribute to a Java Constant”.

Example 38.25. Mapping of a Fixed Value Attribute to a Java Constant

@XmlAttribute
public final static type NAME = value;

type is determined by mapping the base type of the attribute to a Java type using the mappings described in Section 34.1, “Primitive Types”.

NAME is determined by converting the value of the attribute element’s name attribute to all capital letters.

value is determined by the value of the attribute element’s fixed attribute.

For example, the attribute defined in Example 38.23, “In-Line Customization to Force Generation of Constants” is mapped as shown in Example 38.26, “Fixed Value Attribute Mapped to a Java Constant”.

Example 38.26. Fixed Value Attribute Mapped to a Java Constant

@XmlRootElement(name = "widgetAttr")
public class WidgetAttr {

    ...

  @XmlAttribute
  public final static int FIXER = 7;

  ...

}

38.6. Specifying the Base Type of an Element or an Attribute

Overview

Occasionally you need to customize the class of the object generated for an element, or for an attribute defined as part of an XML Schema complex type. For example, you might want to use a more generalized class of object to allow for simple type substitution.

One way to do this is to use the JAXB base type customization. It allows a developer, on a case by case basis, to specify the class of object generated to represent an element or an attribute. The base type customization allows you to specify an alternate mapping between the XML Schema construct and the generated Java object. This alternate mapping can be a simple specialization or a generalization of the default base class. It can also be a mapping of an XML Schema primitive type to a Java class.

Customization usage

To apply the JAXB base type property to an XML Schema construct use the JAXB baseType customization element. The baseType customization element is a child of the JAXB property element, so it must be properly nested.

Depending on how you want to customize the mapping of the XML Schema construct to Java object, you add either the baseType customization element’s name attribute, or a javaType child element. The name attribute is used to map the default class of the generated object to another class within the same class hierarchy. The javaType element is used when you want to map XML Schema primitive types to a Java class.

Important

You cannot use both the name attribute and a javaType child element in the same baseType customization element.

Specializing or generalizing the default mapping

The baseType customization element’s name attribute is used to redefine the class of the generated object to a class within the same Java class hierarchy. The attribute specifies the fully qualified name of the Java class to which the XML Schema construct is mapped. The specified Java class must be either a super-class or a sub-class of the Java class that the code generator normally generates for the XML Schema construct. For XML Schema primitive types that map to Java primitive types, the wrapper class is used as the default base class for the purpose of customization.

For example, an element defined as being of xsd:int uses java.lang.Integer as its default base class. The value of the name attribute can specify any super-class of Integer such as Number or Object.

For simple type substitution, the most common customization is to map the primitive types to an Object object.

Example 38.27, “In-Line Customization of a Base Type” shows an in-line customization that maps one element in a complex type to a Java Object object.

Example 38.27. In-Line Customization of a Base Type

<complexType name="widgetOrderInfo">
  <all>
    <element name="amount" type="xsd:int" />
     <element name="shippingAdress" type="Address">
      <annotation> <appinfo> <jaxb:property> <jaxb:baseType name="java.lang.Object" /> </jaxb:property> </appinfo> </annotation>
    </element>
    <element name="type" type="xsd:string"/>
  </all>
</complexType>

Example 38.28, “External Binding File to Customize a Base Type” shows an external binding file for the customization shown in Example 38.27, “In-Line Customization of a Base Type”.

Example 38.28. External Binding File to Customize a Base Type

<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="enumMap.xsd">
    <jaxb:bindings node="xsd:ComplexType[@name='widgetOrderInfo']">
      <jaxb:bindings node="xsd:element[@name='shippingAddress']">
        <jaxb:property>
          <jaxb:baseType name="java.lang.Object" />
        </jaxb:property>
      </jaxb:bindings>
    </jaxb:bindings>
  </jaxb:bindings>
<jaxb:bindings>

The resulting Java object’s @XmlElement annotation includes a type property. The value of the type property is the class object representing the generated object’s default base type. In the case of XML Schema primitive types, the class is the wrapper class of the corresponding Java primitive type.

Example 38.29, “Java Class with a Modified Base Class” shows the class generated based on the schema definition in Example 38.28, “External Binding File to Customize a Base Type”.

Example 38.29. Java Class with a Modified Base Class

public class WidgetOrderInfo {

    protected int amount;
    @XmlElement(required = true)
    protected String type;
    @XmlElement(required = true, type = Address.class) protected Object shippingAddress;

    ...
    public Object getShippingAddress() {
        return shippingAddress;
    }

    public void setShippingAddress(Object value) {
        this.shippingAddress = value;
    }

}

Usage with javaType

The javaType element can be used to customize how elements and attributes defined using XML Schema primitive types are mapped to Java objects. Using the javaType element provides a lot more flexibility than simply using the baseType element’s name attribute. The javaType element allows you to map a primitive type to any class of object.

For a detailed description of using the javaType element, see Section 38.2, “Specifying the Java Class of an XML Schema Primitive”.