Skip to main content

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

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

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.

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

All information submitted is secure.

  • Close [x]

JAX-WS client APIs in the Web Services Feature Pack for WebSphere Application Server V6.1, Part 3: Using the JAX-WS asynchronous programming model

Dan Sedov (sedov@us.ibm.com), Staff Software Engineer, IBM
Dan Sedov photo
Dan 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 photo
Nikhil 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.

Summary:  In the final part of this series on JAX-WS 2.0 in the WebSphere Application Server V6.1 Feature Pack for Web Services, you'll learn how to create an asynchronous Web client, and learn how to use the polling and callback models.

View more content in this series

Date:  30 Apr 2008
Level:  Introductory
Also available in:   Chinese  Russian

Activity:  13713 views
Comments:  

Introduction

Part 1 and Part 2 of this series described the JAX-WS client APIs and how to use of the JAX-WS programming model to create dispatch and dynamic proxy clients. In this article, we'll continue our discussion of the client APIs and show you how to create an asynchronous Web service client.

This article does the following:

  1. Introduces the asynchronous programming model
  2. Provides examples of the polling and callback models
  3. Describes the asynchronous message exchange pattern (MEP)

JAX-WS 2.0 asynchronous programming model

In Part 2, you learned about the JAX-WS dynamic proxy client. In this article, you'll learn about the asynchronous programming model. The asynchronous programming model is one of the major changes between JAX-WS and JAX-RPC, which provided only synchronous APIs.

Our last article used a simplified banking application. Following is the method signature for the createAccount method:

int createAccount(String customerName, double initialBalance);

Invoking this method synchronously assumes that the request can probably be completed in a few seconds. However, modern applications, especially in service-oriented architectures, may take considerably longer. Typical requirements to create a new bank account may include credit checks, address verification, checks with various government agencies and even a manual workflow.

The JAX-WS programming model offers two models for invoking operations asynchronously – polling and callback. Both methods allow the client to continue processing while waiting for a response.

Asynchronous service endpoint interface (SEI)

Listing 1 shows the sample WSDL file from Part 2 of this series, which we'll also use for this article. Notice that we haven’t changed anything in the WSDL to make it asynchronous.


Listing 1. BankingService.wsdl WSDL definition
                
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="BankingService"
   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/Banking"
   xmlns:types="http://www.example.com/schemas/Banking"
   targetNamespace="http://www.example.com/services/Banking">

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

		<!--
		definition of createAccount operation request and response beans
		-->
		<element name="createAccount">
			<complexType>
				<sequence>
					<element name="owner" type="string" />
				<element name="initialBalance" type="double" />
				</sequence>
			</complexType>
		</element>

		<element name="createAccountResponse">
			<complexType>
				<sequence>
					<element name="accountNumber" type="long" />
				</sequence>
			</complexType>
		</element>


		<!--
		definition of withdraw operation request, response and fault beans 
		-->
		<element name="withdraw">
			<complexType>
				<sequence>
					<element name="accountNumber" type="long" />
					<element name="amount" type="double" />
				</sequence>
			</complexType>
		</element>

		<element name="withdrawResponse">
			<complexType>
				<sequence>
					<element name="amount" type="double" />
				</sequence>
			</complexType>
		</element>

		<element name="InsufficientFunds">
			<complexType>
				<sequence>
					<element name="errorMessage" type="string" />
					<element name="errorCode" type="int" />
				</sequence>
			</complexType>
		</element>

		<!--
		definition of getAccountInfo operation request and response beans 
		-->
		<element name="getAccountInfo">
			<complexType>
				<sequence>
					<element name="accountNumber" type="long" />
				</sequence>
			</complexType>
		</element>

		<element name="getAccountInfoResponse">
			<complexType>
				<sequence>
				  <element name="balance" type="double" />
				  <element name="owner" type="string" />
				</sequence>
			</complexType>
		</element>
	</schema>
   </types>

   <message name="createAccountRequest">
      <part name="request" element="types:createAccount"/>
   </message>

   <message name="createAccountResponse">
      <part name="response" element="types:createAccountResponse"/>
   </message>

   <message name="withdrawRequest">
      <part name="request" element="types:withdraw "/>
   </message>

   <message name="withdrawResponse">
      <part name="response" element="types:withdrawResponse"/>
   </message>

   <message name="InsufficientFunds">
      <part name="error" element="types:InsufficientFunds"/>
   </message>

   <message name="getAccountInfoRequest">
      <part name="request" element="types:getAccountInfo"/>
   </message>

   <message name="getAccountInfoResponse">
      <part name="response" element="types:getAccountInfoResponse"/>
   </message>

   <portType name="BankingSEI">
      <operation name="createAccount">
         <input message="tns:createAccountRequest"/>
         <output message="tns:createAccountResponse"/>
      </operation>

      <operation name="withdraw">
         <input message="tns:withdrawRequest"/>
         <output message="tns:withdrawResponse"/>
	   <fault message="tns:InsufficientFunds"/>
      </operation>

      <operation name="getAccountInfo">
         <input message="tns:getAccountInfoRequest"/>
         <output message="tns:getAccountInfoResponse"/>
      </operation>
   </portType>
   
   <binding name="BankingSoap11Binding" type="tns:BankingSEI">
      <soap:binding
		style="document" 
		transport="http://schemas.xmlsoap.org/soap/http"/>

      <operation name="createAccount">
         <soap:operation soapAction="createAccount"/>
         <input>	
            <soap:body use="literal"/>
         </input>
         <output>
            <soap:body use="literal"/>
         </output>
      </operation>

      <operation name=" withdraw ">
         <soap:operation soapAction="withdraw"/>
         <input>
            <soap:body use="literal"/>
         </input>
         <output>
            <soap:body use="literal"/>
         </output>
         <fault>
            <soap:fault name="InsufficientFunds" use="literal"/>
         </fault>
      </operation>

      <operation name="getAccountInfo">
         <soap:operation soapAction="getAccountInfo"/>
         <input>	
            <soap:body use="literal"/>
         </input>
         <output>
            <soap:body use="literal"/>
         </output>
      </operation>

   </binding>

   <service name="BankingService">
      <port binding="tns: BankingSoap11Binding" name="AccountsPort">
         <soap:address
             location="http://localhost:8080/banking/services
		/BankingService"/>
      </port>
   </service>
