Building an asynchronous web service with JAX-WS

Bookmark and Share
Building an asynchronous web service can be complex especially when you are used to synchronous Web services where you can wait for the response in your favorite tool. To get the response of an asynchronous WS you need to do the following in SOAPUI,  create a MockService based on the WSDL of the Web Service and use this Mock Service URL in the ReplyTo Addressing property of your WS Request. Off course you need to enable Addressing where you also need  add a unique MessageId which can be used as a reference for the Response.



To start this blogpost, I begin with making a simple Hello interface. sayHello is the request operation and will use callbackMessage as response.

package nl.whitehorses.ws.interfaces;

public interface Hello {
public void sayHello(String msg );


public void callbackMessage(String msg );
}


Then the Hello implementation

package nl.whitehorses.ws;

import javax.jws.WebService;
import javax.xml.ws.soap.Addressing;

import nl.whitehorses.ws.interfaces.Hello;

@WebService
@Addressing
public class HelloImpl implements Hello {

@WebMethod()
@Oneway()
public void sayHello(String name) {
}

@WebMethod()
@Oneway()
public void callbackMessage(String msg) {
}
}
The next step is to retrieve the WSDL of this JAX-WS Service, you can start the HelloImpl Web Service by Running this class in JDeveloper and retrieve the WSDL or select the HelloImpl class and press show WSDL for Web Service Annotation ( also JDeveloper ).



This WSDL will be used to generate a Web Service Client project. I need these client classes to do a WS callbackMessage call out. You can do this in a separate project ( check the dependencies ) or in the same WS project.



Change the sayHello implementation, where I try to retrieve the replyTo address and the MessageId of WS-Adresssing. Make a new callbackMessage WS Request and set the reply URL and the relatesTo attribute

package nl.whitehorses.ws;

import com.sun.xml.ws.api.SOAPVersion;
import com.sun.xml.ws.api.addressing.AddressingVersion;
import com.sun.xml.ws.api.addressing.WSEndpointReference;
import com.sun.xml.ws.api.message.HeaderList;
import com.sun.xml.ws.api.message.Headers;
import com.sun.xml.ws.developer.JAXWSProperties;
import com.sun.xml.ws.developer.WSBindingProvider;

import javax.annotation.Resource;

import javax.jws.WebService;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.soap.Addressing;

import nl.whitehors.ws.client.HelloImplService;
import nl.whitehorses.ws.interfaces.Hello;

@WebService
@Addressing
public class HelloImpl implements Hello {

@Resource
WebServiceContext context;

@WebMethod()
@Oneway()
public void sayHello(String name) {

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);

HelloImplService srv = new HelloImplService();
nl.whitehors.ws.client.HelloImpl portType = srv.getHelloImplPort();
WSBindingProvider bp = (WSBindingProvider)portType;

bp.setAddress( reference.getAddress());
bp.setOutboundHeaders(Headers.create(AddressingVersion.W3C.relatesToTag,
messageId));

portType.callbackMessage("hello you [" +  reference.getAddress() + "]");
}

@WebMethod()
@Oneway()
public void callbackMessage(String msg) {
}
}


Restart your JAX-WS Service and test this service in SOAPUI or use the JDeveloper HTTP Analyzer. Make sure, you enable WS-Adressing and set a reply address, for example the SOAPUI Mock Service address



This is the callback request which is send to the SOAPUI Mock Service. It got the RelatesTo Addressing attribute. This is captured in the HTTP Analyzer of JDeveloper.



 And the same callback but then in the SOAPUI Mock Service request window

That's all.

{ 0 comments... Views All / Send Comment! }

Post a Comment