LibraryPrintFeedback

Developing Applications Using JAX-WS

Version 7.1

December 2012
Trademark Disclaimer
Third Party Acknowledgements

Updated: 08 Jan 2014

Table of Contents

I. Starting from Java Code
1. Bottom-Up Service Development
Creating the SEI
Annotating the Code
Required Annotations
Optional Annotations
Defining the Binding Properties with Annotations
Defining Operation Properties with Annotations
Defining Parameter Properties with Annotations
Fuse Services Framework Annotations
WSDL Documentation
Schema Validation of Messages
Specifying the Data Binding
Compressing Messages
Enable Logging on an Endpoint
Adding Properties and Policies to an Endpoint
Generating WSDL
2. Developing a Consumer Without a WSDL Contract
Creating a Service Object
Adding a Port to a Service
Getting a Proxy for an Endpoint
Implementing the Consumer's Business Logic
II. Starting from WSDL
3. A Starting Point WSDL Contract
4. Top-Down Service Development
Generating the Starting Point Code
Implementing the Service Provider
5. Developing a Consumer From a WSDL Contract
Generating the Stub Code
Implementing a Consumer
III. Common Development Tasks
6. Finding WSDL at Runtime
Instantiating a Proxy by Injection
Using a JAX-WS Catalog
Using a contract resolver
7. Generic Fault Handling
Runtime Faults
Protocol Faults
8. Publishing a Service
APIs Used to Publish a Service
Publishing a Service in a Plain Java Application
Publishing a Service in an OSGi Container
IV. Working with Data Types
9. Basic Data Binding Concepts
Including and Importing Schema Definitions
XML Namespace Mapping
The Object Factory
Adding Classes to the Runtime Marshaller
10. Using XML Elements
11. Using Simple Types
Primitive Types
Simple Types Defined by Restriction
Enumerations
Lists
Unions
Simple Type Substitution
12. Using Complex Types
Basic Complex Type Mapping
Attributes
Deriving Complex Types from Simple Types
Deriving Complex Types from Complex Types
Occurrence Constraints
Occurrence Constraints on the All Element
Occurrence Constraints on the Choice Element
Occurrence Constraints on Elements
Occurrence Constraints on Sequences
Using Model Groups
13. Using Wild Card Types
Using Any Elements
Using the XML Schema anyType Type
Using Unbound Attributes
14. Element Substitution
Substitution Groups in XML Schema
Substitution Groups in Java
Widget Vendor Example
The checkWidgets Operation
The placeWidgetOrder Operation
15. Customizing How Types are Generated
Basics of Customizing Type Mappings
Specifying the Java Class of an XML Schema Primitive
Generating Java Classes for Simple Types
Customizing Enumeration Mapping
Customizing Fixed Value Attribute Mapping
Specifying the Base Type of an Element or an Attribute
16. Using A JAXBContext Object
V. Advanced Programming Tasks
17. Using SOAP over JMS
18. Developing Asynchronous Applications
WSDL for Asynchronous Examples
Generating the Stub Code
Implementing an Asynchronous Client with the Polling Approach
Implementing an Asynchronous Client with the Callback Approach
Catching Exceptions Returned from a Remote Service
19. Using Raw XML Messages
Using XML in a Consumer
Usage Modes
Data Types
Working with Dispatch Objects
Using XML in a Service Provider
Messaging Modes
Data Types
Implementing a Provider Object
20. Working with Contexts
Understanding Contexts
Working with Contexts in a Service Implementation
Working with Contexts in a Consumer Implementation
Working with JMS Message Properties
Inspecting JMS Message Headers
Inspecting the Message Header Properties
Setting JMS Properties
21. Writing Handlers
Handlers: An Introduction
Implementing a Logical Handler
Handling Messages in a Logical Handler
Implementing a Protocol Handler
Handling Messages in a SOAP Handler
Initializing a Handler
Handling Fault Messages
Closing a Handler
Releasing a Handler
Configuring Endpoints to Use Handlers
Programmatic Configuration
Adding a Handler Chain to a Consumer
Adding a Handler Chain to a Service Provider
Spring Configuration
A. Maven Tooling Reference
Plug-in Setup — before you can use the Fuse Services Framework plug-ins, you must first add the proper dependencies and repositories to your POM.
cxf-codegen-plugin — generates JAX-WS compliant Java code from a WSDL document
java2ws — generates a WSDL document from Java code
Index

List of Figures

20.1. Message Contexts and Message Processing Path
21.1. Message Exchange Path
21.2. Message Exchange Path with Handlers

List of Tables

1.1. @WebService Properties
1.2. @SOAPBinding Properties
1.3. @WebMethod Properties
1.4. @RequestWrapper Properties
1.5. @ResponseWrapper Properties
1.6. @WebFault Properties
1.7. @WebParam Properties
1.8. @WebResult Properties
1.9. @WSDLDocumentation properties
1.10. @GZIP Properties
1.11. @FastInfoset Properties
1.12. @Logging Properties
1.13. @Policy Properties
4.1. Generated Classes for a Service Provider
6.1. Common JAX-WS Catalog Elements
7.1. APIs that Throw WebServiceException
7.2. Types of Generic Protocol Exceptions
10.1. Attributes Used to Define an Element
10.2. Properties for the @XmlRootElement Annotation
11.1. XML Schema Primitive Type to Java Native Type Mapping
11.2. Primitive Schema Type to Java Wrapper Class Mapping
11.3. List Type Facets
12.1. Elements for Defining How Elements Appear in a Complex Type
12.2. Optional Attributes Used to Define Attributes in XML Schema
13.1. Attributes of the XML Schema Any Element
14.1. Properties for Declaring a JAXB Element is a Member of a Substitution Group
15.1. Attributes for Customizing the Generation of a Java Class for an XML Schema Type
15.2. Values for Customizing Enumeration Member Name Generation
15.3. Attributes for Customizing a Generated Enumeration Class
17.1. JMS URI variants
17.2. JMS properties settable as URI options
19.1. Parameters for createDispatch()
19.2. @WebServiceProvider Properties
20.1. Properties Available in the Service Implementation Context
20.2. Consumer Context Properties
20.3. JMS Header Properties
20.4. Settable JMS Header Properties
21.1. Elements Used to Define a Server-Side Handler Chain

List of Examples

1.1. Simple SEI
1.2. Simple Implementation Class
1.3. Interface with the @WebService Annotation
1.4. Annotated Service Implementation Class
1.5. Specifying a Document Bare SOAP Binding with the SOAP Binding Annotation
1.6. SEI with Annotated Methods
1.7. Fully Annotated SEI
1.8. Using @WSDLDocumentation
1.9. WSDL generated with documentation
1.10. Using @WSDLDocumentationCollection
1.11. Activating schema validation
1.12. Setting the data binding
1.13. Enabling GZIP
1.14. Enabling FastInfoset
1.15. Logging configuration using annotations
1.16. Configuring WS-Security Using @EndpointProperty Annotations
1.17. Configuring WS-Security Using an @EndpointProperties Annotation
1.18. Generating WSDL from Java
1.19. Generated WSDL from an SEI
2.1. Service create() Methods
2.2. Creating a Service Object
2.3. The addPort() Method
2.4. Adding a Port to a Service Object
2.5. The getPort() Method
2.6. Getting a Service Proxy
2.7. Consumer Implemented without a WSDL Contract
3.1. HelloWorld WSDL Contract
4.1. Service Code Generation
4.2. Implementation of the Greeter Service
5.1. Consumer Code Generation
5.2. Outline of a Generated Service Class
5.3. The Greeter Service Endpoint Interface
5.4. Consumer Implementation Code
6.1. Configuration for a Proxy to be Injected into a Service Implementation
6.2. Injecting a Proxy into a Service Implementation
6.3. ServiceContractResolver Interface
6.4. Registering a Contract Resolver
6.5. Service Contract Resolver that can be Registered Using Configuration
6.6. Bean Configuring a Contract Resolver
7.1. Throwing a SOAP Protocol Exception
7.2. Getting the Fault from a SOAP Protocol Exception
8.1. Method for Stopping a Published Endpoint
8.2. Generated Server Mainline
8.3. Custom Server Mainline
8.4. Bundle Activator Interface
8.5. Bundle Activator Start Method for Publishing an Endpoint
8.6. Bundle Activator Stop Method for Stopping an Endpoint
8.7. Bundle Activator Manifest Entry
9.1. Example of a Schema that Includes Another Schema
9.2. Example of an Included Schema
9.3. Example of a Schema that Includes Another Schema
9.4. Example of an Included Schema
9.5. Complex Type Object Factory Entry
9.6. Element Object Factory Entry
9.7. Syntax for Adding Classes to the JAXB Context
9.8. Adding Classes to the JAXB Context
10.1. Simple XML Schema Element Definition
10.2. XML Schema Element Definition with an In-Line Type
10.3. Object Factory Method for a Globally Scoped Element
10.4. Object Factory for a Simple Element
10.5. Using a Globally Scoped Element
10.6. WSDL Using an Element as a Message Part
10.7. Java Method Using a Global Element as a Part
10.8. XML Schema Element with a Default Value
10.9. Object Factory Method for an Element with a Default Value
11.1. Simple type syntax
11.2. Postal Code Simple Type
11.3. Credit Request with Simple Types
11.4. Service Provider Configured to Use Schema Validation
11.5. XML Schema Defined Enumeration
11.6. Generated Enumerated Type for a String Bases XML Schema Enumeration
11.7. List Type Example
11.8. Syntax for XML Schema List Types
11.9. Definition of a List Type
11.10. Alternate Syntax for List Types
11.11. WSDL with a List Type Message Part
11.12. Java Method with a List Type Parameter
11.13. Simple Union Type
11.14. Union with an Anonymous Member Type
12.1. XML Schema Complex Type
12.2. Mapping of an All Complex Type
12.3. Mapping of a Choice Complex Type
12.4. Mapping of a Sequence Complex Type
12.5. XML Schema Defining and Attribute
12.6. Attribute with an In-Line Data Description
12.7. Attribute Group Definition
12.8. Complex Type with an Attribute Group
12.9. techDoc Description
12.10. techDoc Java Class
12.11. dvdType Java Class
12.12. Deriving a Complex Type from a Simple Type by Extension
12.13. Deriving a Complex Type from a Simple Type by Restriction
12.14. idType Java Class
12.15. Deriving a Complex Type by Extension
12.16. Defining a Complex Type by Restriction
12.17. WidgetOrderBillInfo
12.18. Choice Occurrence Constraints
12.19. Java Representation of Choice Structure with an Occurrence Constraint
12.20. Sequence with Occurrence Constraints
12.21. Java Representation of Sequence with an Occurrence Constraint
12.22. XML Schema Model Group
12.23. Complex Type with a Model Group
12.24. Instance of a Type with a Model Group
12.25. Type with a Group
13.1. XML Schema Type Defined with an Any Element
13.2. XML Document with an Any Element
13.3. Complex Type Defined with an Any Element
13.4. Java Class with an Any Element
13.5. Complex Type with a Wild Card Element
13.6. Java Representation of a Wild Card Element
13.7. Complex Type with an Undeclared Attribute
13.8. Examples of Elements Defined with a Wild Card Attribute
13.9. Class for a Complex Type with an Undeclared Attribute
13.10. Working with Undeclared Attributes
14.1. Using a Substitution Group
14.2. Substitution Group with Complex Types
14.3. XML Document using a Substitution Group
14.4. Abstract Head Definition
14.5. Object Factory Method for a Substitution Group
14.6. WSDL Interface Using a Substitution Group
14.7. Generated Interface Using a Substitution Group
14.8. Complex Type Using a Substitution Group
14.9. Java Class for a Complex Type Using a Substitution Group
14.10. Setting a Member of a Substitution Group
14.11. Getting the Value of a Member of the Substitution Group
14.12. Widget Ordering Interface
14.13. Widget Ordering SEI
14.14. Consumer Invoking checkWidgets()
14.15. Service Implementation of checkWidgets()
14.16. Setting a Substitution Group Member
14.17. Implementation of placeWidgetOrder()
15.1. JAXB Customization Namespace
15.2. Specifying the JAXB Customization Version
15.3. Customized XML Schema
15.4. JAXB External Binding Declaration Syntax
15.5. XML Schema File
15.6. External Binding Declaration
15.7. Global Primitive Type Customization
15.8. Binding File for Customizing a Simple Type
15.9. Binding File for Customizing an Element in a Complex Type
15.10. JAXB Adapter Class
15.11. Customized Object Factory Method for a Global Element
15.12. Customized Complex Type
15.13. in-Line Customization to Force Generation of Java Classes for SimpleTypes
15.14. Binding File to Force Generation of Constants
15.15. Simple Type for Customized Mapping
15.16. Customized Mapping of a Simple Type
15.17. Customization to Force Type Safe Member Names
15.18. In-line Customization of an Enumerated Type
15.19. In-line Customization of an Enumerated Type Using a Combined Mapping
15.20. Binding File for Customizing an Enumeration
15.21. in-Line Customization to Force Generation of Constants
15.22. Binding File to Force Generation of Constants
15.23. In-Line Customization to Force Generation of Constants
15.24. Binding File to Force Generation of Constants
15.25. Mapping of a Fixed Value Attribute to a Java Constant
15.26. Fixed Value Attribute Mapped to a Java Constant
15.27. In-Line Customization of a Base Type
15.28. External Binding File to Customize a Base Type
15.29. Java Class with a Modified Base Class
16.1. Getting a JAXB Context Using Classes
16.2. Getting a JAXB Context Using Classes
17.1. JMS URI syntax
17.2. Publishing a SOAP/JMS service
17.3. Consuming a SOAP/JMS service
18.1. WSDL Contract for Asynchronous Example
18.2. Template for an Asynchronous Binding Declaration
18.3. Consumer Code Generation
18.4. WSDL with Embedded Binding Declaration for Asynchronous Mapping
18.5. Service Endpoint Interface with Methods for Asynchronous Invocations
18.6. Non-Blocking Polling Approach for an Asynchronous Operation Call
18.7. Blocking Polling Approach for an Asynchronous Operation Call
18.8. The javax.xml.ws.AsyncHandler Interface
18.9. Callback Implementation Class
18.10. Callback Approach for an Asynchronous Operation Call
18.11. Catching an Exception using the Polling Approach
19.1. The createDispatch() Method
19.2. Creating a Dispatch Object
19.3. The Dispatch.invoke() Method
19.4. Making a Synchronous Invocation Using a Dispatch Object
19.5. The Dispatch.invokeAsync() Method for Polling
19.6. The Dispatch.invokeAsync() Method Using a Callback
19.7. The Dispatch.invokeOneWay() Method
19.8. Making a One Way Invocation Using a Dispatch Object
19.9. Specifying that a Provider Implementation Uses Message Mode
19.10. Specifying that a Provider Implementation Uses Payload Mode
19.11. Provider<SOAPMessage> Implementation
19.12. Provider<DOMSource> Implementation
20.1. The MessageContext.setScope() Method
20.2. Obtaining a Context Object in a Service Implementation
20.3. The MessageContext.get() Method
20.4. Getting a Property from a Service's Message Context
20.5. The MessageContext.put() Method
20.6. Setting a Property in a Service's Message Context
20.7. The getRequestContext() Method
20.8. The getResponseContext() Method
20.9. Getting a Consumer's Request Context
20.10. Reading a Response Context Property
20.11. Setting a Request Context Property
20.12. Getting JMS Message Headers in a Service Implementation
20.13. Getting the JMS Headers from a Consumer Response Header
20.14. Reading the JMS Header Properties
20.15. Setting JMS Properties using the Request Context
21.1. LogicalHandler Synopsis
21.2. Method for Getting the Message Payload in a Logical Handler
21.3. Logical Message Holder
21.4. Getting the Message Body as a JAXB Object
21.5. Updating the Message Body Using a JAXB Object
21.6. Getting the Message's Direction from the SOAP Message Context
21.7. Logical Message Handler Message Processing
21.8. SOAPHandler Synopsis
21.9. The SOAPHander.getHeaders() Method
21.10. The SOAPMessageContext.getHeaders() Method
21.11. Getting the Message's Direction from the SOAP Message Context
21.12. Handling a Message in a SOAP Handler
21.13. Handling a Fault in a Message Handler
21.14. Adding a Handler Chain to a Consumer
21.15. Service Implementation that Loads a Handler Chain
21.16. Handler Configuration File
21.17. Configuring an Endpoint to Use a Handler Chain In Spring

