Red Hat Training

A Red Hat training course is available for Red Hat Fuse

Chapter 32. Basic Data Binding Concepts

Abstract

There are a number of general topics that apply to how Apache CXF handles type mapping.

32.1. Including and Importing Schema Definitions

Overview

Apache CXF supports the including and importing of schema definitions, using the include and import schema tags. These tags enable you to insert definitions from external files or resources into the scope of a schema element. The essential difference between including and importing is:

  • Including brings in definitions that belong to the same target namespace as the enclosing schema element.
  • Importing brings in definitions that belong to a different target namespace from the enclosing schema element.

xsd:include syntax

The include directive has the following syntax:

<include schemaLocation="anyURI" />

The referenced schema, given by anyURI, must either belong to the same target namespace as the enclosing schema, or not belong to any target namespace at all. If the referenced schema does not belong to any target namespace, it is automatically adopted into the enclosing schema’s namespace when it is included.

Example 32.1, “Example of a Schema that Includes Another Schema” shows an example of an XML Schema document that includes another XML Schema document.

Example 32.1. Example of a Schema that Includes Another Schema

<definitions targetNamespace="http://schemas.redhat.com/tests/schema_parser"
             xmlns:tns="http://schemas.redhat.com/tests/schema_parser"
             xmlns:xsd="http://www.w3.org/2001/XMLSchema"
             xmlns="http://schemas.xmlsoap.org/wsdl/">
  <types>
    <schema targetNamespace="http://schemas.redhat.com/tests/schema_parser"
            xmlns="http://www.w3.org/2001/XMLSchema">
      <include schemaLocation="included.xsd"/>
      <complexType name="IncludingSequence">
        <sequence>
          <element name="includedSeq" type="tns:IncludedSequence"/>
        </sequence>
      </complexType>
    </schema>
  </types>
  ...
</definitions>

Example 32.2, “Example of an Included Schema” shows the contents of the included schema file.

Example 32.2. Example of an Included Schema

<schema targetNamespace="http://schemas.redhat.com/tests/schema_parser"
        xmlns="http://www.w3.org/2001/XMLSchema">
  <!-- Included type definitions -->
  <complexType name="IncludedSequence">
    <sequence>
      <element name="varInt" type="int"/>
      <element name="varString" type="string"/>
    </sequence>
  </complexType>
</schema>

xsd:import syntax

The import directive has the following syntax:

<import namespace="namespaceAnyURI"
        schemaLocation="schemaAnyURI" />

The imported definitions must belong to the namespaceAnyURI target namespace. If namespaceAnyURI is blank or remains unspecified, the imported schema definitions are unqualified.

Example 32.3, “Example of a Schema that Imports Another Schema” shows an example of an XML Schema that imports another XML Schema.

Example 32.3. Example of a Schema that Imports Another Schema

<definitions targetNamespace="http://schemas.redhat.com/tests/schema_parser"
             xmlns:tns="http://schemas.redhat.com/tests/schema_parser"
             xmlns:imp="http://schemas.redhat.com/tests/imported_types"
             xmlns:xsd="http://www.w3.org/2001/XMLSchema"
             xmlns="http://schemas.xmlsoap.org/wsdl/">
  <types>
    <schema targetNamespace="http://schemas.redhat.com/tests/schema_parser"
            xmlns="http://www.w3.org/2001/XMLSchema">
      <import namespace="http://schemas.redhat.com/tests/imported_types"
              schemaLocation="included.xsd"/>
      <complexType name="IncludingSequence">
        <sequence>
          <element name="includedSeq" type="imp:IncludedSequence"/>
        </sequence>
      </complexType>
    </schema>
  </types>
  ...
</definitions>

Example 32.4, “Example of an Imported Schema” shows the contents of the imported schema file.

Example 32.4. Example of an Imported Schema

<schema targetNamespace="http://schemas.redhat.com/tests/imported_types"
        xmlns="http://www.w3.org/2001/XMLSchema">
  <!-- Included type definitions -->
  <complexType name="IncludedSequence">
    <sequence>
      <element name="varInt" type="int"/>
      <element name="varString" type="string"/>
    </sequence>
  </complexType>
</schema>

Using non-referenced schema documents

Using types defined in a schema document that is not referenced in the service’s WSDL document is a three step process:

  1. Convert the schema document to a WSDL document using the xsd2wsdl tool.
  2. Generate Java for the types using the wsdl2java tool on the generated WSDL document.

    Important

    You will get a warning from the wsdl2java tool stating that the WSDL document does not define any services. You can ignore this warning.

  3. Add the generated classes to your classpath.

32.2. XML Namespace Mapping

Overview

XML Schema type, group, and element definitions are scoped using namespaces. The namespaces prevent possible naming clashes between entities that use the same name. Java packages serve a similar purpose. Therefore, Apache CXF maps the target namespace of a schema document into a package containing the classes necessary to implement the structures defined in the schema document.

Package naming

