Chapter 9. Asynchronous Web Services

Table of Contents

9.1. Overview
9.2. Asynchronous Client Operation
9.2.1. Using a Service Endpoint Interface Stub with Asynchronous Methods
9.2.2. Using a Dispatch Interface
9.3. Asynchronous Web Services
9.3.1. Configuring Asynchronous Web Services

This chapter describes how to configure asynchronous client operations and asynchronous web services that use an asynchronous provider.

9.1. Overview

In invoking a web service between a service and a client, the client blocks the thread until it receives a response from the server. To resolve such performance issues, JAS-WS web service provides asynchronous client operations.

  • Asynchronous operation using the client-side JAX-WS API.

    To create a JAX-WS client, use the WSDL file of the service to invoke. A service endpoint interface stub with a static asynchronous method is created through custom binding declarations of the file. A client class that implements the stub is created to implement asynchronous client operations.

  • Non-standard asynchronous operation provided by JEUS on the service end.

    This creates a web service endpoint by using an asynchronous web service that operates in an asynchronous method of servlet 3.0. JAX-WS standard does not specify asynchronous operations on the service end.

9.2. Asynchronous Client Operation

This section describes asynchronous operations that use client-side JAX-WS API.

9.2.1. Using a Service Endpoint Interface Stub with Asynchronous Methods

Asynchronous wsdl:operation is mapped to the polling and callback methods. The polling method returns the javax.xml.ws.Response interface object, and the callback method returns the javax.xml.ws.AsyncHandler interface object. This section describes an asynchronous binding declaration that is used to obtain a service endpoint interface (hereafter, SEI) stub, which has asynchronous methods, from WSDL.

9.2.1.1. Declaring an Asynchronous Binding

To use the wsdl:operation element for an asynchronized mapping, an SEI based on asynchronous wsdl:operation mapping must be created by using the wsimport tool.

This section introduces how to create such an asynchronous wsdl:operation mapping.

To create asynchronous wsdl:operation mapping, bindings should be customized using the wsimport tool. The following is the binding configuration file, custom-schema.xml.

[Example 9.1] << custom-schema.xml >>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    wsdlLocation="http://localhost:8088/AddNumbers/addnumbers?wsdl"
    xmlns="http://java.sun.com/xml/ns/jaxws">
    <bindings node="wsdl:definitions">
        <enableAsyncMapping>true</enableAsyncMapping>
    </bindings>
</bindings>

If the binding setting is configured for wsdl:definitions as in the previous example, all wsdl:operation elements in the WSDL document have the same asynchronization setting.

The following is the portion of the build.xml file that uses the custom-schema.xml file.

[Example 9.2] << build.xml >>

...

<target name="build_client" depends="do-deploy-success, init">
    <antcall target="wsimport">
        <param name="package.name" value="async.client" />
        <param name="binding.file" value="-b ${src.conf}/custom-client.xml" />
        <param name="wsdl.file"
            value="http://localhost:8088/AddNumbers/addnumbers?wsdl" />
    </antcall>
    <antcall target="do-compile">
        <param name="javac.excludes" value="fromjava/server/" />
    </antcall>
</target>

...

Portable artifacts, which are created through the wsimport tool, are used to create the SEI with asynchronous methods as in the following.

public int addNumbers(int number1, int number2)
    throws java.rmi.RemoteException;
public Response<AddNumbersResponse> addNumbers(int number1, int number2);
public Future<?> addNumbers(int number1, int number2, 
                            AsyncHandler<AddNumbersResponse>);

As shown in the previous example, the two methods (polling and callback), whose return values are Response<AddNumbersResponse> and Future<?>, have been created. The following sub-sections describe how to create a Java client class using the two methods.

9.2.1.2. Configuring an Asynchronous Client

Asynchronous clients can be configured by using the polling or callback method.

How to create a client by using the polling method

The following is the polling method of an asynchronous SEI obtained through the wsimport tool.

public Response<AddNumbersResponse> addNumbers(int number1, int number2);

The following is an example of a client web service implemented by the method mapped to the polling method. The client application invokes an asynchronous polling method of SEI, and can check for the result.

javax.xml.ws.Response<AddNumbersResponse> resp = port.addNumbersAsync(10, 20);
while(!resp.isDone()){
}
System.out.println(resp.get().getReturn());
...

As shown in the previous example, the method mapped to the polling method returns the javax.xml.ws.Response object. The object can determine when the operation is complete by using the isDone() method inherited from java.util.concurrent.Future<T>, and return the result.

The following example shows a part of a client application code that supports the polling method.

[Example 9.3] << AddNumbersClient.java >>

public class AddNumbersClient {

   ...

   public static void main(String[] args) {
       try {
           AddNumbersImpl port = new AddNumbersService().getAddNumbersImplPort();

           // Asynchronous polling
           Response<AddNumbersResponse> resp = port.addNumbersAsync(10, 20);
           Thread.sleep(2000);
           AddNumbersResponse output = resp.get();
           System.out.println("#############################################");
           System.out.println("### JAX-WS Webservices examples - polling ###");
           System.out.println("#############################################");
           System.out.printf("call webservices in an Asynchronous Polling way...");
           System.out.printf("result : %d\n", output.getReturn());

           ...

       } catch (Exception e) {
           e.printStackTrace();
       }
   }

    ...

}

How to create a client by using the callback method

The following is the callback method of an asynchronous SEI obtained through the wsimport tool.

public Future<?> addNumbers(int number1, int number2,
    AsyncHandler<AddNumbersResponse>);

The method mapped to the callback method provides a handler object that implements the javax.xml.ws.AsynchHandler interface as an additional parameter.

The following is an example code of a handler object that implements the AsynchHandler interface.

[Example 9.4] << AddNumbersClient.java >>

public class AddNumbersClient {

    ...

    static class AddNumbersCallbackHandler implements
            AsyncHandler<AddNumbersResponse> {

        private AddNumbersResponse output;

        public void handleResponse(Response<AddNumbersResponse> response) {
            try {
                output = response.get();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        AddNumbersResponse getResponse() {
            return output;
        }
    }
}

The handler object invokes the handleResponse method when it obtains the web service operation result from the server at runtime. The client application can obtain the result by using the getResponse() method.

The following example is a part of client application code that uses the asynchronous callback method of SEI through the handler object. The client application invokes the asynchronous callback method of SEI, and checks for the result.

AddNumbersCallbackHandler callbackHandler = new AddNumbersCallbackHandler();
Future<?> resp = port.addNumbersAsync(number1, number2, callbackHandler);
while(!resp.isDone()){
}
System.out.println(callbackHandler .getResponse().getReturn());

As shown in the previous example, the method mapped to the callback method returns the javax.util.concurrent.Future object. The object can determine when the operation is complete by using the isDone() method, and return the result.

The following example is a part of the client application code that uses the asynchronous callback method of SEI.

[Example 9.5] << AddNumbersClient.java >>

public class AddNumbersClient {

  public static void main(String[] args) {
    try {
        AddNumbersImpl port = new AddNumbersService().getAddNumbersImplPort();
          ...

        // Asynchronous callback
        AddNumbersCallbackHandler callbackHandler = new AddNumbersCallbackHandler();
        Future<?> response = port.addNumbersAsync(10, 20, callbackHandler);
        Thread.sleep(2000);

        output = callbackHandler.getResponse();
        System.out.println("#############################################");
        System.out.println("### JAX-WS Webservices examples - callback ###");
        System.out.println("#############################################");
        System.out.printf("call webservices in an Asynchronous Callback way...");
        System.out.printf("result: %d\n", output.getReturn());
     } catch (Exception e) {
         e.printStackTrace();
     }
  }
    ...
}

9.2.1.3. Executing an Asynchronous Client

This section shows how to execute an asynchronous client by using the implemented classes and other configuration files in this section.

Create a web service configured with asynchronous operations and deploy it to JEUS by using the following command.

$ ant build deploy

Once the service is deployed successfully, build the client.

Create a client configured with the handler framework, and invoke the service from the client.

As shown in the following, the console outputs the result of calling the polling and callback methods that have been processed successfully.

$ ant run

...

run:
     [java] #############################################
     [java] ### JAX-WS Webservices examples - polling ###
     [java] #############################################
     [java] call webservices in an Asynchronous Polling way...result : 30
     [java] #############################################
     [java] ### JAX-WS Webservices examples - callback ###
     [java] #############################################
     [java] call webservices in an Asynchronous Callback way...result: 30

...

BUILD SUCCESSFUL

9.2.2. Using a Dispatch Interface

Using a client's asynchronous operation by using a dispatch interface is similar to the description in the previous section. The only difference is that the invokeAsync method, which is provided by the created dispatch object, is used.

The following is an example of using the invokeAsync method.

Response<T> response = dispatch.invokeAsync(T);
Future<?> response = dispatch.invokeAsync(T, AsyncHandler);

As shown in the previous example, the invokeAsync(T) method supports asynchronization with the polling method, while the invokeAsync(T, AsyncHandler) method uses the callback method. For AsyncHandler, a user handler is implemented as the callback method.

9.3. Asynchronous Web Services

JEUS JAX-WS provides a way to create an asynchronous web service based on servlet 3.0 asynchronous processing. Since a web service endpoint is synchronized during request processing, it occupies the request processing thread allocated by the servlet container increasing the processing time. This can often cause other requests to wait for a thread. In this case, separate threads are assigned for services that require longer processing time, and request processing threads are returned to the container so that the pending requests can be processed efficiently.

This section describes how to configure asynchronous web services.

9.3.1. Configuring Asynchronous Web Services

JEUS provides the following ways to create a JAX-WS web service as an asynchronous web service.

  • When using the @jeus.webservices.jaxws.api.AsyncWebService Annotation

    The following is an example of configuring a web service as an asynchronous web service by using Annotation.

    [Example 9.6] << AddNumbersImpl.java >>

    @WebService(serviceName="AddNumbers")
    @AsyncWebService        
    public class AddNumbersImpl {
    
        public int addNumbers(int number1, int number2) {
            return number1 + number2;
        }
    }


  • When using the <async-supported> element in web.xml

    A web service that is already implemented can be configured as an asynchronous web service by using the <async-supported> element, which is supported by servlet 3.0, in web.xml.

    [Example 9.7] << web.xml >>

    <web-app>
        <servlet>
            <servlet-name>AddNumbers</servlet-name>
            <servlet-class>fromwsdl.server.AddNumbersImpl</servlet-class>
            <async-supported>true</async-supported>
        </servlet>
        <servlet-mapping>
            <servlet-name>AddNumbers</servlet-name>
            <url-pattern>/addnumbers</url-pattern>
        </servlet-mapping>
    </web-app>