To create a service starting from Java you must do the following:

  1. Create a Service Endpoint Interface (SEI) that defines the methods you want to expose as a service.

    [Tip]Tip

    You can work directly from a Java class, but working from an interface is the recommended approach. Interfaces are better suited for sharing with the developers who are responsible for developing the applications consuming your service. The interface is smaller and does not provide any of the service's implementation details.

  2. Add the required annotations to your code.

  3. Generate the WSDL contract for your service.

    [Tip]Tip

    If you intend to use the SEI as the service's contract, it is not necessary to generate a WSDL contract.

  4. Publish the service as a service provider.

The JAX-WS annotations specify the metadata used to map the SEI to a fully specified service definition. Among the information provided in the annotations are the following:

  • The target namespace for the service.

  • The name of the class used to hold the request message

  • The name of the class used to hold the response message

  • If an operation is a one way operation

  • The binding style the service uses

  • The name of the class used for any custom exceptions

  • The namespaces under which the types used by the service are defined

[Tip]Tip

Most of the annotations have sensible defaults and it is not necessary to provide values for them. However, the more information you provide in the annotations, the better your service definition is specified. A well-specified service definition increases the likelihood that all parts of a distributed application will work together.

The @WebService annotation is defined by the javax.jws.WebService interface and it is placed on an interface or a class that is intended to be used as a service. @WebService has the properties described in Table 1.1


[Tip]Tip

It is not necessary to provide values for any of the @WebService annotation's properties. However, it is recommended that you provide as much information as you can.

The SEI requires that you add the @WebService annotation. Because the SEI is the contract that defines the service, you should specify as much detail as possible about the service in the @WebService annotation's properties.

Example 1.3 shows the interface defined in Example 1.1 with the @WebService annotation.

Example 1.3. Interface with the @WebService Annotation

package com.fusesource.demo;

import javax.jws.*;

@WebService(name="quoteUpdater", 1
            targetNamespace="http:\\demos.fusesource.com", 2
	        serviceName="updateQuoteService", 3
            wsdlLocation="http:\\demos.fusesource.com\quoteExampleService?wsdl", 4
            portName="updateQuotePort") 5
public interface quoteReporter
{
  public Quote getQuote(String ticker);
}

The @WebService annotation in Example 1.3 does the following:

1

Specifies that the value of the name attribute of the wsdl:portType element defining the service interface is quoteUpdater.

2

Specifies that the target namespace of the service is http:\\demos.fusesource.com.

3

Specifies that the value of the name of the wsdl:service element defining the published service is updateQuoteService.

4

Specifies that the service will publish its WSDL contract at http:\\demos.fusesource.com\quoteExampleService?wsdl.

5

Specifies that the value of the name attribute of the wsdl:port element defining the endpoint exposing the service is updateQuotePort.

While the @WebService annotation is sufficient for service enabling a Java interface or a Java class, it does not fully describe how the service will be exposed as a service provider. The JAX-WS programming model uses a number of optional annotations for adding details about your service, such as the binding it uses, to the Java code. You add these annotations to the service's SEI.

[Tip]Tip

The more details you provide in the SEI the easier it is for developers to implement applications that can use the functionality it defines. It also makes the WSDL documents generated by the tools more specific.

The @SOAPBinding annotation is defined by the javax.jws.soap.SOAPBinding interface. It provides details about the SOAP binding used by the service when it is deployed. If the @SOAPBinding annotation is not specified, a service is published using a wrapped doc/literal SOAP binding.

You can put the @SOAPBinding annotation on the SEI and any of the SEI's methods. When it is used on a method, setting of the method's @SOAPBinding annotation take precedence.

Table 1.2 shows the properties for the @SOAPBinding annotation.


The following data bindings are currently supported by Fuse Services Framework:

  • org.apache.cxf.jaxb.JAXBDataBinding

    (Default) The standard JAXB data binding.

  • org.apache.cxf.sdo.SDODataBinding

    The Service Data Objects (SDO) data binding is based on the Apache Tuscany SDO implementation. If you want to use this data binding in the context of a Maven build, you need to add a dependency on the cxf-rt-databinding-sdo artifact.

  • org.apache.cxf.aegis.databinding.AegisDatabinding

    If you want to use this data binding in the context of a Maven build, you need to add a dependency on the cxf-rt-databinding-aegis artifact.

  • org.apache.cxf.xmlbeans.XmlBeansDataBinding

    If you want to use this data binding in the context of a Maven build, you need to add a dependency on the cxf-rt-databinding-xmlbeans artifact.

  • org.apache.cxf.databinding.source.SourceDataBinding

    This data binding belongs to the Apache CXF core.

  • org.apache.cxf.databinding.stax.StaxDataBinding

    This data binding belongs to the Apache CXF core.

Both properties and policies can be used to associate configuration data with an endpoint. The essential difference between them is that properties are a Fuse Services Framework specific configuration mechanism whereas policies are a standard WSDL configuration mechanism. Policies typically originate from WS specifications and standards and they are normally set by defining wsdl:policy elements that appear in the WSDL contract. By contrast, properties are Apache CXF-specific and they are normally set by defining jaxws:properties elements in the Fuse Services Framework Spring configuration file.

It is also possible, however, to define property settings and WSDL policy settings in Java using annotations, as described here.

The @EndpointProperty annotation is defined by the org.apache.cxf.annotations.EndpointProperty interface. It is placed on the SEI.

This annotation adds Apache CXF-specific configuration settings to an endpoint. Endpoint properties can also be specified in a Spring configuration file. For example, to configure WS-Security on an endpoint, you could add endpoint properties using the jaxws:properties element in a Spring configuration file as follows:

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:jaxws="http://cxf.apache.org/jaxws"
   ... >

   <jaxws:endpoint 
      id="MyService"
      address="https://localhost:9001/MyService" 
      serviceName="interop:MyService"
      endpointName="interop:MyServiceEndpoint"
      implementor="com.foo.MyService">
        
      <jaxws:properties>
         <entry key="ws-security.callback-handler" value="interop.client.UTPasswordCallback"/>
         <entry key="ws-security.signature.properties" value="etc/keystore.properties"/>
         <entry key="ws-security.encryption.properties" value="etc/truststore.properties"/>
         <entry key="ws-security.encryption.username" value="useReqSigCert"/>
      </jaxws:properties> 
     
   </jaxws:endpoint> 
</beans>

Alternatively, you could specify the preceding configuration settings in Java by adding @EndpointProperty annotations to the SEI, as shown in Example 1.16.


Example 1.19 shows the WSDL contract that is generated for the SEI shown in Example 1.7.

Example 1.19. Generated WSDL from an SEI

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://demo.eric.org/" 
          xmlns:tns="http://demo.eric.org/" 
		  xmlns:ns1="" 
		  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
		  xmlns:ns2="http://demo.eric.org/types" 
		  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
		  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:types>
    <xsd:schema>
      <xs:complexType name="quote">
        <xs:sequence>
          <xs:element name="ID" type="xs:string" minOccurs="0"/>
          <xs:element name="time" type="xs:string" minOccurs="0"/>
          <xs:element name="val" type="xs:float"/>
        </xs:sequence>
      </xs:complexType>
    </xsd:schema>
  </wsdl:types>
  <wsdl:message name="getStockQuote">
    <wsdl:part name="stockTicker" type="xsd:string">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="getStockQuoteResponse">
    <wsdl:part name="updatedQuote" type="tns:quote">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="quoteReporter">
    <wsdl:operation name="getStockQuote">
      <wsdl:input name="getQuote" message="tns:getStockQuote">
    </wsdl:input>
      <wsdl:output name="getQuoteResponse" message="tns:getStockQuoteResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="quoteReporterBinding" type="tns:quoteReporter">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="getStockQuote">
      <soap:operation style="rpc" />
      <wsdl:input name="getQuote">
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output name="getQuoteResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="quoteReporterService">
    <wsdl:port name="quoteReporterPort" binding="tns:quoteReporterBinding">
      <soap:address location="http://localhost:9000/quoteReporterService" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>



[1] Board is an assumed class whose implementation is left to the reader.

To create a consumer without a WSDL contract you must do the following:

  1. Create a Service object for the service on which the consumer will invoke operations.

  2. Add a port to the Service object.

  3. Get a proxy for the service using the Service object's getPort() method.

  4. Implement the consumer's business logic.

Example 2.2 shows code for creating a Service object for the SEI shown in Example 1.7.

Example 2.2. Creating a Service Object

package com.fusesource.demo;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;

public class Client
{
public static void main(String args[])
  {
1    QName serviceName = new QName("http://demo.fusesource.com", "stockQuoteReporter");
2    Service s = Service.create(serviceName);
   ...
  }
}

