JAX-WS client APIs in the Web Services Feature Pack for WebSphere Application Server V6.1, Part 1: Creating a Dispatch client

This series introduces developers to JAX-WS 2.0, the new programming model supported in the Web Services Feature Pack for WebSphere Application Server V6.1. Part 1 guides you through creating a Dispatch client using the various JAX-WS client APIs.

Share:

Dan Sedov (sedov@us.ibm.com), Staff Software Engineer, IBM

Dan Sedov photoDan Sedov is a Staff Software Engineer performing function testing in IBM Software Group for the Web services component of WebSphere Application Server. For the past two years, Dan has been a member of the WebSphere product team that developed and tested the first Web Services Feature Pack. He has worked on creating and automating JAX-WS Web services engine tests. You can reach Dan at sedov@us.ibm.com.



Nikhil Thaker (nikhil.v.thaker@us.ibm.com), Staff Software Engineer, IBM

Nikhil Thaker photoNikhil Thaker is a Staff Software Engineer with IBM Software Group, and a member of the WebSphere product team that developed Web services feature pack. He has more than nine years of experience in Enterprise Application Integration, and has focused on Web services for the past two years. He has worked with various IBM customers as an IT Specialist in Enterprise Application Integration in IBM Global Services. His industry exposure includes Automotive, Health Care, telecommunication and utilities. You can reach Nikhil at nikhil.v.thaker@us.ibm.com.



November 2009 (First published 18 July 2007)

Also available in Chinese Russian

Introduction

Develop skills on this topic

This content is part of a progressive knowledge path for advancing your skills. See Building and deploying JAX-WS web services

The WebSphere Application Server V6.1 Feature Pack for Web Services extends the capabilities of WebSphere Application Server V6.1 to enable Web services messages to be sent asynchronously, reliably, and securely, focusing on interoperability with other vendors. The Feature Pack offers support for new Web services standards including:

  • Web Services Reliable Messaging (WS-RM)
  • Web Services Addressing (WS-Addressing)
  • SOAP Message Transmission Optimization Mechanism (MTOM)
  • Web Services Secure Conversations (WS-SC)

It also supports the following standards-based programming models:

  • Java API for XML Web Services (JAX-WS 2.0)
  • Java Architecture for XML Binding (JAXB 2.0)
  • SOAP with Attachments API for Java (SAAJ 1.3)
  • Streaming API for XML (StAX 1.0)

In this series, we'll focus on JAX-WS 2.0 client APIs.

The new Dispatch API introduced in JAX-WS supports a fully dynamic service invocation. No WSDL or XML Schema document or any other knowledge of the message layout is required to build a client. This flexibility comes at a cost – the developer must be intimately familiar with the details of SOAP protocol and the underlying message composition API, such as DOM or SAAJ. Some examples of situations in which you might want to use dispatches are:

  • Document exchange scenarios, where the dynamic nature of dispatches is important. For example, when the actual message is output by an external process, such as a file from an external system or as the result of an XSLT transformation. In this scenario, the dispatch is used to provide the SOAP envelope, and to transmit the message and pass back the response without interacting with the actual message.
  • Where interoperability with older, non WS-I compliant services is desired, such as interoperability with RPC-encoded style services.
  • Where you need to work with a data binding technology other than JAXB. JAX-WS is built around its tight integration with JAXB 2.0. Although there is no direct support for other bindings in JAX-WS, while writing this article we came across a number of scenarios where it was desirable to use another data binding technology like Castor or XML beans.
  • Where there are specific advantages to be gained by not using SOAP protocol, dispatches support an XML/HTTP binding, which can be used to invoke endpoints that exchange raw XML documents based on application-defined structures.

This article provides:

  1. A brief overview of JAX-WS
  2. An example of JAX-WS Dispatch client
  3. Examples of the various client APIs used to process a Web service message

Readers should have a good understanding of XML, SOAP, WSDL, and Web services.