</definitions>


To generate portable artifacts with the WSDL in Listing 1, you can use tools like the WebSphere Application Server Toolkit or the wsimport command line tool, located at WAS_HOME/bin/wsimport. In this article, we'll use wsimport. To use wsimport to generate asynchronous artifacts, you need a separate binding customization file, as shown in Listing 2.


Listing 2. binding.xml binding customization file
                
<bindings 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    wsdlLocation="BankingService.wsdl"
    xmlns="http://java.sun.com/xml/ns/jaxws">    
    <bindings node="wsdl:definitions">
        <enableAsyncMapping>true</enableAsyncMapping>
    </bindings>
</bindings>

Listing 2 shows a simple binding customization that will generate asynchronous versions of all methods found in the WSDL. Note that the wsdlLocation element must match the WSDL file name. Invoke the wsimport tool by entering the following:
%WAS_HOME%\bin\wsimport.bat –b binding.xml BankingService.xml

The generated SEI will have the following operations defined for createAccount:


Listing 3. SEI for createAccount
                
// Synchronous method
int createAccount(String customerName, double initialBalance);

// Polling method
javax.xml.ws.Response<CreateAccountResponse> createAccount(String customerName, 
double initialBalance);

// Callback method
javax.concurrent.Future<?> createAccount(String customerName, double initialBalance, 
AsyncHandler<CreateAccountResponse> handler);
      


Polling example

Asynchronous polling clients are useful for implementing Web services based work flows. In a polling client, once the initial request is made the client is free to pursue other work until the request completes. This enables the client to execute other tasks that don't depend on the outcome of the request. Once the request completes, the response is made available to the client.

Table 1 describes the behavior of the javax.xml.ws.Response object.


Table 1. javax.xml.ws.Response object behavior
cancel() Cancel the response processing. This does not stop the server from processing the request.
get() Retrieve the response, if it is available. If the response is not available, the method blocks.
get( long timeout, TimeUnit unit) Retrieve the response, but only block for a specified period of time.
isDone() Check whether the response is available.
isCancelled() Check whether the response processing was cancelled.
getContext () Returns the BindingProvider responseContext associated with the request.

Listing 4 shows an example of a client making an asynchronous polling request.


Listing 4. Polling example
                
// Polling method
Response<CreateAccountResponse> response = createAccount
("Joe Customer", 10.00);

// wait for the response
while (!response.isDone()){
   // do some work that does not depend on the new account being available
   …
}

// retrieve the account number
try {
int accountNumber = response.get().getAccountNumber();
} catch (CancellationException ce) {
	// processing was cancelled via response.cancel()

} catch (ExecutionException ee} {
	// there was an error processing the request
	// getCause() returns the actual exception
	Systemout.println(ee.getCause());
}

One advantage of the polling method is that the response is not actually processed until the response.get() method is called, so the client has full control over when the response is processed. In this way, it is very similar to its synchronous counterpart.


Callback example