The code in Example 2.2 does the following:

1

Builds the QName for the service using the targetNamespace property and the name property of the @WebService annotation.

2

Calls the single parameter create() method to create a new Service object.

[Note]Note

Using the single parameter create() frees you from having any dependencies on accessing a WSDL contract.

The Service class defines an addPort() method, shown in Example 2.3, that is used in cases where there is no WSDL contract available to the consumer implementation. The addPort() method allows you to give a Service object the information, which is typically stored in a wsdl:port element, necessary to create a proxy for a service implementation.


The value of the portName is a QName. The value of its namespace part is the target namespace of the service. The service's target namespace is specified in the targetNamespace property of the @WebService annotation. The value of the QName's local part is the value of wsdl:port element's name attribute. You can determine this value in one of the following ways:

  1. Specify it in the portName property of the @WebService annotation.

  2. Append Port to the value of the name property of the @WebService annotation.

  3. Append Port to the name of the SEI.

The value of the bindingId parameter is a string that uniquely identifies the type of binding used by the endpoint. For a SOAP binding you use the standard SOAP namespace: http://schemas.xmlsoap.org/soap/. If the endpoint is not using a SOAP binding, the value of the bindingId parameter is determined by the binding developer.

The value of the endpointAddress parameter is the address where the endpoint is published. For a SOAP/HTTP endpoint, the address is an HTTP address. Transports other than HTTP use different address schemes.

Example 2.4 shows code for adding a port to the Service object created in Example 2.2.

Example 2.4. Adding a Port to a Service Object

package com.fusesource.demo;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;

public class Client
{
public static void main(String args[])
  {
    ...
1    QName portName = new QName("http://demo.fusesource.com", "stockQuoteReporterPort");
2    s.addPort(portName, 
3              "http://schemas.xmlsoap.org/soap/", 
4              "http://localhost:9000/StockQuote");
    ...
  }
}

The code in Example 2.4 does the following:

1

Creates the QName for the portName parameter.

2

Calls the addPort() method.

3

Specifies that the endpoint uses a SOAP binding.

4

Specifies the address where the endpoint is published.

Example 2.7 shows a consumer for the service defined in Example 1.7.

Example 2.7. Consumer Implemented without a WSDL Contract

package com.fusesource.demo;

import java.io.File;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;

public class Client
{
public static void main(String args[])
  {
    QName serviceName = new QName("http://demo.eric.org", "stockQuoteReporter");
1  Service s = Service.create(serviceName);

    QName portName = new QName("http://demo.eric.org", "stockQuoteReporterPort");
2  s.addPort(portName, "http://schemas.xmlsoap.org/soap/", "http://localhost:9000/EricStockQuote");

3  quoteReporter proxy = s.getPort(portName, quoteReporter.class);

4  Quote quote = proxy.getQuote("ALPHA");
    System.out.println("Stock "+quote.getID()+" is worth "+quote.getVal()+" as of "+quote.getTime());
  }
}

The code in Example 2.7 does the following:

1

Creates a Service object.

2

Adds an endpoint definition to the Service object.

3

Gets a service proxy from the Service object.

4

Invokes an operation on the service proxy.

Example 3.1 shows the HelloWorld WSDL contract. This contract defines a single interface, Greeter, in the wsdl:portType element. The contract also defines the endpoint which will implement the service in the wsdl:port element.

Example 3.1. HelloWorld WSDL Contract

<?xml version="1.0" encoding=";UTF-8"?>
<wsdl:definitions name="HelloWorld"
                  targetNamespace="http://apache.org/hello_world_soap_http"
                  xmlns="http://schemas.xmlsoap.org/wsdl/"
                  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
                  xmlns:tns="http://apache.org/hello_world_soap_http"
                  xmlns:x1="http://apache.org/hello_world_soap_http/types"
                  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <wsdl:types>
    <schema targetNamespace="http://apache.org/hello_world_soap_http/types"
            xmlns="http://www.w3.org/2001/XMLSchema"
            elementFormDefault="qualified"><element name="sayHi">
      <element name="sayHi">
        <complexType>
          <sequence>
            <element name="requestType" type="string"/>
          </sequence>
        </complexType>
      </element>
      <element name="sayHiResponse">
        <complexType>
          <sequence>
            <element name="responseType" type="string"/>
          </sequence>
        </complexType>
      </element>
      <element name="greetMe">
        <complexType>
          <sequence>
            <element name="requestType" type="string"/>
          </sequence>
        </complexType>
      </element>
      <element name="greetMeResponse">
        <complexType>
          <sequence>
            <element name="responseType" type="string"/>
          </sequence>
        </complexType>
      </element>
      <element name="greetMeOneWay">
        <complexType>
          <sequence>
            <element name="requestType" type="string"/>
          </sequence>
        </complexType>
      </element>
      <element name="pingMe">
        <complexType/>
      </element>
      <element name="pingMeResponse">
        <complexType/>
      </element>
      <element name="faultDetail">
        <complexType>
          <sequence>
            <element name="minor" type="short"/>
            <element name="major" type="short"/>
          </sequence>
        </complexType>
      </element>
    </schema>
  </wsdl:types>

  <wsdl:message name="sayHiRequest">
    <wsdl:part element="x1:sayHi" name="in"/>
  </wsdl:message>
  <wsdl:message name="sayHiResponse">
    <wsdl:part element="x1:sayHiResponse" name="out"/>
  </wsdl:message>
  <wsdl:message name="greetMeRequest">
    <wsdl:part element="x1:greetMe" name="in"/>
  </wsdl:message>
  <wsdl:message name="greetMeResponse">
    <wsdl:part element="x1:greetMeResponse" name="out"/>
  </wsdl:message>
  <wsdl:message name="greetMeOneWayRequest">
    <wsdl:part element="x1:greetMeOneWay" name="in"/>
  </wsdl:message>
  <wsdl:message name="pingMeRequest">
    <wsdl:part name="in" element="x1:pingMe"/>
  </wsdl:message>
  <wsdl:message name="pingMeResponse">
    <wsdl:part name="out" element="x1:pingMeResponse"/>
  </wsdl:message>
  <wsdl:message name="pingMeFault">
    <wsdl:part name="faultDetail" element="x1:faultDetail"/>
  </wsdl:message>

  <wsdl:portType name="Greeter">
1    <wsdl:operation name="sayHi">
      <wsdl:input message="tns:sayHiRequest" name="sayHiRequest"/>
      <wsdl:output message="tns:sayHiResponse" name="sayHiResponse"/>
    </wsdl:operation>

2    <wsdl:operation name="greetMe">
      <wsdl:input message="tns:greetMeRequest" name="greetMeRequest"/>
      <wsdl:output message="tns:greetMeResponse" name="greetMeResponse"/>
    </wsdl:operation>

3    <wsdl:operation name="greetMeOneWay">
      <wsdl:input message="tns:greetMeOneWayRequest" name="greetMeOneWayRequest"/>
    </wsdl:operation>

4    <wsdl:operation name="pingMe">
      <wsdl:input name="pingMeRequest" message="tns:pingMeRequest"/>
      <wsdl:output name="pingMeResponse" message="tns:pingMeResponse"/>
      <wsdl:fault name="pingMeFault" message="tns:pingMeFault"/>
    </wsdl:operation>
  </wsdl:portType>

  <wsdl:binding name="Greeter_SOAPBinding" type="tns:Greeter">
    ...
  </wsdl:binding>

  <wsdl:service name="SOAPService">
    <wsdl:port binding="tns:Greeter_SOAPBinding" name="SoapPort">
      <soap:address location="http://localhost:9000/SoapContext/SoapPort"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

The Greeter interface defined in Example 3.1 defines the following operations:

Once you have a WSDL document, the process for developing a JAX-WS service provider is as follows:

  1. Generate starting point code.

  2. Implement the service provider's operations.

  3. Publish the implemented service.

The code generation plug-in generates the following Java packages for the contract shown in Example 3.1:

  • org.apache.hello_world_soap_http — This package is generated from the http://apache.org/hello_world_soap_http target namespace. All of the WSDL entities defined in this namespace (for example, the Greeter port type and the SOAPService service) map to Java classes this Java package.

  • org.apache.hello_world_soap_http.types — This package is generated from the http://apache.org/hello_world_soap_http/types target namespace. All of the XML types defined in this namespace (that is, everything defined in the wsdl:types element of the HelloWorld contract) map to Java classes in this Java package.

The stub files generated by the cxf-codegen-plugin Maven plug-in fall into the following categories:

Example 5.4 shows the code that implements the HelloWorld consumer. The consumer connects to the SoapPort port on the SOAPService service and then proceeds to invoke each of the operations supported by the Greeter port type.

Example 5.4. Consumer Implementation Code

package demo.hw.client;

import java.io.File;
import java.net.URL;
import javax.xml.namespace.QName;
import org.apache.hello_world_soap_http.Greeter;
import org.apache.hello_world_soap_http.PingMeFault;
import org.apache.hello_world_soap_http.SOAPService;

public final class Client {

  private static final QName SERVICE_NAME =
  new QName("http://apache.org/hello_world_soap_http",
            "SOAPService");

  private Client()
  {
  }

  public static void main(String args[]) throws Exception
  {
1 if (args.length == 0)
    {
      System.out.println("please specify wsdl");
      System.exit(1);
    }

2 URL wsdlURL;
    File wsdlFile = new File(args[0]);
    if (wsdlFile.exists())
    {
      wsdlURL = wsdlFile.toURL();
    }
    else
    {
      wsdlURL = new URL(args[0]);
    }

    System.out.println(wsdlURL);
3 SOAPService ss = new SOAPService(wsdlURL,SERVICE_NAME);
4 Greeter port = ss.getSoapPort();
    String resp;

5 System.out.println("Invoking sayHi...");
    resp = port.sayHi();
    System.out.println("Server responded with: " + resp);
    System.out.println();

    System.out.println("Invoking greetMe...");
    resp = port.greetMe(System.getProperty("user.name"));
    System.out.println("Server responded with: " + resp);
    System.out.println();

    System.out.println("Invoking greetMeOneWay...");
    port.greetMeOneWay(System.getProperty("user.name"));
    System.out.println("No response from server as method is OneWay");
    System.out.println();

6 try {
      System.out.println("Invoking pingMe, expecting exception...");
      port.pingMe();
    } catch (PingMeFault ex) {
      System.out.println("Expected exception: PingMeFault has occurred.");
      System.out.println(ex.toString());
    }
    System.exit(0);
  }
}

The Client.main() method from Example 5.4 proceeds as follows:

1

Provided that the Fuse Services Framework runtime classes are on your classpath, the runtime is implicitly initialized. There is no need to call a special function to initialize Fuse Services Framework.

2

The consumer expects a single string argument that gives the location of the WSDL contract for HelloWorld. The WSDL contract's location is stored in wsdlURL.

3

You create a service object using the constructor that requires the WSDL contract's location and service name.

4

Call the appropriate getPortName() method to obtain an instance of the required port. In this case, the SOAPService service supports only the SoapPort port, which implements the Greeter service endpoint interface.

5

The consumer invokes each of the methods supported by the Greeter service endpoint interface.

6

In the case of the pingMe() method, the example code shows how to catch the PingMeFault fault exception.



[2] If the name attribute of the wsdl:service element ends in Service the _Service is not used.

When developing consumers using the JAX-WS APIs you are must provide a hard coded path to the WSDL document that defines your service. While this is OK in a small environment, using hard coded paths does not translate to enterprise deployments.

To address this issue, Fuse Services Framework provides three mechanisms for removing the requirement of using hard coded paths:

[Tip]Tip

Injecting the proxy into your implementation code is generally the best option.

To inject a proxy for an external service into a service provider's implementation do the following:

  1. Deploy the required WSDL documents in a well known location that all parts of the application can access.

    [Tip]Tip

    If you are deploying the application as a WAR file, it is recommended that you place all of the WSDL documents and XML Schema documents in the WEB-INF/wsdl folder of the WAR.

    [Tip]Tip

    If you are deploying the application as a JAR file, it is recommended that you place all of the WSDL documents and XML Schema documents in the META-INF/wsdl folder of the JAR.

  2. Configure a JAX-WS client endpoint for the proxy that is being injected.

  3. Inject the proxy into your service provide using the @Resource annotation.

You can also implement a contract resolver so that it can be added to a client through configuration. The contract resolver is implemented in such a way that when the runtime reads the configuration and instantiates the resolver, the resolver registers itself. Because the runtime handles the initialization, you can decide at runtime if a client needs to use the contract resolver.

