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:
-
Convert the schema document to a WSDL document using the
xsd2wsdl
tool. Generate Java for the types using the
wsdl2java
tool on the generated WSDL document.ImportantYou will get a warning from the
wsdl2java
tool stating that the WSDL document does not define any services. You can ignore this warning.- 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:
The URI scheme, if present, is stripped.
NoteApache 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
.The trailing file type identifier, if present, is stripped.
For example,
\\www.widgetvendor.com\types\widgetTypes.xsd
becomes\\widgetvendor.com\types\widgetTypes
.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"}
.If the first string in the list is an internet domain name, it is decomposed as follows:
-
The leading
www.
is stripped. -
The remaining string is split into its component parts using the
.
as the separator. The order of the list is reversed.
So,
{"www.widegetvendor.com", "types", "widgetTypes"}
becomes{"com", "widegetvendor", "types", "widgetTypes"}
NoteInternet domain names end in one of the following:
.com
,.net
,.edu
,.org
,.gov
, or in one of the two-letter country codes.
-
The leading
The strings are converted into all lower case.
So,
{"com", "widegetvendor", "types", "widgetTypes"}
becomes{"com", "widegetvendor", "types", "widgettypes"}
.The strings are normalized into valid Java package name components as follows:
-
If the strings contain any special characters, the special characters are converted to an underscore(
_
). -
If any of the strings are a Java keyword, the keyword is prefixed with an underscore(
_
). -
If any of the strings begin with a numeral, the string is prefixed with an underscore(
_
).
-
If the strings contain any special characters, the special characters are converted to an underscore(
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
facetFor more information on how enumerations are mapped see Section 34.3, “Enumerations”.
A public
ObjectFactory
class that contains methods for instantiating objects from the schemaFor 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 {
...
}