The name of the generated package is derived from a schema’s target namespace using the following algorithm:

  1. The URI scheme, if present, is stripped.

    Note

    Apache CXF will only strip the http:, https:, and urn: schemes.

    For example, the namespace http:\\www.widgetvendor.com\types\widgetTypes.xsd becomes \\widgetvendor.com\types\widgetTypes.xsd.

  2. The trailing file type identifier, if present, is stripped.

    For example, \\www.widgetvendor.com\types\widgetTypes.xsd becomes \\widgetvendor.com\types\widgetTypes.

  3. The resulting string is broken into a list of strings using / and : as separators.

    So, \\www.widgetvendor.com\types\widgetTypes becomes the list {"www.widegetvendor.com", "types", "widgetTypes"}.

  4. If the first string in the list is an internet domain name, it is decomposed as follows:

    1. The leading www. is stripped.
    2. The remaining string is split into its component parts using the . as the separator.
    3. The order of the list is reversed.

      So, {"www.widegetvendor.com", "types", "widgetTypes"} becomes {"com", "widegetvendor", "types", "widgetTypes"}

      Note

      Internet domain names end in one of the following: .com, .net, .edu, .org, .gov, or in one of the two-letter country codes.

  5. The strings are converted into all lower case.

    So, {"com", "widegetvendor", "types", "widgetTypes"} becomes {"com", "widegetvendor", "types", "widgettypes"}.

  6. The strings are normalized into valid Java package name components as follows:

    1. If the strings contain any special characters, the special characters are converted to an underscore(_).
    2. If any of the strings are a Java keyword, the keyword is prefixed with an underscore(_).
    3. If any of the strings begin with a numeral, the string is prefixed with an underscore(_).
  7. The strings are concatenated using . as a separator.

    So, {"com", "widegetvendor", "types", "widgettypes"} becomes the package name com.widgetvendor.types.widgettypes.

The XML Schema constructs defined in the namespace http:\\www.widgetvendor.com\types\widgetTypes.xsd are mapped to the Java package com.widgetvendor.types.widgettypes.

Package contents

A JAXB generated package contains the following:

  • A class implementing each complex type defined in the schema

    For more information on complex type mapping see Chapter 35, Using Complex Types.

  • An enum type for any simple types defined using the enumeration facet

    For more information on how enumerations are mapped see Section 34.3, “Enumerations”.

  • A public ObjectFactory class that contains methods for instantiating objects from the schema

    For more information on the ObjectFactory class see Section 32.3, “The Object Factory”.

  • A package-info.java file that provides metadata about the classes in the package

32.3. The Object Factory

Overview

JAXB uses an object factory to provide a mechanism for instantiating instances of JAXB generated constructs. The object factory contains methods for instantiating all of the XML schema defined constructs in the package’s scope. The only exception is that enumerations do not get a creation method in the object factory.

Complex type factory methods

For each Java class generated to implement an XML schema complex type, the object factory contains a method for creating an instance of the class. This method takes the form:

typeName createtypeName();

For example, if your schema contained a complex type named widgetType, Apache CXF generates a class called WidgetType to implement it. Example 32.5, “Complex Type Object Factory Entry” shows the generated creation method in the object factory.

Example 32.5. Complex Type Object Factory Entry

public class ObjectFactory
{
  ...
  WidgetType createWidgetType()
  {
    return new WidgetType();
  }
  ...
}

Element factory methods

For elements that are declared in the schema’s global scope, Apache CXF inserts a factory method into the object factory. As discussed in Chapter 33, Using XML Elements, XML Schema elements are mapped to JAXBElement<T> objects. The creation method takes the form:

public JAXBElement<elementType> createelementName(elementType value);

For example if you have an element named comment of type xsd:string, Apache CXF generates the object factory method shown in Example 32.6, “Element Object Factory Entry”

Example 32.6. Element Object Factory Entry

public class ObjectFactory
{
    ...
    @XmlElementDecl(namespace = "...", name = "comment")
    public JAXBElement<String> createComment(String value) {
        return new JAXBElement<String>(_Comment_QNAME, String.class, null, value);
    }
    ...
}

32.4. Adding Classes to the Runtime Marshaller

Overview

When the Apache CXF runtime reads and writes XML data it uses a map that associates the XML Schema types with their representative Java types. By default, the map contains all of the types defined in the target namespace of the WSDL contract’s schema element. It also contains any types that are generated from the namespaces of any schemas that are imported into the WSDL contract.

The addition of types from namespaces other than the schema namespace used by an application’s schema element is accomplished using the @XmlSeeAlso annotation. If your application needs to work with types that are generated outside the scope of your application’s WSDL document, you can edit the @XmlSeeAlso annotation to add them to the JAXB map.

Using the @XmlSeeAlso annotation

The @XmlSeeAlso annotation can be added to the SEI of your service. It contains a comma separated list of classes to include in the JAXB context. Example 32.7, “Syntax for Adding Classes to the JAXB Context” shows the syntax for using the @XmlSeeAlso annotation.

Example 32.7. Syntax for Adding Classes to the JAXB Context

import javax.xml.bind.annotation.XmlSeeAlso;
     @WebService()
     @XmlSeeAlso({Class1.class, Class2.class, ..., ClassN.class})
     public class GeneratedSEI {
         ...
     }

In cases where you have access to the JAXB generated classes, it is more efficient to use the ObjectFactory classes generated to support the needed types. Including the ObjectFactory class includes all of the classes that are known to the object factory.

Example

Example 32.8, “Adding Classes to the JAXB Context” shows an SEI annotated with @XmlSeeAlso.

Example 32.8. Adding Classes to the JAXB Context

...
import javax.xml.bind.annotation.XmlSeeAlso;
...
    @WebService()
    @XmlSeeAlso({org.apache.schemas.types.test.ObjectFactory.class, org.apache.schemas.tests.group_test.ObjectFactory.class})
    public interface Foo {
        ...
    }