To implement a contract resolver so that it can be added to a client through configuration do the following:

Example 6.5 shows a contract resolver implementation that can be added to a client using configuration.


To register the contract resolver with a client you need to add a bean element to the client's configuration. The bean element's class attribute is the name of the class implementing the contract resolver.

Example 6.6 shows a bean for adding a configuration resolver implemented by the org.apache.cxf.demos.myContractResolver class.


Fuse Services Framework provides a number of ways to publish a service as a service provider. How you publish a service depends on the deployment environment you are using. Many of the containers supported by Fuse Services Framework do not require writing logic for publishing endpoints. There are two exceptions:

For detailed information in deploying applications into the supported containers see Configuring Web Service Endpoints.

A service provider is instantiated using an Endpoint object. You instantiate an Endpoint object for your service provider using one of the following methods:

[Important]Important

The implementation object passed to any of the Endpoint creation methods must either be an instance of a class annotated with javax.jws.WebService and meeting the requirements for being an SEI implementation or it must be an instance of a class annotated with javax.xml.ws.WebServiceProvider and implementing the Provider interface.

The code generators -server flag makes the tool generate a simple server mainline. The generated server mainline, as shown in Example 8.2, publishes one service provider for each port element in the specified WSDL contract.

For more information see cxf-codegen-plugin.

Example 8.2 shows a generated server mainline.

Example 8.2. Generated Server Mainline

package org.apache.hello_world_soap_http;

import javax.xml.ws.Endpoint;

public class GreeterServer {

    protected GreeterServer() throws Exception {
        System.out.println("Starting Server");
1        Object implementor = new GreeterImpl();
2        String address = "http://localhost:9000/SoapContext/SoapPort";
3        Endpoint.publish(address, implementor);
    }
    
    public static void main(String args[]) throws Exception { 
        new GreeterServer();
        System.out.println("Server ready..."); 
        
        Thread.sleep(5 * 60 * 1000); 
        System.out.println("Server exiting");
        System.exit(0);
    }
}

The code in Example 8.2 does the following:

1

Instantiates a copy of the service implementation object.

2

Creates the address for the endpoint based on the contents of the address child of the wsdl:port element in the endpoint's contract.

3

Publishes the endpoint.

If you used the Java first development model or you do not want to use the generated server mainline you can write your own. To write your server mainline you must do the following:

  1. Instantiate an javax.xml.ws.Endpoint object for the service provider.

  2. Create an optional server context to use when publishing the service provider.

  3. Publish the service provider using one of the publish() methods.

  4. Stop the service provider when the application is ready to exit.

Example 8.3 shows the code for publishing a service provider.

Example 8.3. Custom Server Mainline

package org.apache.hello_world_soap_http;

import javax.xml.ws.Endpoint;

public class GreeterServer
{
  protected GreeterServer() throws Exception
  {
  }
    
  public static void main(String args[]) throws Exception
  { 
1    GreeterImpl impl = new GreeterImpl();
2    Endpoint endpt.create(impl);
3    endpt.publish("http://localhost:9000/SoapContext/SoapPort");

    boolean done = false;
4   while(!done)
    {
      ...
    }

5   endpt.stop();
    System.exit(0);
  }
}

The code in Example 8.3 does the following:

1

Instantiates a copy of the service's implementation object.

2

Creates an unpublished Endpoint for the service implementation.

3

Publishes the service provider at http://localhost:9000/SoapContext/SoapPort.

4

Loops until the server should be shutdown.

5

Stops the published endpoint.

The bundle activator's start method is where you publish your endpoints. To publish your endpoints the start method must do the following:

  1. Instantiate an javax.xml.ws.Endpoint object for the service provider.

  2. Create an optional server context to use when publishing the service provider.

  3. Publish the service provider using one of the publish() methods.

Example 8.5 shows code for publishing a service provider.


The code in Example 8.5 does the following:

1

Instantiates a copy of the service's implementation object.

2

Creates an unpublished Endpoint for the service implementation.

3

Publish the service provider at http://localhost:9000/SoapContext/SoapPort.

The include directive has the following syntax:

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 9.1 shows an example of an XML Schema document that includes another XML Schema document.


Example 9.2 shows the contents of the included schema file.


The import directive has the following syntax:

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

Example 9.3 shows an example of an XML Schema that imports another XML Schema.


Example 9.4 shows the contents of the imported schema file.


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]Note

    Fuse Services Framework 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]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.

A JAXB generated package contains the following:

In XML Schema elements are defined using element elements. element elements has one required attribute. The name specifies the name of the element as it appears in an XML document.

In addition to the name attribute element elements have the optional attributes listed in Table 10.1.


Example 10.1 shows a simple element definition.


An element can also define its own type using an in-line type definition. In-line types are specified using either a complexType element or a simpleType element. Once you specify whether the type of data is complex or simple, you can define any type of data needed using the tools available for each type of data.

Example 10.2 shows an element definition with an in-line type definition.


By default, globally defined elements are mapped to JAXBElement<T> objects where the template class is determined by the value of the element element's type attribute. For primitive types, the template class is derived using the wrapper class mapping described in Wrapper classes. For complex types, the Java class generated to support the complex type is used as the template class.

To support the mapping and to relieve the developer of unnecessary worry about an element's QName, an object factory method is generated for each globally defined element, as shown in Example 10.3.


For example, the element defined in Example 10.1 results in the object factory method shown in Example 10.4.


Example 10.5 shows an example of using a globally scoped element in Java.


If a globally scoped element is used to define a message part, the generated Java parameter is not an instance of JAXBElement<T>. Instead it is mapped to a regular Java type or class.

Given the WSDL fragment shown in Example 10.6, the resulting method has a parameter of type String.


Example 10.7 shows the generated method signature for the sayHi operation.


XML Schema enumerations where the base type is xsd:string are automatically mapped to Java enum type. You can instruct the code generator to map enumerations with other base types to Java enum types by using the customizations described in Customizing Enumeration Mapping.

The enum type is created as follows:

  1. The name of the type is taken from the name attribute of the simple type definition and converted to a Java identifier.

    In general, this means converting the first character of the XML Schema's name to an uppercase letter. If the first character of the XML Schema's name is an invalid character, an underscrore (_) is prepended to the name.

  2. For each enumeration facet, an enum constant is generated based on the value of the value attribute.

    The constant's name is derived by converting all of the lowercase letters in the value to their uppercase equivalent.

  3. A constructor is generated that takes the Java type mapped from the enumeration's base type.

  4. A public method called value() is generated to access the facet value that is represented by an instance of the type.

    The return type of the value() method is the base type of the XML Schema type.

  5. A public method called fromValue() is generated to create an instance of the enum type based on a facet value.

    The parameter type of the value() method is the base type of the XML Schema type.

  6. The class is decorated with the @XmlEnum annotation.

The enumerated type defined in Example 11.5 is mapped to the enum type shown in Example 11.6.


XML Schema list types are simple types and as such are defined using a simpleType element. The most common syntax used to define a list type is shown in Example 11.8.


The value given for atomicType defines the type of the elements in the list. It can only be one of the built in XML Schema atomic types, like xsd:int or xsd:string, or a user-defined simple type that is not a list.

In addition to defining the type of elements listed in the list type, you can also use facets to further constrain the properties of the list type. Table 11.3 shows the facets used by list types.


For example, the definition for the simpleList element shown in Example 11.7, is shown in Example 11.9.


In addition to the syntax shown in Example 11.8 you can also define a list type using the less common syntax shown in Example 11.10.


You can customize the generation of simple types to facilitate lossless support of simple type substitution in the following ways:

XML Schema complex types are defined using the complexType element. The complexType element wraps the rest of elements used to define the structure of the data. It can appear either as the parent element of a named type definition, or as the child of an element element anonymously defining the structure of the information stored in the element. When the complexType element is used to define a named type, it requires the use of the name attribute. The name attribute specifies a unique identifier for referencing the type.

Complex type definitions that contain one or more elements have one of the child elements described in Table 12.1. These elements determine how the specified elements appear in an instance of the type.


[Note]Note

If a complex type definition only uses attributes, you do not need one of the elements described in Table 12.1.

After deciding how the elements will appear, you define the elements by adding one or more element element children to the definition.

Example 12.1 shows a complex type definition in XML Schema.


XML Schema complex types are mapped to Java classes. Each element in the complex type definition is mapped to a member variable in the Java class. Getter and setter methods are also generated for each element in the complex type.

All generated Java classes are decorated with the @XmlType annotation. If the mapping is for a named complex type, the annotations name is set to the value of the complexType element's name attribute. If the complex type is defined as part of an element definition, the value of the @XmlType annotation's name property is the value of the element element's name attribute.

[Note]Note

As described in Java mapping of elements with an in-line type, the generated class is decorated with the @XmlRootElement annotation if it is generated for a complex type defined as part of an element definition.

To provide the runtime with guidelines indicating how the elements of the XML Schema complex type should be handled, the code generators alter the annotations used to decorate the class and its member variables.

All Complex Type

All complex types are defined using the all element. They are annotated as follows:

  • The @XmlType annotation's propOrder property is empty.

  • Each element is decorated with the @XmlElement annotation.

  • The @XmlElement annotation's required property is set to true.

Example 12.2 shows the mapping for an all complex type with two elements.


Choice Complex Type

Choice complex types are defined using the choice element. They are annotated as follows:

Example 12.3 shows the mapping for a choice complex type with two elements.


Sequence Complex Type

A sequence complex type is defined using the sequence element. It is annotated as follows:

Example 12.4 shows the mapping for the complex type defined in Example 12.1.


Fuse Services Framework supports the use of attribute elements and attributeGroup elements within the scope of a complexType element. When defining structures for an XML document attribute declarations provide a means of adding information that is specified within the tag, not the value that the tag contains. For example, when describing the XML element <value currency="euro">410<\value> in XML Schema the currency attribute is described using an attribute element as shown in Example 12.5.

The attributeGroup element allows you to define a group of reusable attributes that can be referenced by all complex types defined by the schema. For example, if you are defining a series of elements that all use the attributes category and pubDate, you could define an attribute group with these attributes and reference them in all the elements that use them. This is shown in Example 12.7.

When describing data types for use in developing application logic, attributes whose use attribute is set to either optional or required are treated as elements of a structure. For each attribute declaration contained within a complex type description, an element is generated in the class for the attribute, along with the appropriate getter and setter methods.

An XML Schema attribute element has one required attribute, name, that is used to identify the attribute. It also has four optional attributes that are described in Table 12.2.


Example 12.5 shows an attribute element defining an attribute, currency, whose value is a string.


If the type attribute is omitted from the attribute element, the format of the data must be described in-line. Example 12.6 shows an attribute element for an attribute, category, that can take the values autobiography, non-fiction, or fiction.


Using an attribute group in a complex type definition is a two step process:

  1. Define the attribute group.

    An attribute group is defined using an attributeGroup element with a number of attribute child elements. The attributeGroup requires a name attribute that defines the string used to refer to the attribute group. The attribute elements define the members of the attribute group and are specified as shown in Defining an attribute in XML Schema. Example 12.7 shows the description of the attribute group catalogIndecies. The attribute group has two members: category, which is optional, and pubDate, which is required.


  2. Use the attribute group in the definition of a complex type.

    You use attribute groups in complex type definitions by using the attributeGroup element with the ref attribute. The value of the ref attribute is the name given the attribute group that you want to use as part of the type definition. For example if you want to use the attribute group catalogIndecies in the complex type dvdType, you would use <attributeGroup ref="catalogIndecies" /> as shown in Example 12.8.


Attributes are mapped to Java in much the same way that member elements are mapped to Java. Required attributes and optional attributes are mapped to member variables in the generated Java class. The member variables are decorated with the @XmlAttribute annotation. If the attribute is required, the @XmlAttribute annotation's required property is set to true.

The complex type defined in Example 12.9 is mapped to the Java class shown in Example 12.10.



As shown in Example 12.10, the default attribute and the fixed attribute instruct the code generators to add code to the getter method generated for the attribute. This additional code ensures that the specified value is returned if no value is set.

[Important]Important

The fixed attribute is treated the same as the default attribute. If you want the fixed attribute to be treated as a Java constant you can use the customization described in Customizing Fixed Value Attribute Mapping.

Attribute groups are mapped to Java as if the members of the group were explicitly used in the type definition. If the attribute group has three members, and it is used in a complex type, the generated class for that type will include a member variable, along with the getter and setter methods, for each member of the attribute group. For example, the complex type defined in Example 12.8, Fuse Services Framework generates a class containing the member variables category and pubDate to support the members of the attribute group as shown in Example 12.11.


