Implement an Asynchronous Web Service using JAX-WS in JDeveloper

1

This article discusses how to implement an asynchronous web service in


Java EE. The Java application will expose a one way operation that will process the request and send a response message to a callback Web Service interface that is indicated in the request header through WS Addressing properties (messageID, replyToAddress). The Asynchronous Web Service is subsequently deployed and invoked from SoapUI.

The article starts with nothing but a simple WSDL file that defines the two portTypes: one way call and the [one way]call back:

SNAGHTML1c7c2772

The main steps are:

  1. Generate the JAX-WS Client & Proxy for the ThoughtfulGreeterCallback portType (to invoke the callback service in order to send the response)
  2. Generate the JAX-WS Web Service for the ThoughtfulGreeter portType (to implement the one way web service)
  3. Edit the generated code for the ThoughtfulGreeter portType in order to create the response and invoke the callback interface – used on WS-Addressing details in the request

When the implementation is thus complete, we create a new project in SoapUI. In this project, we will create a test request to invoke the ThoughtfulGreeter service. We will also create a MockService in SoapUI to act as the callback interface ThoughfulGreeterCallback. In the request from SoapUI to the ThoughtfulGreeter service, we will specify WS-Addressing properties that refer to the MockService.

Finally, when we have SoapUI make the call to the ThoughtfulGreeter service, we will receive a call (back) to the MockService, containing the response.

Note: this article is a cross post from the Oracle SOA Suite Handbook blog.

Generate the JAX-WS Client & Proxy for the ThoughtfulGreeterCallback portType

(to invoke the callback service in order to send the response)

Create a new Java EE Web Application through the New Gallery wizard in JDeveloper:

image

Set the name of the application – for example to AsynchronousJavaWebService – and the package prefix – for example saibot.airport.services.pr. Press Next.

image

On page 5, set the name of the View project to WebServices.

image

Press Finish.

From the New Gallery, select item Web Service Client and Proxy – to generate the objects to invoke a Web Service from Java:

image

Select the WSDL for the ThoughtfulGreeterService:
image

The WSDL contains two port types but no service element (it is abstract). A warning will be presented by JDeveloper – about generating a default service element. Press Yes to accept this action.

image

Accept all defaults. On step 4, JDeveloper indicates it will generate proxies for two port types (or ports) in the web service definition:

image

Do not generate any asynchronous methods:

image

The last step presents an overview of what the wizard is about to generate. Press finish.

image

The proxy we have just created is intended only to invoke the Callback service to return the response to (asynchronously). The classes ThoughtfulGreeterPortClient and ThoughtfulGreeter are not required to the call back – and can be removed from the project.

image

The usages are presented. Proceed with the removal.

image

Generate the JAX-WS Web Service for the ThoughtfulGreeter portType

(to implement the one way web service)

Note: To prevent us from having to remove unwanted stuff later on, I have commented out the callback binding and portType in the WSDL document before running the Java Web Service wizard.

image

image

image

image

Press Finish to have the Java Web Service generated.

The generated objects are added to the project:

image

Make a small change to the class ThoughtfulGreeterImpl – to see that the one way service has been invoked:

System.out.println("Request received; it contains name= "+payload.getName());

image

Run the Web Service (which will build and deploy the Web Application to the Integrated WebLogic Server):

image

When the deployment is complete, the Web Service is available to be invoked:

image

Click on the URL shown. This will bring up the HTTP Analyzer tool in JDeveloper. This tool will inspect the WSDL document for the web service and present an interface based on the service interface. Enter a value for name and press Send Request:

image

In the console we can see that the Web Service has been invoked

image

Edit the generated Java code for the ThoughtfulGreeter portType

in order to create the response and invoke the callback interface – used on WS-Addressing details in the request.Open class ThoughtfulGreeterImpl.

Add @Resource for WebServiceContext.to ThoughtfulGreeterImpl Class

