Saturday, February 12, 2011

Building an asynchronous web service with JAX-WS

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.

Then the Hello implementation
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

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.

24 comments:

  1. Hey,

    It it worth noting that this service won't be asynchronous as the request will not return until such time as the response has be fired.

    WLS does has a bunch of annotations to support this though.... you need to at least buffer your service:

    http://download.oracle.com/docs/cd/E12840_01/wls/docs103/webserv_adv_rpc/buffered.html#wp266524

    Gerard

    ReplyDelete
  2. Hi Gerard,

    you are right.

    Thanks

    ReplyDelete
  3. Hi Gerard,

    I rechecked my example but I only need to add @WebMethod() and @Oneway() to my methods. Especially oneway is importent else you will get two messages back.

    Buffered does not do much, I checked the queues for messages and consumers/producers but no action.

    your doc only applies to jax-rpc and I checked the jax-ws docs of wls and they dont mention this.

    thanks.

    ReplyDelete
  4. Hi Mr Edwin

    Thank you very much for these tutorials. They helped me to start with SOA suite 11g.

    My problem, I have an asynchronous BPEL process. I can invoke it from java code, but I don't know how to receive the asynchronous callback.

    Please, any idea?

    Regards

    ReplyDelete
  5. Hi,

    did you read the comments of this blogpost. http://biemond.blogspot.com/2009/11/calling-soa-suite-direct-binding.html

    thanks

    ReplyDelete
  6. Thank you

    I will try it and tell you the result

    ReplyDelete
  7. Hi Edwin,

    I really loved this Article. I was looking for Asynchronous WebService demo specially for JAXWS for a long time.
    I got it now. Thanks once again for sharing this.

    Regards
    Jay SenSharma

    ReplyDelete
  8. Thanks Edwin for a fantastic blog !

    Two questions.

    1. Do we have to configure JMS queues before running this sample on WLS ?

    2. If yes, then I presume we have to write our MDB to read from the queue and invoke the service. How does the MDB invoke the deployed service ?

    Thanks so much in advance !

    ReplyDelete
  9. Hi

    you dont need a jms queue for this example.

    but you can use a queue if you process need this, then your jax-ws service put the message on a queue , mdb reads this queue, do your thing and the mdb does the call back.

    thanks

    thanks

    ReplyDelete
  10. Using http as a transport protocol for asynchronous webservice is generally not a good idea as HTTP is a request-reply protocol.
    I would still prefer MQ or JMS

    http://oracled.wordpress.com

    ReplyDelete
  11. Edwin, I deployed the async java service to weblogic server and I want this to be invoked from my Asyc BPEL process. I have also set the wsa properties ie messageId, ReplyTo in the invoke activity properties. But I couldn't receive the response in the following receive activity. ie., the Receive is still waiting with msg "Waiting for "callbackMessage" from "CallbackResp". Asynchronous callback."

    Can you please suggest.

    ReplyDelete
  12. Edwin, Exposing this Java class as web service creates a single portType. To receive callback response from the same service we need to have different port?

    If yes how can be we modify this class to create two diff ports one for request and another for callback.

    ReplyDelete
  13. Hi,

    I need to have two operations with only an input.
    Don't know how you can do that 2 porttypes

    but you can do contract first , make your own wdsl and generate a java interface.

    thanks

    ReplyDelete
  14. Thanks Edwin for reply.

    I had now defined correlation sets in BPEL to go with content based correlation. The java web service when doing the callback its hitting BPEL but im getting fault as "Unable to find operation: unknown".

    How can I tell which operation to perform the callback.

    Thanks,
    Arun

    ReplyDelete
  15. Able to fix the unable to find operation issue. Updated the BPEL wsdl accordingly.

    ReplyDelete
  16. hi Edwin.
    I am new to web service and find this webpage helpful. But while I was looking through the codes I found "HelloImplService", how to develop this page? as I am using Netbeans 7 and apache tomcat7.

    Thanks in advance.

    ReplyDelete
  17. Hi
    When I trying to test your example from SOUP-UI I'm getting "weblogic.wsee.reliability.handshake.HandshakeMsgException: Could not parse create sequence/offer message ...
    Caused by: weblogic.xml.dom.ChildCountException: missing child Endpoint in wsrm:Offer" in WLS outlog. What I'm doing wrong ? Does SOUP-UI have some magic options for RM :) ? I had enabled WS-RM for Request.

    ReplyDelete
    Replies
    1. Hi,

      disable WS-RM , I got that only working with jdeveloper and wls not with soapUI. WS-RM does a lot of handshaking .

      thanks

      Delete
  18. Hi,
    I tried to follow the example, but I'm missing the "show WSDL for Web Service Annotation" function in JDeveloper (right click on class?). Tried in 11.1.1.3 and 11.1.1.5. When I start or test the Web Service, it says that the WSDL is missing. Which version did you use?

    ReplyDelete
    Replies
    1. Hi,

      select the ws icon on the class name in the jdeveloper application window. ( not code window )
      oh strange , did it generate a web.xml with some servlet reference ( or did you do contract first ). I think you can also arrange this from the web service annotation.

      thanks

      Delete
    2. Strange, if I create an data control on the class, the log says "generate WSDL", but in the end, there is none.

      Delete
    3. Hi,

      Asyn ws is a bit strange in a web application, you need to start a thread which can wait for the response else you can better make a sync service.

      thanks

      Delete
  19. can i use sopa ui url to generate stub in jdeveloper by using its webservice wizard.??? My webservice is not up and running anywhere so i want that i can enter some raw data in webservice and have it in response of webservice method

    ReplyDelete
    Replies
    1. Hi,

      To mock a service you can use soapui or use the proxy analyzer of jdeveloper to emulate a service
      http://biemond.blogspot.com/2007/11/http-analyzer-11g-to-test-and-monitor.html

      Or do you mean something else

      thanks

      Delete