Example 12.13 shows an example of a complex type, idType, that is derived by restriction from xsd:string. The defined type restricts the possible values of xsd:stringto values that are ten characters in length. It also adds an attribute to the type.


As in Example 12.12 the simpleContent element signals that the new type does not contain any children. This example uses a restriction element to constrain the possible values used in the new type. The attribute element adds the element to the new type.

To restrict a complex type use the restriction element to limit the possible values of the base type's elements or attributes. When restricting a complex type you must list all of the elements and attributes of the base type. For each element you can add restrictive attributes to the definition. For example, you can add a maxOccurs attribute to an element to limit the number of times it can occur. You can also use the fixed attribute to force one or more of the elements to have predetermined values.

Example 12.16 shows an example of defining a complex type by restricting another complex type. The restricted type, wallawallaAddress, can only be used for addresses in Walla Walla, Washington because the values for the city element, the state element, and the zipCode element are fixed.


As it does with all complex types, Fuse Services Framework generates a class to represent complex types derived from another complex type. The Java class generated for the derived complex type extends the Java class generated to support the base complex type. The base Java class is also modified to include the @XmlSeeAlso annotation. The base class' @XmlSeeAlso annotation lists all of the classes that extend the base class.

When the new complex type is derived by extension, the generated class will include member variables for all of the added elements and attributes. The new member variables will be generated according to the same mappings as all other elements.

When the new complex type is derived by restriction, the generated class will have no new member variables. The generated class will simply be a shell that does not provide any additional functionality. It is entirely up to you to ensure that the restrictions defined in the XML Schema are enforced.

For example, the schema in Example 12.15 results in the generation of two Java classes: WidgetOrderInfo and WidgetBillOrderInfo. WidgetOrderBillInfo extends WidgetOrderInfo because widgetOrderBillInfo is derived by extension from widgetOrderInfo. Example 12.17 shows the generated class for widgetOrderBillInfo.


XML Schema allows you to specify the occurrence constraints on four of the XML Schema elements that make up a complex type definition:

Unlike single instance choice structures, XML Schema choice structures that can occur multiple times are mapped to a Java class with a single member variable. This single member variable is a List<T> object that holds all of the data for the multiple occurrences of the sequence. For example, if the sequence defined in Example 12.18 occurred two times, then the list would have two items.

The name of the Java class' member variable is derived by concatenating the names of the member elements. The element names are separated by Or and the first letter of the variable name is converted to lower case. For example, the member variable generated from Example 12.18 would be named memberNameOrGuestName.

The type of object stored in the list depends on the relationship between the types of the member elements. For example:

  • If the member elements are of the same type the generated list will contain JAXBElement<T> objects. The base type of the JAXBElement<T> objects is determined by the normal mapping of the member elements' type.

  • If the member elements are of different types and their Java representations implement a common interface, the list will contains objects of the common interface.

  • If the member elements are of different types and their Java representations extend a common base class, the list will contains objects of the common base class.

  • If none of the other conditions are met, the list will contain Object objects.

The generated Java class will only have a getter method for the member variable. The getter method returns a reference to the live list. Any modifications made to the returned list will effect the actual object.

The Java class is decorated with the @XmlType annotation. The annotation's name property is set to the value of the name attribute from the parent element of the XML Schema definition. The annotation's propOrder property contains the single member variable representing the elements in the sequence.

The member variable representing the elements in the choice structure are decorated with the @XmlElements annotation. The @XmlElements annotation contains a comma separated list of @XmlElement annotations. The list has one @XmlElement annotation for each member element defined in the XML Schema definition of the type. The @XmlElement annotations in the list have their name property set to the value of the XML Schema element element's name attribute and their type property set to the Java class resulting from the mapping of the XML Schema element element's type.

Example 12.19 shows the Java mapping for the XML Schema choice structure defined in Example 12.18.


Unlike single instance sequences, XML Schema sequences that can occur multiple times are mapped to a Java class with a single member variable. This single member variable is a List<T> object that holds all of the data for the multiple occurrences of the sequence. For example, if the sequence defined in Example 12.20 occurred two times, then the list would have four items.

The name of the Java class' member variable is derived by concatenating the names of the member elements. The element names are separated by And and the first letter of the variable name is converted to lower case. For example, the member variable generated from Example 12.20 is named nameAndLcid.

The type of object stored in the list depends on the relationship between the types of the member elements. For example:

  • If the member elements are of the same type the generated list will contain JAXBElement<T> objects. The base type of the JAXBElement<T> objects is determined by the normal mapping of the member elements' type.

  • If the member elements are of different types and their Java representations implement a common interface, the list will contains objects of the common interface.

  • If the member elements are of different types and their Java representations extend a common base class, the list will contain objects of the common base class.

  • If none of the other conditions are met, the list will contain Object objects.

The generated Java class only has a getter method for the member variable. The getter method returns a reference to the live list. Any modifications made to the returned list effects the actual object.

The Java class is decorated with the @XmlType annotation. The annotation's name property is set to the value of the name attribute from the parent element of the XML Schema definition. The annotation's propOrder property contains the single member variable representing the elements in the sequence.

The member variable representing the elements in the sequence are decorated with the @XmlElements annotation. The @XmlElements annotation contains a comma separated list of @XmlElement annotations. The list has one @XmlElement annotation for each member element defined in the XML Schema definition of the type. The @XmlElement annotations in the list have their name property set to the value of the XML Schema element element's name attribute and their type property set to the Java class resulting from the mapping of the XML Schema element element's type.

Example 12.21 shows the Java mapping for the XML Schema sequence defined in Example 12.20.


By default, a model group is only mapped to Java artifacts when it is included in a complex type definition. When generating code for a complex type that includes a model group, Fuse Services Framework simply includes the member variables for the model group into the Java class generated for the type. The member variables representing the model group are annotated based on the definitions of the model group.

Example 12.25 shows the Java class generated for the complex type defined in Example 12.23.


The any element can be used when defining sequence complex types and choice complex types. In most cases, the any element is an empty element. It can, however, take an annotation element as a child.

Table 13.1 describes the any element's attributes.


Example 13.3 shows a complex type defined with an any element


XML Schema any elements result in the creation of a Java property named any. The property has associated getter and setter methods. The type of the resulting property depends on the value of the element's processContents attribute. If the any element's processContents attribute is set to skip, the element is mapped to a org.w3c.dom.Element object. For all other values of the processContents attribute an any element is mapped to a Java Object object.

The generated property is decorated with the @XmlAnyElement annotation. This annotation has an optional lax property that instructs the runtime what to do when marshaling the data. Its default value is false which instructs the runtime to automatically marshal the data into a org.w3c.dom.Element object. Setting lax to true instructs the runtime to attempt to marshal the data into JAXB types. When the any element's processContents attribute is set to skip, the lax property is set to its default value. For all other values of the processContents attribute, lax is set to true.

Example 13.4 shows how the complex type defined in Example 13.3 is mapped to a Java class.


The otherAttributes member of the generated class expects to be populated with a Map object. The map is keyed using QNames. Once you get the map , you can access any attributes set on the object and set new attributes on the object.

Example 13.10 shows sample code for working with undeclared attributes.

Example 13.10. Working with Undeclared Attributes

Arbitter judge = new Arbitter();
Map<QName, String> otherAtts = judge.getOtherAttributes(); 1

QName at1 = new QName("test.apache.org", "house"); 2
QName at2 = new QName("test.apache.org", "veteran");

otherAtts.put(at1, "Cape"); 3
otherAtts.put(at2, "false");

String vetStatus = otherAtts.get(at2); 4

The code in Example 13.10 does the following:

1

Gets the map containing the undeclared attributes.

2

Creates QNames to work with the attributes.

3

Sets the values for the attributes into the map.

2

Retrieves the value for one of the attributes.

The elements of a substitution group must be of the same type as the head element or of a type derived from the head element’s type. For example, if the head element is of type xsd:int all members of the substitution group must be of type xsd:int or of a type derived from xsd:int. You can also define a substitution group similar to the one shown in Example 14.2 where the elements of the substitution group are of types derived from the head element’s type.


The head element of the substitution group, widget, is defined as being of type widgetType. Each element of the substitution group extends widgetType to include data that is specific to ordering that type of widget.

Based on the schema in Example 14.2, the part elements in Example 14.3 are valid.


The object factory generated to support a package containing a substitution group has methods for each of the elements in the substitution group. For each of the members of the substitution group, except for the head element, the @XmlElementDecl annotation decorating the object factory method includes two additional properties, as described in Table 14.1.


The object factory method for the head element of the substitution group's @XmlElementDecl contains only the default namespace property and the default name property.

In addition to the element instantiation methods, the object factory contains a method for instantiating an object representing the head element. If the members of the substitution group are all of complex types, the object factory also contains methods for instantiating instances of each complex type used.

Example 14.5 shows the object factory method for the substitution group defined in Example 14.2.


If the head element of a substitution group is used as a message part in one of an operation's messages, the resulting method parameter will be an object of the class generated to support that element. It will not necessarily be an instance of the JAXBElement<? extends T> class. The runtime relies on Java's native type hierarchy to support the type substitution, and Java will catch any attempts to use unsupported types.

To ensure that the runtime knows all of the classes needed to support the element substitution, the SEI is decorated with the @XmlSeeAlso annotation. This annotation specifies a list of classes required by the runtime for marshalling. Fore more information on using the @XmlSeeAlso annotation see Adding Classes to the Runtime Marshaller.

Example 14.7 shows the SEI generated for the interface shown in Example 14.6. The interface uses the substitution group defined in Example 14.2.



[Tip]Tip

The SEI shown in Example 14.7 lists the object factory in the @XmlSeeAlso annotation. Listing the object factory for a namespace provides access to all of the generated classes for that namespace.

How you work with a substitution group depends on whether the code generator mapped the group to a straight Java class or to a JAXBElement<? extends T> class. When the element is simply mapped to an object of the generated value class, you work with the object the same way you work with other Java objects that are part of a type hierarchy. You can substitute any of the subclasses for the parent class. You can inspect the object to determine its exact class, and cast it appropriately.

[Tip]Tip

The JAXB specification recommends that you use the object factory methods for instantiating objects of the generated classes.

When the code generators create a JAXBElement<? extends T> object to hold instances of a substitution group, you must wrap the element's value in a JAXBElement<? extends T> object. The best method to do this is to use the element creation methods provided by the object factory. They provide an easy means for creating an element based on its value.

Example 14.10 shows code for setting an instance of a substitution group.

Example 14.10. Setting a Member of a Substitution Group

ObjectFactory of = new ObjectFactory(); 1
PlasticWidgetType pWidget = of.createPlasticWidgetType(); 2
pWidget.setShape = "round';
pWidget.setColor = "green";
pWidget.setMoldProcess = "injection";

JAXBElement<PlasticWidgetType> widget = of.createPlasticWidget(pWidget); 3

WidgetOrderInfo order = of.createWidgetOrderInfo(); 4
order.setWidget(widget); 5

The code in Example 14.10 does the following:

1

Instantiates an object factory.

2

Instantiates a PlasticWidgetType object.

3

Instantiates a JAXBElement<PlasticWidgetType> object to hold a plastic widget element.

4

Instantiates a WidgetOrderInfo object.

5

Sets the WidgetOrderInfo object's widget to the JAXBElement object holding the plastic widget element.

The object factory methods do not help when extracting the element's value from a JAXBElement<? extends T> object. You must to use the JAXBElement<? extends T> object's getValue() method. The following options determine the type of object returned by the getValue() method:

Example 14.11 shows code retrieving the value from a substitution group. To determine the proper class of the element's value object the example uses the element's getName() method.


This section shows an example of substitution groups being used in Fuse Services Framework to solve a real world application. A service and consumer are developed using the widget substitution group defined in Example 14.2. The service offers two operations: checkWidgets and placeWidgetOrder. Example 14.12 shows the interface for the ordering service.


Example 14.13 shows the generated Java SEI for the interface.


[Note]Note

Because the example only demonstrates the use of substitution groups, some of the business logic is not shown.

The generated method signature uses the Java class supporting the type of the substitution group's head element. Because the member elements of a substitution group are either of the same type as the head element or of a type derived from the head element's type, the Java classes generated to support the members of the substitution group inherit from the Java class generated to support the head element. Java's type hierarchy natively supports using subclasses in place of the parent class.

Because of how Fuse Services Framework generates the types for a substitution group and Java's type hierarchy, the client can invoke checkWidgets() without using any special code. When developing the logic to invoke checkWidgets() you can pass in an object of one of the classes generated to support the widget substitution group.

