+

Search Tips   |   Advanced Search

Invoking JAX-WS web services asynchronously

JAX-WS provides support for invoking web services using an asynchronous client invocation. JAX-WS provides support for both a callback and polling model when calling web services asynchronously. Both the callback model and the polling model are available on the Dispatch client and the Dynamic Proxy client.

Develop a JAX-WS Dynamic Proxy or Dispatch client. When developing Dynamic Proxy clients, after you generate the portable client artifacts from a WSDL file using the wsimport command, the generated service endpoint interface (SEI) does not have asynchronous methods included in the interface. Use JAX-WS bindings to add the asynchronous callback or polling methods on the interface for the Dynamic Proxy client. To enable asynchronous mappings, we can add the jaxws:enableAsyncMapping binding declaration to the WSDL file. For more information on adding binding customizations to generate an asynchronous interface, see chapter 8 of the JAX-WS specification.

Supported configurations: When you run the wsimport tool and enable asynchronous invocation through the use of the JAX-WS enableAsyncMapping binding declaration, ensure that the corresponding response message the WSDL file does not contain parts. When a response message does not contain parts, the request acts as a two-way request, but the actual response that is sent back is empty. The wsimport tool does not correctly handle a void response. To avoid this scenario, we can remove the output message from the operation which makes your operation a one-way operation or we can add a <wsdl:part> to your message. For more information on the usage, syntax and parameters for the wsimport tool, see the wsimport command for JAX-WS applications documentation..

An asynchronous invocation of a web service sends a request to the service endpoint and then immediately returns control to the client program without waiting for the response to return from the service. JAX-WS asynchronous web service clients consume web services using either the callback approach or the polling approach. Using a polling model, a client can issue a request and receive a response object that is polled to determine if the server has responded. When the server responds, the actual response is retrieved. Using the callback model, the client provides a callback handler to accept and process the inbound response object. The handleResponse() method of the handler is called when the result is available. Both the polling and callback models enable the client to focus on continuing to process work without waiting for a response to return, while providing for a more dynamic and efficient model to invoke web services. Polling invocations are valid from EJB clients or JEE (Java EE) application clients. Callback invocations are valid only from Java EE application clients.

Use the callback asynchronous invocation model

To implement an asynchronous invocation that uses the callback model, the client provides an AsyncHandler callback handler to accept and process the inbound response object. The client callback handler implements the javax.xml.ws.AsyncHandler interface, which contains the application code that is run when an asynchronous response is received from the server. The javax.xml.ws.AsyncHandler interface contains the handleResponse(java.xml.ws.Response) method that is called after the run time has received and processed the asynchronous response from the server. The response is delivered to the callback handler in the form of a javax.xml.ws.Response object. The response object returns the response content when the get() method is called. Additionally, if an error was received, then an exception is returned to the client during that call. The response method is then invoked according to the threading model used by the executor method, java.util.concurrent.Executor on the client's java.xml.ws.Service instance that was used to create the Dynamic Proxy or Dispatch client instance. The executor is used to invoke any asynchronous callbacks registered by the application. Use the setExecutor and getExecutor methods to modify and retrieve the executor configured for the service.

Use the polling asynchronous invocation model

Use the polling model, a client can issue a request and receive a response object that can subsequently be polled to determine if the server has responded. When the server responds, the actual response can then be retrieved. The response object returns the response content when the get() method is called. The client receives an object of type javax.xml.ws.Response from the invokeAsync method. That Response object is used to monitor the status of the request to the server, determine when the operation has completed, and to retrieve the response results.

Use an asynchronous message exchange

By default, asynchronous client invocations do not have asynchronous behavior of the message exchange pattern on the wire. The programming model is asynchronous; however, the exchange of request or response messages with the server is not asynchronous. To use an asynchronous message exchange, the com.ibm.websphere.webservices.use.async.mep property must be set on the client request context with a boolean value of true. When this property is enabled, the messages exchanged between the client and server are different from messages exchanged synchronously. With an asynchronous exchange, the request and response messages have WS-Addressing headers added that provide additional routing information for the messages. Another major difference between asynchronous and synchronous message exchange is that the response is delivered to an asynchronous listener that then delivers that response back to the client. For asynchronous exchanges, there is no timeout that is sent to notify the client to stop listening for a response. To force the client to stop waiting for a response, issue a Response.cancel() method on the object returned from a polling invocation or a Future.cancel() method on the object returned from a callback invocation. The cancel response does not affect the server when processing a request.

The location of the asynchronous listener is sent to the server, so that the service can reply to the client. On Windows operating systems, the local host name is used by default, because it is compatible with Dynamic Host Configuration Protocol (DHCP). However, if the server cannot resolve the host name, the client application does not receive replies from the target service. For example, a client application is hosted on the workstation myhost.bar.com. In the following SOAP message header, the client application sends the short name myhost as its host details. Unless the target server can resolve myhost to myhost.bar.com, subsequent replies do not reach the client application:

  <soapenv:Header>    
    <wsa:To>http://target.bar.com:81/LiteSecurityService/SecurityService</wsa:To>
    <wsa:ReplyTo>        
      <wsa:Address>http://myhost:2146/axis2/services/LiteSecurityService.
        WSRMServicePort/AnonOutInOp?IBMwebservicesID=922A5DC38A337C4CEF1168347862705
      </wsa:Address>
    </wsa:ReplyTo>
    <wsa:MessageID>urn:uuid:922A5DC38A337C4CEF1168347862403</wsa:MessageID>
    <wsa:Action>getEndpointReference</wsa:Action>
  </soapenv:Header>
To resolve this issue, configure the client to send the location details for the asynchronous listener in IP format, by adding the following system property to the Java virtual machine. Note that by transmitting the IP address, you lose the benefits of DHCP.

gotcha

  1. Determine if to implement the callback method or the polling method for the client to asynchronously invoke the web service.

  2. Optional. Configure the client request context. Add the

      com.ibm.websphere.webservices.use.async.mep

    property to the request context to enable asynchronous messaging for the web services client. Using this property requires that the service endpoint supports WS-Addressing which is supported by default for the application server. The following example demonstrates how to set this property:

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

  3. To implement the asynchronous callback method, perform the following steps.

    1. Find the asynchronous callback method on the SEI or javax.xml.ws.Dispatch interface. For an SEI, the method name ends in Async and has one more parameter than the synchronous method of type javax.xml.ws.AsyncHandler. The invokeAsync(Object, AsyncHandler) method is the one used on the Dispatch interface.

    2. Optional. Add the service.setExecutor methods to the client application. Adding the executor methods gives the client control of the scheduling methods for processing the response. We can also choose to use the java.current.Executors class factory to obtain packaged executors or implement our own executor class. See the JAX-WS specification for more information on using executor class methods with the client.

    3. Implement the javax.xml.ws.AsyncHandler interface. The javax.xml.ws.AsyncHandler interface only has the handleResponse(javax.xml.ws.Response) method. The method must contain the logic for processing the response or possibly an exception. The method is called after the client run time has received and processed the asynchronous response from the server.

    4. Invoke the asynchronous callback method with the parameter data and the callback handler.

    5. The handleResponse(Response) method is invoked on the callback object when the response is available. The Response.get() method is called within this method to deliver the response.

  4. To implement the polling method,

    1. Find the asynchronous polling method on the SEI or javax.xml.ws.Dispatch interface. For an SEI, the method name ends in Async and has a return type of javax.xml.ws.Response. The invokeAsync(Object) method is used on the Dispatch interface.

    2. Invoke the asynchronous polling method with the parameter data.

    3. The client receives the object type, javax.xml.ws.Response, used to monitor the status of the request to the server. The isDone() method indicates whether the invocation has completed. When the isDone() method returns a value of true, call the get() method to retrieve the response object.

  5. Use the cancel() method for the callback or polling method if the client needs to stop waiting for a response from the service. If the cancel() method is invoked by the client, the endpoint continues to process the request. However, the wait and response processing for the client is stopped.


Results

You have enabled the JAX-WS web service client to asynchronously invoke and consume web services. See the JAX-WS specification for additional information regarding the asynchronous client APIs.


Example

The following example illustrates a web service interface with methods for asynchronous requests from the client.

@WebService

public interface CreditRatingService {
       // Synchronous operation.
       Score getCreditScore(Customer     customer);
       // Asynchronous operation with polling.
       Response<Score> getCreditScoreAsync(Customer customer);
       // Asynchronous operation with callback.
       Future<?> getQuoteAsync(Customer customer, 
              AsyncHandler<Score> handler);
}

Use the callback method

The callback method requires a callback handler that is shown in the following example. When using the callback procedure, after a request is made, the callback handler is responsible for handling the response. The response value is a response or possibly an exception. The Future<?> method represents the result of an asynchronous computation and is checked to see if the computation is complete. When we want the application to find out if the request is completed, invoke the Future.isDone() method. Note that the Future.get() method does not provide a meaningful response and is not similar to the Response.get() method.

CreditRatingService svc = ...;
 
Future<?> invocation = svc.getCreditScoreAsync(customerTom, new AsyncHandler<Score>() {
              public void handleResponse (
                     Response<Score> response)
                  {
                     score = response.get();
                     // process the request...
                  }
    }
);

Use the polling method

The following example illustrates an asynchronous polling client:

CreditRatingService svc = ...;
Response<Score> response = svc.getCreditScoreAsync(customerTom);
 
while (!response.isDone()) {
       // Do something while we wait.
}

score = response.get();


Related concepts

  • JAX-WS
  • JAX-WS client programming model


    Related tasks

  • Implement static JAX-WS web services clients
  • Generating Java artifacts for JAX-WS applications from a WSDL file
  • Develop a dynamic client using JAX-WS APIs
  • Use the JAX-WS asynchronous response servlet

  • Web services specifications and APIs


    Related information:

    JAX-WS API documentation
    JAX-WS API User's Guide documentation