JAX-WS 2.0 overview

JAX-WS 2.0 is the new Java API for Web services development. It builds on the the older JAX-RPC programming model, and adds numerous improvements. Some of the benefits of JAX-WS 2.0 are:

  • Separates the data binding technology from the Web services programming model with support for Java Architecture for XML Binding (JAXB) 2.0.
  • Supports SOAP 1.2, as well as SOAP 1.1.
  • Supports WS-I Basic Profile 1.1 for improved Web services interoperability.
  • Adds a descriptorless deployment of Web services by including support for annotations defined in JSR 181 (Web Services Metadata for the Java Platform) and annotations defined with JAX-WS as well. Since all metadata is in standardized annotations, the Web service implementations are vendor-neutral.
  • Supports an asynchronous client programming model.
  • Simplifies the development of handlers and provides a mechanism to allow handlers to collaborate with service clients and service endpoint implementations.
  • Includes the API in Java Platform, Extended Edition (Java EE) 5 and Java 2 Plaform, Standard Edition (J2SE) 6.

JAX-WS 2.0 client APIs

Figure 1 shows the class relationships between various JAX-WS client APIs. JAX-WS provides this set of APIs for a Web service client to invoke an operation on a remotely deployed service endpoint. You can use these APIs to invoke operations dynamically or statically, as well as synchronously or asynchronously.

Figure 1. JAX-WS client API relationships
Figure 1. JAX-WS client API relationships

An example: Creating a Dispatch client

The rest of this article describes how to create a Dispatch client from a WSDL document, and then explains the API. The example uses the following WSDL:

Listing 1. WSDL definition
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="HelloWorldService"
   xmlns="http://schemas.xmlsoap.org/wsdl/"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:tns="http://www.example.com/services/HelloWorld"
   xmlns:types="http://www.example.com/schemas/HelloWorld"
   targetNamespace="http://www.example.com/services/HelloWorld">

   <types>
      <schema
		xmlns="http://www.w3.org/2001/XMLSchema"
	 	targetNamespace=”http://www.example.com/schemas/HelloWorld”>

		<element name=”hello”>
			<complexType>
				<sequence>
					<element name=”message” type=”string” />
				</sequence>
			</complexType>
		</element>

		<element name=”helloResponse”>
			<complexType>
				<sequence>
					<element name=”message” type=”string” />
				</sequence>
			</complexType>
		</element>
	</schema>
   </types>

   <message name="HelloRequest">
      <part name="firstName" element="types:hello"/>
   </message>

   <message name="HelloResponse">
      <part name="greeting" element=”types:helloResponse"/>
   </message>

   <portType name="HelloWorldSEI">
      <operation name="hello">
         <input message="tns:HelloRequest"/>
         <output message="tns:HelloResponse"/>
      </operation>
   </portType>
   
   <binding name="HelloSoap11Binding" type="tns:HelloWorldSEI">
      <soap:binding
		style="document" 
		transport="http://schemas.xmlsoap.org/soap/http"/>
      <operation name="hello">
         <soap:operation soapAction="hello"/>
         <input>
            <soap:body use="literal"/>
         </input>
         <output>
            <soap:body use="literal"/>
         </output>
      </operation>
   </binding>

   <service name="HelloService">
      <port binding="tns:HelloSoap11Binding" name="HelloPort">
         <soap:address
             location="http://localhost:8080/hello/services/HelloService"/>
      </port>
   </service>
</definitions>

This WSDL describes a service, HelloWorldService, with a single port called HelloPort. The portType HelloWorldSEI defines a single hello operation. The hello operation is in wrapped document-literal style, so when it transmits the hello request, it expects to receive helloResponse back.

Let's take a look at a simple Dispatch client that invokes the hello operation. First we'll look at the whole invocation, and then we'll break down the pieces individually:

Listing 2. JAX-WS client – javax.xml.ws.Dispatch example
// Qnames for service as defined in wsdl.
QName serviceName =
  new Qname("http://www.example.com/services/HelloWorld", "HelloService");

//QName for Port As defined in wsdl.
QName portName =
  new Qname("http://www.example.com/services/HelloWorld", "HelloPort");

//Endpoint Address
String  endpointAddress =
  "http://localhost:8080/hello/services/HelloService";

// Create a dynamic Service instance
Service service = Service.create(serviceName);

// Add a port to the Service
service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointAddress);

//Create a dispatch instance
Dispatch<SOAPMessage> dispatch = 
   service.createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE);

// Use Dispatch as BindingProvider
BindingProvider bp = (BindingProvider) dispatch;

// Optionally Configure RequestContext to send SOAPAction HTTP Header
Map<String, Object> rc = bp.getRequestContext();
rc.put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE);
rc.put(BindingProvider.SOAPACTION_URI_PROPERTY, "hello");

// Obtain a preconfigured SAAJ MessageFactory
MessageFactory factory =
   ((SOAPBinding) bp.getBinding()).getMessageFactory();

// Create SOAPMessage Request
SOAPMessage request = factory.createMessage();

// Request Header
SOAPHeader header = request.getSOAPHeader();

// Request Body
SOAPBody body = request.getSOAPBody();

// Compose the soap:Body payload
QName payloadName =
   new QName("http://www.example.com/schemas/HelloWorld", "hello", "ns1");

SOAPBodyElement payload = body.addBodyElement(payloadName); 

SOAPElement message = payload.addChildElement("message");

message.addTextNode("Hello World!");

// Invoke the endpoint synchronously
SOAPMessage reply = null;

try {
	//Invoke Endpoint Operation and read response
	reply = dispatch.invoke(request);
} catch (WebServiceException wse){
	wse.printStackTrace();
}

// process the reply
body = reply.getSOAPBody();

QName responseName =
   new QName("http://www.example.com/schemas/HelloWorld", "helloResponse");

SOAPBodyElement bodyElement = body.getChildElements(responseName).next());
String message = bodyElement.getValue();

The example above uses the following steps to invoke an operation on an endpoint using the Dispatch API:

  1. Create and configure a dynamic Service instance
  2. Create a Dispatch client
  3. Configure a request context
  4. Compose a request message
  5. Invoke the operation
  6. Process the response message

These steps are described in the following sections.


Step 1: Create and configure a dynamic Service instance

The Service class is an abstraction that represents a WSDL service. A Service instance can be a dynamic service (a service created on the fly) or a static instance (a class generated by JAX-WS tools that extends the service class). In this article, we'll focus on a dynamic service.

A J2SE client can use the Service.create() method to create a Service instance. When a J2SE client chooses to create a Service instance, as illustrated in our example, it is a dynamic Service instance, which means that it is configured dynamically, rather than statically as in the case of a generated Service Class. There are two ways to create a dynamic service instance:

  • create(QName serviceName) returns a service object for a service with the given name. No WSDL document is attached to the service.

    As shown in in Listing 2, we first define the Service QName as defined in the WSDL and then use that to create a Service.

    Listing 3. Create a dynamic Service instance
    //Qnames for service
    QName serviceName =
      new Qname("http://www.example.com/services/HelloWorld", "HelloService");
    
    //Create a dynamic Service instance
    Service service = Service.create(serviceName);

    A WSDL service is a collection of related ports, each of which consists of a port type bound to a particular protocol and available at a particular endpoint address. As shown in Listing 2, we define a port QName as described in the WSDL and then add that port to the Service.

    Listing 4. Add port to Service
    QName portName =
      new Qname("http://www.example.com/services/HelloWorld", "HelloPort");
    
    //Endpoint Address
    String  endpointAddress =
      "http://localhost:8080/hello/services/HelloService";
    
    // Add a port to the Service
    service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointAddress);
  • create(URL wsdlLocation, QName serviceName) returns a service object for the specified WSDL document and service name, as shown in Listing 5:
    Listing 5. Create dynamic service using WSDL
    //WSDL URL
    URL wsdlLocation = new URL("http://www.example.com/services/HelloWorld?wsdl");
    
    //Qname for service
    QName serviceName =
      new Qname("http://www.example.com/services/HelloWorld", "HelloService");
    
    //Create a dynamic Service instance
    Service service = Service.create(wsdlLocation, serviceName);