Example 14.14 shows a consumer invoking checkWidgets().


To invoke placeWidgetOrder() the consumer must construct a widget order containing one element of the widget substitution group. When adding the widget to the order, the consumer should use the object factory methods generated for each element of the substitution group. This ensures that the runtime and the service can correctly process the order. For example, if an order is being placed for a plastic widget, the ObjectFactory.createPlasticWidget() method is used to create the element before adding it to the order.

Example 14.16 shows consumer code for setting the widget property of the WidgetOrderInfo object.

Example 14.16. Setting a Substitution Group Member

ObjectFactory of = new ObjectFactory();

WidgetOrderInfo order = new of.createWidgetOrderInfo();
...
System.out.println();
System.out.println("What color widgets do you want to order?");
String color = reader.readLine(); 
System.out.println();
System.out.println("What shape widgets do you want to order?");
String shape = reader.readLine();
System.out.println(); 
System.out.println("What type of widgets do you want to order?");
System.out.println("1 - Normal");
System.out.println("2 - Wood");
System.out.println("3 - Plastic");
System.out.println("Selection [1-3]");
String selection = reader.readLine();
String trimmed = selection.trim();
char widgetType = trimmed.charAt(0);
switch (widgetType)
{
  case '1':
  {
    WidgetType widget = of.createWidgetType();
    widget.setColor(color);
    widget.setShape(shape);
    JAXB<WidgetType> widgetElement = of.createWidget(widget);
    order.setWidget(widgetElement);
    break; 
  } 
  case '2': 
  { 
    WoodWidgetType woodWidget = of.createWoodWidgetType();
    woodWidget.setColor(color);
    woodWidget.setShape(shape);
    System.out.println(); 
    System.out.println("What type of wood are your widgets?");
    String wood = reader.readLine(); 
    woodWidget.setWoodType(wood);
    JAXB<WoodWidgetType> widgetElement = of.createWoodWidget(woodWidget);
    order.setWoodWidget(widgetElement);
    break; 
  }
  case '3': 
  { 
    PlasticWidgetType plasticWidget = of.createPlasticWidgetType();
    plasticWidget.setColor(color);
    plasticWidget.setShape(shape);
    System.out.println();
    System.out.println("What type of mold to use for your
                        widgets?");
    String mold = reader.readLine();
    plasticWidget.setMoldProcess(mold);
    JAXB<WidgetType> widgetElement = of.createPlasticWidget(plasticWidget);
    order.setPlasticWidget(widgetElement);
    break; 
  }
  default :
    System.out.println("Invaid Widget Selection!!");
    }

The placeWidgetOrder() method receives an order in the form of a WidgetOrderInfo object, processes the order, and returns a bill to the consumer in the form of a WidgetOrderBillInfo object. The orders can be for a plain widget, a plastic widget, or a wooden widget. The type of widget ordered is determined by what type of object is stored in widgetOrderForm object’s widget property. The widget property is a substitution group and can contain a widget element, a woodWidget element, or a plasticWidget element.

The implementation must determine which of the possible elements is stored in the order. This can be accomplished using the JAXBElement<? extends T> object's getName() method to determine the element's QName. The QName can then be used to determine which element in the substitution group is in the order. Once the element included in the bill is known, you can extract its value into the proper type of object.

Example 14.17 shows a possible implementation.

Example 14.17. Implementation of placeWidgetOrder()

public com.widgetvendor.types.widgettypes.WidgetOrderBillInfo placeWidgetOrder(WidgetOrderInfo widgetOrderForm)
{
  ObjectFactory of = new ObjectFactory(); 1

  WidgetOrderBillInfo bill = new WidgetOrderBillInfo() 2

   // Copy the shipping address and the number of widgets
   // ordered from widgetOrderForm to bill
   ...

  int numOrdered = widgetOrderForm.getAmount(); 3

  String elementName = widgetOrderForm.getWidget().getName().getLocalPart(); 4
  if (elementName.equals("woodWidget") 5
  {
    WoodWidgetType widget=order.getWidget().getValue(); 6
    buildWoodWidget(widget, numOrdered);

    // Add the widget info to bill
    JAXBElement<WoodWidgetType> widgetElement = of.createWoodWidget(widget); 7
    bill.setWidget(widgetElement); 8

    float amtDue = numOrdered * 0.75;
    bill.setAmountDue(amtDue); 9
  }
  else if (elementName.equals("plasticWidget")
  {
    PlasticWidgetType widget=order.getWidget().getValue();
    buildPlasticWidget(widget, numOrdered);

    // Add the widget info to bill
    JAXBElement<PlasticWidgetType> widgetElement = of.createPlasticWidget(widget);
    bill.setWidget(widgetElement);

    float amtDue = numOrdered * 0.90;
    bill.setAmountDue(amtDue);
  }
  else
  {
    WidgetType widget=order.getWidget().getValue();
    buildWidget(widget, numOrdered);

    // Add the widget info to bill
    JAXBElement<WidgetType> widgetElement = of.createWidget(widget);
    bill.setWidget(widgetElement);

    float amtDue = numOrdered * 0.30;
    bill.setAmountDue(amtDue);
  }

  return(bill);
}

The code in Example 14.17 does the following:

1

Instantiates an object factory to create elements.

2

Instantiates a WidgetOrderBillInfo object to hold the bill.

3

Gets the number of widgets ordered.

4

Gets the local name of the element stored in the order.

5

Checks to see if the element is a woodWidget element.

6

Extracts the value of the element from the order to the proper type of object.

7

Creates a JAXBElement<T> object placed into the bill.

8

Sets the bill object's widget property.

9

Sets the bill object's amountDue property.

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 15.4 shows the syntax of an external binding declaration.


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 15.5, the external binding declaration shown in Example 15.6 modifies the generation of the complex type size.



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

The javaType customization element takes four attributes, as described in Table 15.1.


The javaType customization element can be used in three ways:

The Fuse Services Framework 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 15.10.


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]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 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 Default primitive type converters.

As mentioned in 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 15.11 shows the object factory method for an element affected by the customization shown in Example 15.7.


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 15.12 shows the object factory method for an element affected by the customization shown in Example 15.7.


Example 15.18 shows an enumerated type that uses in-line customization and has the enumeration's members customized separately.


Example 15.19 shows an enumerated type that uses in-line customization and combines the member's customization in the class customization.


Example 15.20 shows an external binding file that customizes an enumerated type.


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 15.23 shows an in-line customization that forces the code generator to generate constants for a single attribute with a fixed value.


Example 15.24 shows an external binding file that customizes the generation of a fixed attribute.


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.

[Tip]Tip

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

Example 15.27 shows an in-line customization that maps one element in a complex type to a Java Object object.


Example 15.28 shows an external binding file for the customization shown in Example 15.27.


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 15.29 shows the class generated based on the schema definition in Example 15.28.


The SOAP over JMS protocol is defined by the World Wide Web Consortium(W3C) as a way of providing a more reliable transport layer to the customary SOAP/HTTP protocol used by most services. The Fuse Services Framework implementation is fully compliant with the specification and should be compatible with any framework that is also compliant.

This transport uses JNDI to find the JMS destinations. When an operation is invoked, the request is packaged as a SOAP message and sent in the body of a JMS message to the specified destination.

Publishing and consuming SOAP/JMS services differ from SOAP/HTTP services in the following ways:

  • SOAP/JMS service addressed are specified using a special JMS URI

  • you must use the Fuse Services Framework specific factory objects to use SOAP/JMS endpoints

JMS endpoints use a JMS URI as defined in the URI Scheme for JMS 1.0. Example 17.1 shows the syntax for a JMS URI.


Table 17.1 describes the available variants for the JMS URI.


Table 17.2 shows the URI options.


The JAX-WS standard publish() method cannot be used to publish a SOAP/JMS service. Instead, you must use the Fuse Services Framework's JaxWsServerFactoryBean class as shown in Example 17.2.

Example 17.2. Publishing a SOAP/JMS service

1String address = "jms:jndi:dynamicQueues/test.cxf.jmstransport.queue3"
    + "?jndiInitialContextFactory"
    + "=org.apache.activemq.jndi.ActiveMQInitialContextFactory"
    + "&jndiConnectionFactoryName=ConnectionFactory"
    + "&jndiURL=tcp://localhost:61500";
Hello implementor = new HelloImpl();
2JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean();
svrFactory.setServiceClass(Hello.class);
3svrFactory.setAddress(address);
4svrFactory.setTransportId(JMSSpecConstants.SOAP_JMS_SPECIFICIATION_TRANSPORTID);
svrFactory.setServiceBean(implementor);
svrFactory.create();

The code in Example 17.2 does the following:

1

Creates the JMS URI representing t he endpoint's address.

2

Instantiates a JaxWsServerFactoryBean to publish the service.

3

Sets the address field of the factory bean with the JMS URI of the service.

4

Specifies that the service created by the factory will use the SOAP/JMS transport.

The standard JAX-WS APIs cannot be used to consume a SOAP/JMS service. Instead, you must use the Fuse Services Framework's JaxWsProxyFactoryBean class as shown in Example 17.3.

Example 17.3. Consuming a SOAP/JMS service

// Java
public void invoke() throws Exception {
1    String address = "jms:jndi:dynamicQueues/test.cxf.jmstransport.queue3"
        + "?jndiInitialContextFactory"
        + "=org.apache.activemq.jndi.ActiveMQInitialContextFactory"
        + "&jndiConnectionFactoryName=ConnectionFactory&jndiURL=tcp://localhost:61500";
2    JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
3    factory.setAddress(address);
4    factory.setTransportId(JMSSpecConstants.SOAP_JMS_SPECIFICIATION_TRANSPORTID);
    factory.setServiceClass(Hello.class);
    Hello client = (Hello)factory.create();
    String reply = client.sayHi(" HI");
    System.out.println(reply);
}

The code in Example 17.3 does the following:

1

Creates the JMS URI representing t he endpoint's address.

2

Instantiates a JaxWsProxyFactoryBean to create the proxy.

3

Sets the address field of the factory bean with the JMS URI of the service.

4

Specifies that the proxy created by the factory will use the SOAP/JMS transport.

In addition to the usual synchronous mode of invocation, Fuse Services Framework supports two forms of asynchronous invocation:

Example 18.1 shows the WSDL contract that is used for the asynchronous examples. The contract defines a single interface, GreeterAsync, which contains a single operation, greetMeSometime.

Example 18.1. WSDL Contract for Asynchronous Example

<?xml version="1.0" encoding="UTF-8"?><wsdl:definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
                  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
                  xmlns:tns="http://apache.org/hello_world_async_soap_http"
                  xmlns:x1="http://apache.org/hello_world_async_soap_http/types"
                  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                  targetNamespace="http://apache.org/hello_world_async_soap_http"
                  name="HelloWorld">
  <wsdl:types>
    <schema targetNamespace="http://apache.org/hello_world_async_soap_http/types"
            xmlns="http://www.w3.org/2001/XMLSchema"
            xmlns:x1="http://apache.org/hello_world_async_soap_http/types"
            elementFormDefault="qualified">
      <element name="greetMeSometime">
        <complexType>
          <sequence>
            <element name="requestType" type="xsd:string"/>
          </sequence>
        </complexType>
      </element>
      <element name="greetMeSometimeResponse">
        <complexType>
          <sequence>
            <element name="responseType"
                     type="xsd:string"/>
          </sequence>
        </complexType>
      </element>
    </schema>
  </wsdl:types>

  <wsdl:message name="greetMeSometimeRequest">
    <wsdl:part name="in" element="x1:greetMeSometime"/>
  </wsdl:message>
  <wsdl:message name="greetMeSometimeResponse">
    <wsdl:part name="out"
               element="x1:greetMeSometimeResponse"/>
  </wsdl:message>

  <wsdl:portType name="GreeterAsync">
    <wsdl:operation name="greetMeSometime">
      <wsdl:input name="greetMeSometimeRequest"
                  message="tns:greetMeSometimeRequest"/>
      <wsdl:output name="greetMeSometimeResponse"
                   message="tns:greetMeSometimeResponse"/>
    </wsdl:operation>
  </wsdl:portType>

  <wsdl:binding name="GreeterAsync_SOAPBinding"
                type="tns:GreeterAsync">
    ...
  </wsdl:binding>

  <wsdl:service name="SOAPService">
    <wsdl:port name="SoapPort"
               binding="tns:GreeterAsync_SOAPBinding">
      <soap:address location="http://localhost:9000/SoapContext/SoapPort"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

The template for a binding declaration file that switches on asynchronous invocations is shown in Example 18.2.


Where AffectedWSDL specifies the URL of the WSDL contract that is affected by this binding declaration. The AffectedNode is an XPath value that specifies which node (or nodes) from the WSDL contract are affected by this binding declaration. You can set AffectedNode to wsdl:definitions, if you want the entire WSDL contract to be affected. The jaxws:enableAsyncMapping element is set to true to enable the asynchronous invocation feature.

For example, if you want to generate asynchronous methods only for the GreeterAsync interface, you can specify <bindings node="wsdl:definitions/wsdl:portType[@name='GreeterAsync']"> in the preceding binding declaration.

Assuming that the binding declaration is stored in a file, async_binding.xml, you would set up your POM as shown in Example 18.3.


The -b option tells the code generator where to locate the external binding file.

For more information on the code generator see cxf-codegen-plugin.

You can also embed the binding customization directly into the WSDL document defining the service by placing the jaxws:bindings element and its associated jaxws:enableAsynchMapping child directly into the WSDL. You also must add a namespace declaration for the jaxws prefix.

Example 18.4 shows a WSDL file with an embedded binding declaration that activates the asynchronous mapping for an operation.


When embedding the binding declaration into the WSDL document you can control the scope affected by the declaration by changing where you place the declaration. When the declaration is placed as a child of the wsdl:definitions element the code generator creates asynchronous methods for all of the operations defined in the WSDL document. If it is placed as a child of a wsdl:portType element the code generator creates asynchronous methods for all of the operations defined in the interface. If it is placed as a child of a wsdl:operation element the code generator creates asynchronous methods for only that operation.

It is not necessary to pass any special options to the code generator when using embedded declarations. The code generator will recognize them and act accordingly.

The polling approach is the more straightforward of the two approaches to developing an asynchronous application. The client invokes the asynchronous method called OperationNameAsync() and is returned a Response<T> object that it polls for a response. What the client does while it is waiting for a response is depends on the requirements of the application. There are two basic patterns for handling the polling:

  • Non-blocking polling — You periodically check to see if the result is ready by calling the non-blocking Response<T>.isDone() method. If the result is ready, the client processes it. If it not, the client continues doing other things.

  • Blocking polling — You call Response<T>.get() right away, and block until the response arrives (optionally specifying a timeout).

Example 18.6 illustrates using non-blocking polling to make an asynchronous invocation on the greetMeSometime operation defined in Example 18.1. The client invokes the asynchronous operation and periodically checks to see if the result is returned.


The code in Example 18.6 does the following:

1

Invokes the greetMeSometimeAsync() on the proxy.

The method call returns the Response<GreetMeSometimeResponse> object to the client immediately. The Fuse Services Framework runtime handles the details of receiving the reply from the remote endpoint and populating the Response<GreetMeSometimeResponse> object.

[Note]Note

The runtime transmits the request to the remote endpoint's greetMeSometime() method and handles the details of the asynchronous nature of the call transparently. The endpoint, and therefore the service implementation, never worries about the details of how the client intends to wait for a response.

2

Checks to see if a response has arrived by checking the isDone() of the returned Response object.

If the response has not arrived, the client continues working before checking again.

3

When the response arrives, the client retrieves it from the Response object using the get() method.

An alternative approach to making an asynchronous operation invocation is to implement a callback class. You then call the asynchronous remote method that takes the callback object as a parameter. The runtime returns the response to the callback object.

To implement an application that uses callbacks, do the following:

  1. Create a callback class that implements the AsyncHandler interface.

    [Note]Note

    Your callback object can perform any amount of response processing required by your application.

  2. Make remote invocations using the operationNameAsync() that takes the callback object as a parameter and returns a Future<?> object.

  3. If your client requires access to the response data, you can poll the returned Future<?> object's isDone() method to see if the remote endpoint has sent the response.

    [Tip]Tip

    If the callback object does all of the response processing, it is not necessary to check if the response has arrived.

The callback class must implement the javax.xml.ws.AsyncHandler interface. The interface defines a single method:

void handleResponse(Response<T> res);

The Fuse Services Framework runtime calls the handleResponse() method to notify the client that the response has arrived. Example 18.8 shows an outline of the AsyncHandler interface that you must implement.


Example 18.9 shows a callback class for the greetMeSometime operation defined in Example 18.1.

Example 18.9. Callback Implementation Class

package demo.hw.client;

import javax.xml.ws.AsyncHandler;
import javax.xml.ws.Response;

import org.apache.hello_world_async_soap_http.types.*;

public class GreeterAsyncHandler implements AsyncHandler<GreetMeSometimeResponse>
{
1  private GreetMeSometimeResponse reply;

2  public void handleResponse(Response<GreetMeSometimeResponse>
                             response)
  {
    try
    {
      reply = response.get();
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
  }

3  public String getResponse()
  {
    return reply.getResponseType();
  }
}

The callback implementation shown in Example 18.9 does the following:

1

Defines a member variable, response, that holds the response returned from the remote endpoint.

2

Implements handleResponse().

This implementation simply extracts the response and assigns it to the member variable reply.

3

Implements an added method called getResponse().

This method is a convenience method that extracts the data from reply and returns it.

Example 18.10 illustrates a client that uses the callback approach to make an asynchronous call to the GreetMeSometime operation defined in Example 18.1.


The code in Example 18.10 does the following:

1

Instantiates a callback object.

2

Invokes the greetMeSometimeAsync() that takes the callback object on the proxy.

The method call returns the Future<?> object to the client immediately. The Fuse Services Framework runtime handles the details of receiving the reply from the remote endpoint, invoking the callback object's handleResponse() method, and populating the Response<GreetMeSometimeResponse> object.

[Note]Note

The runtime transmits the request to the remote endpoint's greetMeSometime() method and handles the details of the asynchronous nature of the call without the remote endpoint's knowledge. The endpoint, and therefore the service implementation, does not need to worry about the details of how the client intends to wait for a response.

3

Uses the returned Future<?> object's isDone() method to check if the response has arrived from the remote endpoint.

4

Invokes the callback object's getResponse() method to get the response data.

Example 18.11 shows an example of catching an exception using the polling approach.


The code in Example 18.11 does the following:

1

Wraps the call to the Response<T> object's get() method in a try/catch block.

2

Catches a ExecutionException exception.

3

Extracts the cause field from the exception.

If the consumer was using the callback approach the code used to catch the exception would be placed in the callback object where the service's response is extracted.

The Dispatch interface is a low-level JAX-WS API that allows you work directly with raw messages. It accepts and returns messages, or payloads, of a number of types including DOM objects, SOAP messages, and JAXB objects. Because it is a low-level API, the Dispatch interface does not perform any of the message preparation that the higher-level JAX-WS APIs perform. You must ensure that the messages, or payloads, that you pass to the Dispatch object are properly constructed, and make sense for the remote operation being invoked.

Dispatch objects have two usage modes:

The usage mode you specify for a Dispatch object determines the amount of detail that is passed to the user level code.

To use a Dispatch object to invoke a remote service the following sequence should be followed:

  1. Create a Dispatch object.

  2. Construct a request message.

  3. Call the proper invoke() method.

  4. Parse the response message.

To create a Dispatch object do the following:

Example 19.2 shows the code for creating a Dispatch object that works with DOMSource objects in payload mode.


When working with Dispatch objects, requests must be built from scratch. The developer is responsible for ensuring that the messages passed to a Dispatch object match a request that the targeted service provider can process. This requires precise knowledge about the messages used by the service provider and what, if any, header information it requires.

This information can be provided by a WSDL document or an XML Schema document that defines the messages. While service providers vary greatly there are a few guidelines to be followed:

For more information about how services use XML messages see, the WS-I Basic Profile.

Dispatch objects also support asynchronous invocations. As with the higher level asynchronous APIs discussed in Developing Asynchronous Applications, Dispatch objects can use both the polling approach and the callback approach.

When using the polling approach, the invokeAsync() method returns a Response<t> object that can be polled to see if the response has arrived. Example 19.5 shows the signature of the method used to make an asynchronous invocation using the polling approach.


For detailed information on using the polling approach for asynchronous invocations see Implementing an Asynchronous Client with the Polling Approach.

When using the callback approach, the invokeAsync() method takes an AsyncHandler implementation that processes the response when it is returned. Example 19.6 shows the signature of the method used to make an asynchronous invocation using the callback approach.


For detailed information on using the callback approach for asynchronous invocations see Implementing an Asynchronous Client with the Callback Approach.

[Note]Note

As with the synchronous invoke() method, the type of the response and the type of the request are determined when you create the Dispatch object.

The Provider interface is a low-level JAX-WS API that allows you to implement a service provider that works directly with messages as raw XML. The messages are not packaged into JAXB objects before being passed to an object that implements the Provider interface.

Objects that implement the Provider interface have two messaging modes:

The messaging mode you specify determines the level of messaging detail that is passed to your implementation.

A Provider implementation can accept and return objects that are derived from the javax.xml.transform.Source interface. Source objects are low level objects that hold XML documents. Each Source implementation provides methods that access the stored XML documents and manipulate its contents. The following objects implement the Source interface:

DOMSource

Holds XML messages as a Document Object Model(DOM) tree. The XML message is stored as a set of Node objects that are accessed using the getNode() method. Nodes can be either updated or added to the DOM tree using the setNode() method.

SAXSource

Holds XML messages as a Simple API for XML (SAX) object. SAX objects contain an InputSource object that holds the raw data and an XMLReader object that parses the raw data.

StreamSource

Holds XML messages as a data stream. The data stream can be manipulated the same as any other data stream.

If you create your Provider object so that it uses generic Source objects, Fuse Services Framework returns the messages as SAXSource objects.

This behavior can be changed using the endpoint's source-preferred-format property. See Configuring Web Service Endpoints for information about configuring the Fuse Services Framework runtime.

[Important]Important

When using Source objects the developer is responsible for ensuring that all required binding specific wrappers are added to the message. For example, when interacting with a service expecting SOAP messages, the developer must ensure that the required SOAP envelope is added to the outgoing request and that the SOAP envelope's contents are correct.

Unlike the higher-level SEI based service implementations, Provider implementations receive requests as raw XML data, and must send responses as raw XML data. This requires that the developer has intimate knowledge of the messages used by the service being implemented. These details can typically be found in the WSDL document describing the service.

WS-I Basic Profile provides guidelines about the messages used by services, including:

  • The root element of a request is based in the value of the name attribute of the wsdl:operation element that corresponds to the operation that is invoked.

    [Warning]Warning

    If the service uses doc/literal bare messages, the root element of the request is based on the value of name attribute of the wsdl:part element referred to by the wsdl:operation element.

  • The root element of all messages is namespace qualified.

  • If the service uses rpc/literal messages, the top-level elements in the messages are not namespace qualified.

    [Important]Important

    The children of top-level elements might be namespace qualified, but to be certain you will must check their schema definitions.

  • If the service uses rpc/literal messages, none of the top-level elements can be null.

  • If the service uses doc/literal messages, then the schema definition of the message determines if any of the elements are namespace qualified.

Example 19.11 shows a Provider implementation that works with SOAPMessage objects in message mode.

Example 19.11. Provider<SOAPMessage> Implementation

import javax.xml.ws.Provider;
import javax.xml.ws.Service;
import javax.xml.ws.ServiceMode;
import javax.xml.ws.WebServiceProvider;

1@WebServiceProvider(portName="stockQuoteReporterPort"
                    serviceName="stockQuoteReporter")
2@ServiceMode(value="Service.Mode.MESSAGE")
public class  stockQuoteReporterProvider implements Provider<SOAPMessage>
{
3public stockQuoteReporterProvider()
  {
  }

4public SOAPMessage invoke(SOAPMessage request)
  {
5  SOAPBody requestBody = request.getSOAPBody();
6  if(requestBody.getElementName.getLocalName.equals("getStockPrice"))
    {
7    MessageFactory mf = MessageFactory.newInstance();
      SOAPFactory sf = SOAPFactory.newInstance();

8    SOAPMessage response = mf.createMessage();
      SOAPBody respBody = response.getSOAPBody();
      Name bodyName = sf.createName("getStockPriceResponse");
      respBody.addBodyElement(bodyName);
      SOAPElement respContent = respBody.addChildElement("price");
      respContent.setValue("123.00");
      response.saveChanges();
9    return response;
    }
    ...
  }
}

The code in Example 19.11 does the following:

1

Specifies that the following class implements a Provider object that implements the service whose wsdl:service element is named stockQuoteReporter, and whose wsdl:port element is named stockQuoteReporterPort.

2

Specifies that this Provider implementation uses message mode.

3

Provides the required default public constructor.

4

Provides an implementation of the invoke() method that takes a SOAPMessage object and returns a SOAPMessage object.

5

Extracts the request message from the body of the incoming SOAP message.

6

Checks the root element of the request message to determine how to process the request.

7

Creates the factories required for building the response.

8

Builds the SOAP message for the response.

9

Returns the response as a SOAPMessage object.

Example 19.12 shows an example of a Provider implementation using DOMSource objects in payload mode.

Example 19.12. Provider<DOMSource> Implementation

import javax.xml.ws.Provider;
import javax.xml.ws.Service;
import javax.xml.ws.ServiceMode;
import javax.xml.ws.WebServiceProvider;

1@WebServiceProvider(portName="stockQuoteReporterPort" serviceName="stockQuoteReporter")
2@ServiceMode(value="Service.Mode.PAYLOAD")
public class  stockQuoteReporterProvider implements Provider<DOMSource>
3public stockQuoteReporterProvider()
  {
  }

4public DOMSource invoke(DOMSource request)
  {
    DOMSource response = new DOMSource();
    ...
    return response;
  }
}

The code in Example 19.12 does the following:

1

Specifies that the class implements a Provider object that implements the service whose wsdl:service element is named stockQuoteReporter, and whose wsdl:port element is named stockQuoteReporterPort.

2

Specifies that this Provider implementation uses payload mode.

3

Provides the required default public constructor.

4

Provides an implementation of the invoke() method that takes a DOMSource object and returns a DOMSource object.

Table 20.1 lists the properties accessible through the context in a service implementation object.

Table 20.1. Properties Available in the Service Implementation Context

Base Class
Property NameDescription
org.apache.cxf.message.Message
PROTOCOL_HEADERS[a]Specifies the transport specific header information. The value is stored as a java.util.Map<String, List<String>>.
RESPONSE_CODE[a]Specifies the response code returned to the consumer. The value is stored as an Integer object.
ENDPOINT_ADDRESSSpecifies the address of the service provider. The value is stored as a String.
HTTP_REQUEST_METHOD[a]Specifies the HTTP verb sent with a request. The value is stored as a String.
PATH_INFO[a]

Specifies the path of the resource being requested. The value is stored as a String.

The path is the portion of the URI after the hostname and before any query string. For example, if an endpoint's URI is http://cxf.apache.org/demo/widgets the path is /demo/widgets.

QUERY_STRING[a]

Specifies the query, if any, attached to the URI used to invoke the request. The value is stored as a String.

Queries appear at the end of the URI after a ?. For example, if a request is made to http://cxf.apache.org/demo/widgets?color the query is color.

MTOM_ENABLEDSpecifies whether or not the service provider can use MTOM for SOAP attachments. The value is stored as a Boolean.
SCHEMA_VALIDATION_ENABLEDSpecifies whether or not the service provider validates messages against a schema. The value is stored as a Boolean.
FAULT_STACKTRACE_ENABLEDSpecifies if the runtime provides a stack trace along with a fault message. The value is stored as a Boolean.
CONTENT_TYPESpecifies the MIME type of the message. The value is stored as a String.
BASE_PATH

Specifies the path of the resource being requested. The value is stored as a java.net.URL.

The path is the portion of the URI after the hostname and before any query string. For example, if an endpoint's URL is http://cxf.apache.org/demo/widgets the base path is /demo/widgets.

ENCODINGSpecifies the encoding of the message. The value is stored as a String.
FIXED_PARAMETER_ORDERSpecifies whether the parameters must appear in the message in a particular order. The value is stored as a Boolean.
MAINTAIN_SESSIONSpecifies if the consumer wants to maintain the current session for future requests. The value is stored as a Boolean.
WSDL_DESCRIPTION[a]Specifies the WSDL document that defines the service being implemented. The value is stored as a org.xml.sax.InputSource object.
WSDL_SERVICE[a]Specifies the qualified name of the wsdl:service element that defines the service being implemented. The value is stored as a QName.
WSDL_PORT[a]Specifies the qualified name of the wsdl:port element that defines the endpoint used to access the service. The value is stored as a QName.
WSDL_INTERFACE[a]Specifies the qualified name of the wsdl:portType element that defines the service being implemented. The value is stored as a QName.
WSDL_OPERATION[a]Specifies the qualified name of the wsdl:operation element that corresponds to the operation invoked by the consumer. The value is stored as a QName.
javax.xml.ws.handler.MessageContext
MESSAGE_OUTBOUND_PROPERTYSpecifies if a message is outbound. The value is stored as a Boolean. true specifies that a message is outbound.
INBOUND_MESSAGE_ATTACHMENTS

Contains any attachments included in the request message. The value is stored as a java.util.Map<String, DataHandler>.

The key value for the map is the MIME Content-ID for the header.

OUTBOUND_MESSAGE_ATTACHMENTS

Contains any attachments for the response message. The value is stored as a java.util.Map<String, DataHandler>.

The key value for the map is the MIME Content-ID for the header.

WSDL_DESCRIPTIONSpecifies the WSDL document that defines the service being implemented. The value is stored as a org.xml.sax.InputSource object.
WSDL_SERVICESpecifies the qualified name of the wsdl:service element that defines the service being implemented. The value is stored as a QName.
WSDL_PORTSpecifies the qualified name of the wsdl:port element that defines the endpoint used to access the service. The value is stored as a QName.
WSDL_INTERFACESpecifies the qualified name of the wsdl:portType element that defines the service being implemented. The value is stored as a QName.
WSDL_OPERATIONSpecifies the qualified name of the wsdl:operation element that corresponds to the operation invoked by the consumer. The value is stored as a QName.
HTTP_RESPONSE_CODESpecifies the response code returned to the consumer. The value is stored as an Integer object.
HTTP_REQUEST_HEADERSSpecifies the HTTP headers on a request. The value is stored as a java.util.Map<String, List<String>>.
HTTP_RESPONSE_HEADERSSpecifies the HTTP headers for the response. The value is stored as a java.util.Map<String, List<String>>.
HTTP_REQUEST_METHODSpecifies the HTTP verb sent with a request. The value is stored as a String.
SERVLET_REQUESTContains the servlet's request object. The value is stored as a javax.servlet.http.HttpServletRequest.
SERVLET_RESPONSEContains the servlet's response object. The value is stored as a javax.servlet.http.HttpResponse.
SERVLET_CONTEXTContains the servlet's context object. The value is stored as a javax.servlet.ServletContext.
PATH_INFO

Specifies the path of the resource being requested. The value is stored as a String.

The path is the portion of the URI after the hostname and before any query string. For example, if an endpoint's URL is http://cxf.apache.org/demo/widgets the path is /demo/widgets.

QUERY_STRING

Specifies the query, if any, attached to the URI used to invoke the request. The value is stored as a String.

Queries appear at the end of the URI after a ?. For example, if a request is made to http://cxf.apache.org/demo/widgets?color the query string is color.

REFERENCE_PARAMETERSSpecifies the WS-Addressing reference parameters. This includes all of the SOAP headers whose wsa:IsReferenceParameter attribute is set to true. The value is stored as a java.util.List.
org.apache.cxf.transport.jms.JMSConstants
JMS_SERVER_HEADERSContains the JMS message headers. For more information see Working with JMS Message Properties.

[a] When using HTTP this property is the same as the standard JAX-WS defined property.


The Fuse Services Framework JMS transport has a context mechanism that can be used to inspect a JMS message's properties. The context mechanism can also be used to set a JMS message's properties.

Consumers and services use different context mechanisms to access the JMS message header properties. However, both mechanisms return the header properties as a org.apache.cxf.transports.jms.context.JMSMessageHeadersType object.

Once a message is successfully retrieved from the JMS transport you can inspect the JMS header properties using the consumer's response context. In addition, you can see how long the client waits for a response before timing out.

You can To get the JMS message headers from a consumer's response context do the following:

  1. Get the response context as described in Obtaining a context.

  2. Get the JMS message header properties from the response context using the context's get() method with org.apache.cxf.transports.jms.JMSConstants.JMS_CLIENT_RESPONSE_HEADERS as the parameter.

Example 20.13 shows code for getting the JMS message header properties from a consumer's response context.

Example 20.13. Getting the JMS Headers from a Consumer Response Header

import org.apache.cxf.transports.jms.context.*;
// Proxy greeter initialized previously
1BindingProvider  bp = (BindingProvider)greeter;
2Map<String, Object> responseContext = bp.getResponseContext();
3JMSMessageHeadersType responseHdr = (JMSMessageHeadersType)
                           responseContext.get(JMSConstants.JMS_CLIENT_REQUEST_HEADERS);
...
}

The code in Example 20.13 does the following:

1

Casts the proxy to a BindingProvider.

2

Gets the response context.

3

Retrieves the JMS message headers from the response context.

Example 20.14 shows code for inspecting some of the JMS properties using the response context.

Example 20.14. Reading the JMS Header Properties

// JMSMessageHeadersType messageHdr retrieved previously
1System.out.println("Correlation ID: "+messageHdr.getJMSCorrelationID());
2System.out.println("Message Priority: "+messageHdr.getJMSPriority());
3System.out.println("Redelivered: "+messageHdr.getRedelivered());
  
JMSPropertyType prop = null;
4List<JMSPropertyType> optProps = messageHdr.getProperty();
5Iterator<JMSPropertyType> iter = optProps.iterator();
6while (iter.hasNext())
{
  prop = iter.next();
   System.out.println("Property name: "+prop.getName());
   System.out.println("Property value: "+prop.getValue());
}

The code in Example 20.14 does the following:

1

Prints the value of the message's correlation ID.

2

Prints the value of the message's priority property.

3

Prints the value of the message's redelivered property.

4

Gets the list of the message's optional header properties.

5

Gets an Iterator to traverse the list of properties.

6

Iterates through the list of optional properties and prints their name and value.

Using the request context in a consumer endpoint, you can set a number of the JMS message header properties and the consumer endpoint's timeout value. These properties are valid for a single invocation. You must reset them each time you invoke an operation on the service proxy.

[Note]Note

You cannot set header properties in a service.

Table 20.4 lists the properties in the JMS header that can be set using the consumer endpoint's request context.


To set these properties do the following:

  1. Create an org.apache.cxf.transports.jms.context.JMSMessageHeadersType object.

  2. Populate the values you want to set using the appropriate setter methods described in Table 20.4.

  3. Set the values to the request context by calling the request context's put() method using org.apache.cxf.transports.jms.JMSConstants.JMS_CLIENT_REQUEST_HEADERS as the first argument, and the new JMSMessageHeadersType object as the second argument.

Example 20.15 shows code for setting some of the JMS properties using the request context.

Example 20.15. Setting JMS Properties using the Request Context

import org.apache.cxf.transports.jms.context.*;
 // Proxy greeter initialized previously
1InvocationHandler handler = Proxy.getInvocationHandler(greeter);


BindingProvider bp= null;
2if (handler instanceof BindingProvider)
{
3  bp = (BindingProvider)handler;
4  Map<String, Object> requestContext = bp.getRequestContext();
  
5  JMSMessageHeadersType requestHdr = new JMSMessageHeadersType();
6  requestHdr.setJMSCorrelationID("WithBob");
7  requestHdr.setJMSExpiration(3600000L);
  
  
8  JMSPropertyType prop = new JMSPropertyType;
9  prop.setName("MyProperty");
  prop.setValue("Bluebird");
10  requestHdr.getProperty().add(prop);

11  requestContext.put(JMSConstants.CLIENT_REQUEST_HEADERS, requestHdr);

12  requestContext.put(JMSConstants.CLIENT_RECEIVE_TIMEOUT, new Long(1000));
}

The code in Example 20.15 does the following:

1

Gets the InvocationHandler for the proxy whose JMS properties you want to change.

2

Checks to see if the InvocationHandler is a BindingProvider.

3

Casts the returned InvocationHandler object into a BindingProvider object to retrieve the request context.

4

Gets the request context.

5

Creates a JMSMessageHeadersType object to hold the new message header values.

6

Sets the Correlation ID.

7

Sets the Expiration property to 60 minutes.

8

Creates a new JMSPropertyType object.

9

Sets the values for the optional property.

10

Adds the optional property to the message header.

11

Sets the JMS message header values into the request context.

12

Sets the client receive timeout property to 1 second.

To implement a logical hander you do the following:

  1. Implement any initialization logic required by the handler.

  2. Implement the message handling logic.

  3. Implement the fault handling logic.

  4. Implement the logic for closing the handler when it is finished.

  5. Implement any logic for cleaning up the handler's resources before it is destroyed.