public class ThoughtfulGreeterImpl {
@Resource
WebServiceContext context;
public ThoughtfulGreeterImpl() {
}

image

Add method callbackToHelloFromWorld to ThoughtfulGreeterImpl Class. This method uses the ThoughtfulGreeterCallback Port on the ThoughtfulGreeterService to invoke the callback service. The message context, retrieved from the WebServiceContext, contains the endpoint address at which the invoker of the one way helloToWorld operation suggest the callback interface is exposed. It also contains the messageId that is to be sent in the callback call to allow the consumer of the asynchronous service to complete the correlation of the response with the original request.

private void callbackToHelloFromWorld(GreetingResponseType greetingResponse) {
// invoke the generated WebService Proxy to pass back the greeting response
HeaderList hl = (HeaderList) context.getMessageContext().get(JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY);
// gets the addressing informations in the SOAP header
WSEndpointReference reference = hl.getReplyTo(AddressingVersion.W3C, SOAPVersion.SOAP_11);
String messageId = hl.getMessageID(AddressingVersion.W3C, SOAPVersion.SOAP_11);

ThoughtfulGreeterService thoughtfulGreeterService = new ThoughtfulGreeterService();
ThoughtfulGreeterCallback thoughtfulGreeterCallback =
thoughtfulGreeterService.getThoughtfulGreeterCallbackPort();

WSBindingProvider bp = (WSBindingProvider) thoughtfulGreeterCallback;
bp.setAddress(reference.getAddress());
bp.setOutboundHeaders(Headers.create(AddressingVersion.W3C.relatesToTag, messageId));
System.out.println("Call back address = "+ reference.getAddress());
System.out.println("Message id = "+messageId);
System.out.println("call callback now ************************************************************");

thoughtfulGreeterCallback.helloFromWorld(greetingResponse);
}

Add lines in method helloToWorld to create the response and invoke callbackToHelloFromWorld:

GreetingResponseType response = new GreetingResponseType();
response.setGreeting("Hello from the world to " + payload.getName());
callbackToHelloFromWorld(response);

Right click on the ThoughtfulGreeterService and select Run from the context menu. This will make the application be built and (re)deployed.

image

The console then shows (again) the address at which the service is available.

Setup the SoapUI Test Project

SoapUI is a good for testing web services – SOAP and REST – other services as well. It can handle XML and JSON and other payloads. It can deal with asynchronous services – because it can expose the callback interface to which the asynchronous response is to be returned. We will look at SoapUI in our current example.

Create a new SoapUI project – based on the WSDL document exposed by the deployed ThoughtfulGreeter service (at the address shown as Target URL in the console after deployment – with ?WSDL added at the end): http://localhost:7101/AsynchronousJavaWebService-WebServices-context-root/ThoughtfulGreeterSOAP11BindingPort?WSDL).

image

The project is created – here is what it looks like:

image

Next, we need a MockService in SoapUI – to implement the callback interface (PortType ThoughtfulGreeterCallback) for the ThoughtfulGreeterService. Right click on the project in SoapUI. Select New SOAP MockService from the context menu.

image

Set the name of the MockService to ThoughtfulGreeterCallbackService:

image

And click on OK.

Add a MockOperation – from the context menu on the MockService.

image

Select the operation helloFromWorld (in the ThoughtfulGreeterCallbackSOAP11Binding in the WSDL for the ThoughtfulGreeterService):

image

Open the MockService Editor, from the context menu on the Mock Service:

image

Open the options window for the Mock Service:

image

Set the Path and Port for the Mock Service to appropriate values – such as /MockThoughfulGreeterCallback and 8081:

image

Start the Mock Service. Note we do not have to specify a response message for this mock service and operation. The operation is one-way – only to be invoked in order for the asynchronous service  to deliver its response.

image

Using the icon in the Mock Editor window, open the WSDL page for the Mock Service. It is the easiest way to get hold of the end point for the MockService. We need this endpoint, to pass it in the request to the ThoughtfulGreeterService.helloToWorld operationas the ReplyTo address:

image

The browser opens at the WSDL page for the Mock Service:

image

Copy the endpoint url (minus ?WSDL) to the clipboard.

Open the Test Request for the helloToWorld operation. Set the endpoint to the endpoint found in the JDeveloper console after deployment. Set a value for the name element in the request message.

Open the tab for Addressing details. Check the checkbox labeled Enable WS-Addressing. Set the ReplyTo property with the endpoint address in the clipboard buffer (copied from the WSDL page for the Mock Service). Check the checkbox labeled Randomly generate MessageId.

image

This basically means that SoapUI will add several WS-Addressing headers to the request it sends to the ThoughtfulGreeterService – including one for the ReplyTo address (the callback endpoint) and the message id to be used in the callback.

Now make the call from SoapUI.

Check in JDeveloper Console:

image

Clearly the JAX-WS Web Service was invoked and the request had headers with a callback address and a message id.

Check in SoapUI in the MockService editor. Here you will find a log line for a incoming request. When you inspect the message exchange results, you will find the response message as well as the RelatesTo header property with the same message Id that was sent in the request message:

image

 

Resources

Download JDeveloper 12c Application: AsynchronousJavaWebServiceJDeveloper12cApplication

Documentation

SoapUI – Testing Asynchronous Services

SoapUI – Working with MockServices

Blog articles:

Create an Asynchronous JAX-WS Web Service and call it from Oracle BPEL 11g – Bob Webster’s Blog

Invoke a single port async service using JAX-WS and WS-Addressing – Gerard Davison

How to call a webservice directly from Java (without webservice library) – Frank Houweling on the AMIS Technology Blog

Building an asynchronous web service with JAX-WS – Edwin Biemond

SOA Suite 11g Asynchronous Testing with soapUI – A-Team blog

Share.

About Author

Lucas Jellema, active in IT (and with Oracle) since 1994. Oracle ACE Director for Fusion Middleware. Consultant, trainer and instructor on diverse areas including Oracle Database (SQL & PLSQL), Service Oriented Architecture, BPM, ADF, Java in various shapes and forms and many other things. Author of the Oracle Press book: Oracle SOA Suite 11g Handbook. Frequent presenter on conferences such as JavaOne, Oracle OpenWorld, ODTUG Kaleidoscope, Devoxx and OBUG. Presenter for Oracle University Celebrity specials.

1 Comment

  1. Nanda Kishore on

    Where can I get the wsdl here. This example requires wsdl to be there. I couldn’t find one which can be used to check

Leave a Reply