Pages

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.

37 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,

    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
    Replies
    1. You are righ regarding the anotation..but great example...almost all the the job is done..congratulation and thanks!

      Delete
  3. 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
  4. Hi,

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

    thanks

    ReplyDelete
  5. Thank you

    I will try it and tell you the result

    ReplyDelete
  6. 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
  7. 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
  8. 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
  9. 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
  10. 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
  11. 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
  12. 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
  13. 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
  14. Able to fix the unable to find operation issue. Updated the BPEL wsdl accordingly.

    ReplyDelete
  15. 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
  16. 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
  17. 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
  18. 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
  19. nice one edwin...

    edwin.. i need one help.. i have two tables in db one is header and one is line table and have two file locations,in one of the location a header table resides and in one line table resides i need to read them and insert in to the tables one after the other.. first header and then lines if lines fails it shud rollback.

    thanks
    saileshan

    ReplyDelete
  20. Hi,

    Use bpel, read the header file and read the line file and loop away and do inserts. Or maybe you can use OSB which read the first file and do a service call out the read the other.

    hope this helps

    ReplyDelete
  21. Hi Edwin,
    I can't find code listing for HelloImplService.java. Would it be possible for you to list that as well here?


    Thank you.

    ReplyDelete
  22. My bad. I missed the client generation piece when I wrote that comment. Thank you.

    ReplyDelete
  23. Hi Edwin

    Thanks for the nice post.
    I need some help on developing asynchronous JAX-WS web services using JMS transport(not the regular HTTP)Can we implement MDB as the JMS endpoint? If you could post some code snippets it will be really helpful.

    Thanks in Advance

    ReplyDelete
    Replies
    1. Hi,

      do you mean this. Soap over JMS
      for a MDB you should use a Queue.

      thanks

      Delete
  24. Hi Edwin,

    I have a requirement as below :

    I am working on Jdev 1.5 version and BPEL 2.0 specification. I have an if-else condition in my BPEL. In the if condition I have a while loop with 2 correlation sets, Correlation_1 and Correlation_2. Now in the else condition, I have again created 2 more correlation sets Correlation_3 and Correlation_4. The Property Aliases of these correlation sets, Correlation_1 and Correlation_3 are same, but I have created them separately. Same is the case with Correlation_2 and Correlation_4. Now when I use the correlation set only in the if loop it works fine, but when I use in both the if and else condition, the correlation does not work.

    I have even tried creating a scope for the else condition, which is not in any while loop, but that scope is not visible.

    Can you please suggest something for this?

    ReplyDelete
  25. A good article, thank you. I discussed this article in:
    http://soa-java.blogspot.nl/2012/01/asynchronous-web-service-using-java-jax.html

    ReplyDelete
  26. Hi Edwin,

    Do you have the complete project codes for this in JDeveloper? I would like to really play around with your codes and see actually how you did it. Forgive I'm still new with the webservices and I really need this because I will be developing Client that will having a callback call to the Consumer (webservices).

    Regards,
    Godric

    ReplyDelete
    Replies
    1. Hi,

      can you try this
      https://github.com/biemond/jdev11g_examples/tree/master/AsyncJAX-WS

      thanks

      Delete
  27. This comment has been removed by the author.

    ReplyDelete
  28. Hi Edwin,

    I got your source code (silly of me).
    I was wondering when the HelloImplPortClient class calls the web service:
    helloImpl.sayHello("Edwin");

    where is the message out from:
    portType.callbackMessage("hello you [" + reference.getAddress() + "]");

    will be seen?


    since this is a callback mechanism, how can the client will be able to receive the message sent from the webservice provider?

    I hope my questions does make sense to you...

    Thanks,
    Godric

    ReplyDelete