We could also have chosen to use a static service. A static service becomes available when the WSDL file is compiled with JAX-WS tools to generate Java artifacts. We chose a dynamic service here because:

  • We don't want to generate any artifacts.
  • We may not know the service that we're invoking at the time of writing the client. For example, we may get the WSDL document from an intermediary and then use it to dynamically configure the service object.
  • We use the dispatch just to transmit a message that originates in another system.

Step 2: Create a Dispatch client

The Dispatch is a low-level API that requires clients to construct messages or message payloads using an XML-based technology. The higher level JAX-WS APIs are designed to hide the details of working with XML and allow users to work with more familiar Java objects. The Dispatch supports two usage modes, identified by the constants:

  • javax.xml.ws.Service.Mode.PAYLOAD
  • javax.xml.ws.Service.Mode.MESSAGE

In the PAYLOAD mode, client applications work with contents of the <soap:Body> element (the message payload) rather than the entire messages themselves. The JAX-WS run time is responsible for providing the SOAP envelope if the service is using a SOAP binding.

Listing 6. Create Dispatch instance in PAYLOAD mode
//Create a dispatch instance
Dispatch<SOAPMessage> dispatch = 
   service.createDispatch(portName, javax.xml.transform.Source.class,
Service.Mode.PAYLOAD);

In the MESSAGE mode, client applications work directly with protocol-specific message structures. The client is responsible for providing both the SOAP envelope and the message payload. In our example, we use MESSAGE mode, as shown in Listing 7.

Listing 7. Create dispatch instance in MESSAGE mode
//Create a dispatch instance
Dispatch<SOAPMessage> dispatch = 
   service.createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE);

Step 3: Configure the request context

JAX-WS client APIs implement the BindingProvider interface, which allows them to maintain separate contexts for the request and response phases of a message exchange with the endpoint. The request and response contexts are of type Map<String, Object> and are obtained using the getRequestContext and getResponseContext methods of the BindingProvider interface.

The following table shows the standard properties that can be set on the request context after the Dispatch instance is created:

PropertyPurpose
javax.xml.ws.service.endpoint.address The address of the service endpoint as a protocol-specific URI. The URI scheme must match the protocol binding in use.
javax.xml.ws.security.auth.usernamejavax.xml.ws.security.auth.password The user name and password for HTTP basic authentication.
javax.xml.ws.session.maintain Indicates that the client wishes to participate in an HTTP session.
javax.xml.ws.soap.http.soapaction.usejavax.xml.ws.soap.http.soapaction.uri Controls whether the SOAPAction HTTP header is used in SOAP over HTTP requests.
Listing 8. Using a binding provider to set up RequestContext
//get Binding provider
BindingProvider bp = (BindingProvider) dispatch;

// Configure RequestContext (optional step)
Map<String, Object> rc = bp.getRequestContext();

//Ask RequestContext to USE SOAPAction.
rc.put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE);

//Add SOAPAction to RequestContext
rc.put(BindingProvider.SOAPACTION_URI_PROPERTY, "hello");

Step 4: Compose a request message

Our example uses a Dispatch of type SOAPMessage, but dispatches also support several other APIs for composing the message. For example, javax.xml.transform.Source with DOMSource, SAXSource and StreamSource subinterfaces, JAXB 2.0 objects, and javax.activation.DataSource are all valid types of dispatches. Our example demonstrates invocations using the SAAJ SOAPMessage API to compose a message,as shown in Listing 9:

Listing 9. Create SOAP message
//Create SOAPMessage Request
SOAPMessage request = factory.createMessage();

//Request Header
SOAPHeader header = request.getSOAPHeader();

//Request Body
SOAPBody body = request.getSOAPBody();

As you can see here the payloadName is the XML Schema "hello" element's QName.

Listing 10. wsdl element representing operation signature
 <schema
	xmlns="http://www.w3.org/2001/XMLSchema"
	targetNamespace="http://www.example.com/schemas/HelloWorld">

	<element name="hello">
		<complexType>
			<sequence>
				<element name="message" type="string" />
			</sequence>
		</complexType>
	</element>
</schema>

// Compose the soap:Body payload
QName payloadName =
   new QName("http://www.example.com/schemas/HelloWorld", "hello", "ns1");

SOAPBodyElement payload = body.addBodyElement(payloadName);
SOAPElement message = payload.addChildElement("message");
message.addTextNode("Hello World!");

You may wonder why we chose to construct our message this way. Our simple WSDL uses document-style SOAP binding, as shown in Listing 11:

Listing 11. Document-style SOAP binding
<soap:binding
		style="document" 
		transport="http://schemas.xmlsoap.org/soap/http"/>

In this style, we transmit exact XML documents. Other styles transmit differently formatted messages. The developerWorks article Which style of WSDL should I use? describes different WSDL styles and their corresponding messages.


Step 5: Invoke the operation

Once the request is created, it is dispatched using one of several Invoke methods on the Dispatch instance. Our example uses a synchronous request-response message exchange pattern, as shown in Listing 12:

Listing 12. Dispatch invoking operation with request
try {
	//Invoke Endpoint Operation and read response
	reply = dispatch.invoke(request);
} catch (WebServiceException wse){
	wse.printStackTrace();
}

In the event that request was not successfully dispatched, a WebServiceException is thrown with an underlying exception as the cause (for example, HostNotFoundException). If the endpoint had a problem processing the request, a SOAPFaultException is thrown.


Step 6: Process the response message

The response received from ths Invoke is finally processed by extracting the body of the reply SOAP message and parsing it according to the WSDL definition. In this example, we expect to receive a helloResponse XML element, as shown in Listing 12:

Listing 13. Response processing
<element name="helloResponse">
	<complexType>
		<sequence>
			<element name="message" type="string" />
		</sequence>
	</complexType>
</element>

// process the reply
body = reply.getSOAPBody();

QName responseName =
   new QName("http://www.example.com/schemas/HelloWorld", "helloResponse");

SOAPBodyElement bodyElement = body.getChildElements(responseName).next());
String message = bodyElement.getValue();

Summary

In this article, you've learned how to create a Dispatch client that can be used to dynamically invoke a Web service. You've also learned a bit about the other JAX-WS client APIs that are used to configure the context of the SOAP message sent to the server. The WebSphere Application Server V6.1 Web Services Feature Pack implementation of the Dispatch API supports the input and output message types javax.xml.transform.Source, JAXB Object, javax.xml.soap.SoapMessage and java.lang.String. A Web services client application can use the Dispatch API to invoke one- and two-way synchronous and asynchronus operations implemented by a Web service endpoint. Some other situations in which you might use a Dispatch API to invoke a Web service are:

  • When interoperability with legacy JAX-RPC or non-WS-I compliant Web services is required.
  • To invoke a Web service with xml/http binding and not traditional SOAP binding.
  • To invoke a Web service by using a data binding other than JAXB.

Downloads

DescriptionNameSize
Project interchange filejaxwsDispatch.zip124KB
Project interchange filejaxwsProxy_samples.zip158KB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere, SOA and web services
ArticleID=240726
ArticleTitle=JAX-WS client APIs in the Web Services Feature Pack for WebSphere Application Server V6.1, Part 1: Creating a Dispatch client
publish-date=11182009