Asynchronous callback clients are useful for implementing batch processing and notification consumer applications. In a callback client, once the request is made, the client is free to pursue other work; however, the response is not made available to the client. The actual response is processed by the specified AsyncHandler implementation. Once the response is made available to the callback handler, the code flow is much the same as with polling client.

Table 2 describes how javax.concurrent.Future behaves in an asynchronous callback client.


Table 2. javax.concurrent.Future behavior in an asynchronous callback client
cancel() Cancel the response processing. This does not stop the server from processing the request.
get() Clients should not call this method because its behavior is indeterminate.
get( long timeout, TimeUnit unit) Clients should not call this method as its behavior is indeterminate
isDone() Check whether the response is available.
isCancelled() Check whether the response processing was cancelled.

Listing 5 shows the client invoking the asynchronous callback method. Note that the while loop is completely optional, as the actual response (including any failures in delivering or processing the request) will be delivered to the callback handler.


Listing 5. Callback invocation
                
// Callback method
CreateAcountHandler handler = new CreateAcountHandler();
Future>?< monitor = createAccount("Joe Customer", 10.00, handler);

// wait for the response
while (!monitor.isDone()){
   // do some work that does not depend on the new account being available
   …
}

Listing 6 shows the implementation of the Async handler.


Listing 6. AsyncHandler implementation
                
public class CreateAcountHandler implements AsyncHandler<CreateAccountResponse> {
	public void handleResponse(Response<CreateAccountResponse> response) {

		// retrieve the account number
		try {
		int accountNumber = response.get().getAccountNumber();
	} catch (CancellationException ce) {
		// processing was cancelled via response.cancel()

	} catch (ExecutionException ee} {
		// there was an error processing the request
		// getCause() returns the actual exception
		Systemout.println(ee.getCause());
	}
	}
}

Threading considerations

Callback calls process the response on a different thread from the one the client is running on. This allows the client to gain some control over performance if there are many concurrent asynchronous requests. You can get this control by providing an Executor using the BankingService.setExecutor() method. Executors provide both a thread pool and a means for the JAX-WS run-time to queue asynchronous responses for processing. Listing 7 shows an example of how to use an Executors factory to create a thread pool of 10 threads.


Listing 7. Executor example
                
BankingService svc = new BankingService();
svc.setExecutor(java.util.concurrent.Executors.newFixedThreadPool(10));

WebSphere provides its own default Executor, so providing your own Executor is optional.


Asynchronous MEP

So far in our discussion, we've only talked about the asynchronous programming model, in which the actual requests are synchronous and are affected by socket read and write timeouts. To make these requests asynchronous at the HTTP connection level, you have to set additional properties in the request context. To enable the asynchronous message exchange, set com.ibm.websphere.webservices.use.async.mep to true in the request context.


Listing 8. Enable asynchronous message exchange
                
// Create a Dynamic Proxy client
BankingService service = new BankingService();
BankingSEI port = service.getAccountsPort();

// Use Proxy Instance as BindingProvider
BindingProvider bp = (BindingProvider) port;

Map<String, Object> rc = bp.getRequestContext();
rc.put("com.ibm.websphere.webservices.use.async.mep", Boolean.TRUE);

// invoke the operation asynchronously

When asynchronous message exchange is enabled, WS-Addressing support is enabled and a wsa:ReplyTo header is added to the SOAP request. The HTTP request is immediately acknowledged and the original connection is closed. The client then starts a local HTTP server and listens for the response from the endpoint.

Note that this property is specific to IBM's implementation of JAX-WS and won't work on other vendor’s implementations. It is, however, compatible with any endpoint that supports WS-Addressing,k such as other WebSphere Application Server or Microsoft .NET endpoints.


Summary

JAX-WS introduces an asynchronous programming model via polling and callback APIs. Asynchronous Web service calls are non-blocking, which means that an application can invoke a Web service and can continue running the business logic without waiting for a response. The introduction of such a powerful programming model, which was lacking in JAX-RPC, is a good enough reason for customers to migrate from JAX-RPC to new JAX-WS.


Resources

Learn

Get products and technologies

Discuss

About the authors

Dan Sedov photo

Dan 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 photo

Nikhil 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.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


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. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

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.

(Must be between 3 – 31 characters.)

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

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere, SOA and Web services
ArticleID=304597
ArticleTitle=JAX-WS client APIs in the Web Services Feature Pack for WebSphere Application Server V6.1, Part 3: Using the JAX-WS asynchronous programming model
publish-date=04302008
author1-email=sedov@us.ibm.com
author1-email-cc=crothemi@us.ibm.com
author2-email=nikhil.v.thaker@us.ibm.com
author2-email-cc=crothemi@us.ibm.com

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers