jws

JAX-WS Callback Example

1. Introduction

Java Architecture for XML Web Services (JAX-WS) is a Java programming language for creating web services, particularly SOAP services.

JAX-WS provides both Callback and Polling mechanisms to invoke web services asynchronously. In Callback mode, the client provides a callback handler to accept and process the inbound response object.

In this example, I will demonstrate how to invoke a JAX-WS service asynchronously via the callback mechanism.

2. Business Use Case

A HelloService takes exactly 1 minute to complete the sayHello operation. The client of HelloService wants to continue with other tasks while waiting for the response from sayHello for performance purposes.

3. Technologies used

The example code in this article was built and run using:

  • Java 1.8.101 (1.8.x will do fine)
  • Maven 3.3.9 (3.3.x will do fine)
  • Eclipse Mars (Any Java IDE would work)

4. JAX-WS Service

Create a project named jax-ws-server-jdk which creates HelloService with one operation: sayHello.

4.1. HelloService Interface

Create a HelloService interface and annotate it with @WebService.

HelloService.java

package jcg.demo.jaxws.service;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

@WebService(name = "HelloService", targetNamespace = "http://jcg.demo.async.ws")
@SOAPBinding(style = Style.DOCUMENT)
public interface HelloService {

	@WebMethod
	String sayHello(String msg);

}

4.2. HelloServiceImpl Class

Create a HelloServiceImpl to implement the HelloServiceInterface.

HelloService.java

package jcg.demo.jaxws.service.impl;

import javax.jws.WebService;

import jcg.demo.jaxws.service.HelloService;

@WebService(endpointInterface = "jcg.demo.jaxws.service.HelloService")
public class HelloServiceImpl implements HelloService {

	private static final int ONE_MINUTES = 60000;

	@Override
	public String sayHello(String message) {

		try {
			Thread.sleep(ONE_MINUTES);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("Server sayHello to " + message);
		return "Hello " + message;
	}

}

4.3. HelloServerApp

Publish the HelloServiceImpl at http://localhost:9980/hello?wsdl.

HelloServerApp.java

package jcg.demo.jaxws;

import javax.xml.ws.Endpoint;

import jcg.demo.jaxws.service.impl.HelloServiceImpl;

public class HelloServerApp {

	public static void main(String[] args) {
		Endpoint ep = Endpoint.create(new HelloServiceImpl());
		ep.publish("http://localhost:9980/hello");
	}
}

5. Generate Client with AyncMapping Enabled

Create a project named jax-ws-client-static which generates a JAX-WS client from http://localhost:9980/hello?wsdl with enableAsyncMapping enabled.

5.1. POM.XML

Configure Maven POM.xml to generate the JAX-WS client with enableAsyncMapping enabled.

async-bindings.xml

<?xml version="1.0" encoding="UTF-8"?>

<bindings xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
	wsdlLocation="http://localhost:9980/hello?wsdl" xmlns="http://java.sun.com/xml/ns/jaxws">

	<!-- applies to wsdl:definitions node, that would mean the entire wsdl -->
	<enableAsyncMapping>true</enableAsyncMapping>

</bindings>

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>jax-ws-client</groupId>
	<artifactId>jax-ws-client-static</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>

	<profiles>
		<profile>
			<id>codegen</id>
			<build>
				<plugins>
					<plugin>
						<groupId>org.codehaus.mojo</groupId>
						<artifactId>jaxws-maven-plugin</artifactId>
						<version>1.12</version>
						<executions>
							<execution>
								<id>hello_wsdl</id>
								<goals>
									<goal>wsimport</goal>
								</goals>
								<configuration>
									<wsdlUrls>
										<wsdlUrl>http://localhost:9980/hello?wsdl</wsdlUrl>
									</wsdlUrls>
									<bindingDirectory>${basedir}/src/main/resources/jaxws</bindingDirectory>
									<keep>true</keep>
									<packageName>jcg.demo.jaxws.client.hello</packageName>
									<sourceDestDir>src/generated/java</sourceDestDir>
								</configuration>
							</execution>

						</executions>
					</plugin>
				</plugins>
			</build>
		</profile>
	</profiles>
</project>

5.2. HelloService Generated Code

Execute mv install -P codegen to generate the source code and verify that HelloService has three operations:

  • sayHello for synchronous call
  • Response sayHelloAsync for asynchronous call with polling
  • Future sayHelloAsync for asynchronous call with callback

HelloService.java

package jcg.demo.jaxws.client.hello;

import java.util.concurrent.Future;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.AsyncHandler;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.Response;
import javax.xml.ws.ResponseWrapper;


/**
 * This class was generated by the JAX-WS RI.
 * JAX-WS RI 2.1.7-b01-
 * Generated source version: 2.1
 * 
 */
@WebService(name = "HelloService", targetNamespace = "http://jcg.demo.async.ws")
@XmlSeeAlso({
    ObjectFactory.class
})
public interface HelloService {


    /**
     * 
     * @param arg0
     * @return
     *     returns javax.xml.ws.Response<jcg.demo.jaxws.client.hello.SayHelloResponse>
     */
    @WebMethod(operationName = "sayHello")
    @RequestWrapper(localName = "sayHello", targetNamespace = "http://jcg.demo.async.ws", className = "jcg.demo.jaxws.client.hello.SayHello")
    @ResponseWrapper(localName = "sayHelloResponse", targetNamespace = "http://jcg.demo.async.ws", className = "jcg.demo.jaxws.client.hello.SayHelloResponse")
    public Response<SayHelloResponse> sayHelloAsync(
        @WebParam(name = "arg0", targetNamespace = "")
        String arg0);

    /**
     * 
     * @param arg0
     * @param asyncHandler
     * @return
     *     returns java.util.concurrent.Future<? extends java.lang.Object>
     */
    @WebMethod(operationName = "sayHello")
    @RequestWrapper(localName = "sayHello", targetNamespace = "http://jcg.demo.async.ws", className = "jcg.demo.jaxws.client.hello.SayHello")
    @ResponseWrapper(localName = "sayHelloResponse", targetNamespace = "http://jcg.demo.async.ws", className = "jcg.demo.jaxws.client.hello.SayHelloResponse")
    public Future<?> sayHelloAsync(
        @WebParam(name = "arg0", targetNamespace = "")
        String arg0,
        @WebParam(name = "asyncHandler", targetNamespace = "")
        AsyncHandler<SayHelloResponse> asyncHandler);

    /**
     * 
     * @param arg0
     * @return
     *     returns java.lang.String
     */
    @WebMethod
    @WebResult(targetNamespace = "")
    @RequestWrapper(localName = "sayHello", targetNamespace = "http://jcg.demo.async.ws", className = "jcg.demo.jaxws.client.hello.SayHello")
    @ResponseWrapper(localName = "sayHelloResponse", targetNamespace = "http://jcg.demo.async.ws", className = "jcg.demo.jaxws.client.hello.SayHelloResponse")
    public String sayHello(
        @WebParam(name = "arg0", targetNamespace = "")
        String arg0);

}

5.3. ClientApp

Create a client application which invokes the service asynchronously.

ClientApp.java

package jcg.demo.callback;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import javax.xml.ws.Response;

import jcg.demo.jaxws.client.hello.HelloService;
import jcg.demo.jaxws.client.hello.HelloServiceImplService;
import jcg.demo.jaxws.client.hello.SayHelloResponse;

public class ClientApp {
	private static final int TEN_SECONDS = 10000;
	private static final String MESSAGE_DEMO = "Mary Zheng";

	public static void main(String args[]) {
		HelloServiceImplService client = new HelloServiceImplService();
		HelloService helloService = client.getHelloServiceImplPort();

		try {
			invokeSync(helloService);
			invokeAsyncWithCallBack(helloService);
			invokeAsyncWithPolling(helloService);
		} catch (InterruptedException | ExecutionException e) {

			e.printStackTrace();
		}

	}

	private static void invokeSync(HelloService helloService) {
		String retFromServer = helloService.sayHello(MESSAGE_DEMO);
		System.out.println("Program waits till service returns. " + retFromServer);

	}

	private static void invokeAsyncWithPolling(HelloService helloService)
			throws InterruptedException, ExecutionException {

		Response response = helloService.sayHelloAsync(MESSAGE_DEMO);

		while (!response.isDone()) {
			Thread.sleep(TEN_SECONDS);
			System.out.println("Program can do something while waiting and checking if the response is done. ");
		}
		SayHelloResponse output = response.get();
		System.out.println("Retrieved via polling: " + output.getReturn());

	}

	private static void invokeAsyncWithCallBack(HelloService helloService) throws InterruptedException {

		Future future = helloService.sayHelloAsync(MESSAGE_DEMO, (response) -> {
			try {
				System.out.println("Retrieved via callback response: " + response.get().getReturn());
			} catch (Exception exc) {
				System.out.println(exc.getClass().getName() + " using callback for response:" + exc.getMessage());
			}
		});

		for (int i = 0; i < 9; i++) {
			System.out.println("Program can do something while waiting for the callback response!!!");
			Thread.sleep(TEN_SECONDS);
		}

	}
}

6. Demo Time

Start HelloServerApp and ClientApp.

ClientApp output

Program waits till service returns. Hello Mary Zheng
Program can do something while waiting for the callback response!!!
Program can do something while waiting for the callback response!!!
Program can do something while waiting for the callback response!!!
Program can do something while waiting for the callback response!!!
Program can do something while waiting for the callback response!!!
Program can do something while waiting for the callback response!!!
Program can do something while waiting for the callback response!!!
Retrieved via callback response: Hello Mary Zheng
Program can do something while waiting for the callback response!!!
Program can do something while waiting for the callback response!!!
Program can do something while waiting and checking if the response is done. 
Program can do something while waiting and checking if the response is done. 
Program can do something while waiting and checking if the response is done. 
Program can do something while waiting and checking if the response is done. 
Program can do something while waiting and checking if the response is done. 
Program can do something while waiting and checking if the response is done. 
Program can do something while waiting and checking if the response is done. 
Retrieved via polling: Hello Mary Zheng

Note: Both invokeAsyncWithCallBack and invokeAsyncWithPolling allow the client to continue on other task while waiting for the service response.

7. Summary

In this example, I first built a JAX-WS service: HelloService. Then I built a JAX-WS client from the server WSDL with asyncMapping enabled. Lastly I built a clientApp to demonstrate how to invoke the service asynchronously.

8. Download the Source Code

This example consists of a JAX-WS service and JAX-WS client which invokes the service asynchronously with callback.

Download
You can download the full source code of this example here: JAX-WS Callback Example

Mary Zheng

Mary has graduated from Mechanical Engineering department at ShangHai JiaoTong University. She also holds a Master degree in Computer Science from Webster University. During her studies she has been involved with a large number of projects ranging from programming and software engineering. She works as a senior Software Engineer in the telecommunications sector where she acts as a leader and works with others to design, implement, and monitor the software solution.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Mohit
Mohit
2 years ago

Good work. Was able to use it almost seamlessly and exactly what I was looking for. Very basic example to get started along with right level of explanation.

Back to top button