Tuesday, September 7, 2010

SOAP over JMS with Oracle Service Bus 11g

In a previous blog I already showed you how you can do SOAP over JMS with a JAX-RPC Web Service. In this blogpost I will use OSB 11g ( Also works in 10.3 ). The OSB Proxy Services is also based on the JAX-RPC framework, so it works almost the same as a normal Java JAX-RPC Service.

You need to start with a new Proxy Service based on a WSDL

Choose for JMS. OSB will generates a default Endpoint Uri. You need to remember the QueueName of this Endpoint uri, you will use this in your Java proxy client.
OSB automatically creates a new Queue with this name when it does not already exists.

In the JMS Transport tab you need to select Is Response Required and JMSMessageID as Response Pattern.

In the Message Flow Tab I will use a simple File Busines Service and in the Response Action an Assign to set the WSDL response in the body variable.
In the Response Action you need add a Transport Header.

In the Transport Header you need to add the _wls_mimehdrContent_Type Header with as value 'text/xml; charset=utf-8' and use Inbound Response as Direction.
If you don't set this Transport Header you can get a content type null error on the JAX-RPC Client side
Deploy this project to the OSB Server.

Now you can download the WSDL of the Proxy Service in the SB Console, you need this to generate the JAX-RPC Client.

extract this jar and optional you can change the Endpoint to this Uri jms://servername:7001?URI=JMSProxyServiceRequest . Change the servername, the port number and change the Queue name.  That's enough to find the Queue.

The last step is to generate a Java Web Service Proxy client. Please read this blogpost how to generate a client.
This is the ANT Target I used to generate the client classes based on the WSDL
<target name="clientOSB">
  <clientgen wsdl="file:/c:/temp/jms/HelloworldNormal.wsdl"
             destdir="src" 
             packagename="nl.whitehorses.clientosb.jms"
             type="JAXRPC"/>
  <javac srcdir="src" 
         destdir="classes"
         includes="nl/whitehorses/clientosb/jms/**/*.java"/>
 </target>

And the java test client. If you change the WSDL Endpoint you don't need to set JmsTransportInfo
package nl.whitehorses.clientosb.jms;

import java.net.URISyntaxException;

import java.rmi.RemoteException;

import javax.xml.rpc.ServiceException;
import javax.xml.rpc.Stub;

import weblogic.wsee.connection.transport.jms.JmsTransportInfo;

public class TestService {

    public TestService() {
    }


    public static void main(String[] args) {

        try {
            HelloWorldServiceSoapHttpPortBindingQSService hello = new HelloWorldServiceSoapHttpPortBindingQSService_Impl();
            HelloWorldService port = hello.getHelloWorldServiceSoapHttpPortBindingQSPort();

            String uri = "jms://laptopedwin:7001?URI=JMSProxyServiceRequest";  
            JmsTransportInfo ti =  new JmsTransportInfo(uri);  
            ((Stub)port)._setProperty("weblogic.wsee.connection.transportinfo", ti);  
           
            System.out.println(port.sayHello());

        } catch (ServiceException e) {
            e.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }

}
Here you can download the OSB workspace.

22 comments:

  1. Hello, I have a question on another subject, could you help?

    I have a parent table that has a relationship with a child table, the child table has a composite key, the following image explains better relations

    http://i26.servimg.com/u/f26/12/26/78/42/casoco10.png

    The problem is with the parent table (tabla4), how I can make the view object for use in a form? if I put two selectOneChoice for the ID of the child table (tabla3) does not guarantee the consistency or completeness

    How do I create an attribute or component that contains both ID?

    ReplyDelete
  2. Hi,

    you should do this with a adf bc viewlink between the view table3 and table 4.

    Make a form of table of table3 and table4 as detail table. When you add a new record on table 4 then the fk is automatically filled and just provide the new pk.

    Hope this helps

    ReplyDelete
  3. Hello!

    This post was very useful for getting up and running with Soap Over JMS in the OSB environment. Thank you!

    One question I have is the use of JAX-RPC to support Soap Over JMS. Can you see Oracle improving this to cover the JAX-WS standard?

    And are we forced to generate the client using the WL tool? What about other tools such as CXF or Axis2?

    Anyway, once again thanks for your efforts in this area. They make a huge difference :)


    Mark.

    ReplyDelete
  4. Hi,

    dont think Oracle will change this, jax-ws client only supports HTTP. Dont know what the jax-ws standard says about this.

    thanks

    ReplyDelete
  5. Hello, Edwin. Thank you so much for this post, it has been very useful to me. But I have a question: is there a way to expose the WSDL in this setup without having to get it from the sb console?
    Thanks again, Humberto

    ReplyDelete
  6. Hi

    Don't think so, you need to use the sbconsole for the wsdl.

    thanks

    ReplyDelete
  7. First of all congratulations for this great post.

    I had one proxy service using http as protocol, but due the large size of the request in my case, I decided to change the protocol from http to jms and make it assync.

    I was using SOAPUI to test the http service, but since it is quite complicated to import the WSDL using JMS on this tool, I tried to implement a java project in Netbeans and created a WS client using JAX-WS as you did.

    Unfortunately when I run the method I got this error:

    Exception in thread "main" javax.xml.ws.WebServiceException: Unsupported endpoint address: jms://WN7-6J6VJN1.poagdc.amer.dell.com:7001/weblogic.jms.XAConnectionFactory/JMSProxyServiceRequest
    at com.sun.xml.internal.ws.api.pipe.TransportTubeFactory.create(TransportTubeFactory.java:133)
    at com.sun.xml.internal.ws.transport.DeferredTransportPipe.processRequest(DeferredTransportPipe.java:101)
    at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Fiber.java:587)
    at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Fiber.java:546)
    at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Fiber.java:531)
    at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Fiber.java:428)
    at com.sun.xml.internal.ws.client.Stub.process(Stub.java:211)
    at com.sun.xml.internal.ws.client.sei.SEIStub.doProcess(SEIStub.java:124)
    at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:98)
    at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78)
    at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:107)
    at $Proxy29.bookInfoleaseContract(Unknown Source)
    at JMSBookingContractMain.bookInfoleaseContract(JMSBookingContractMain.java:396)
    at JMSBookingContractMain.main(JMSBookingContractMain.java:384)


    Did I miss something ?

    cheers,
    Davinod

    ReplyDelete
  8. Hi,

    Yes jax-ws won't support it, you need to use jax-rpc. jax-ws only supports http.

    thanks

    ReplyDelete
  9. Hi
    Can we invoke any xml-rpc service from OSB? I really dont understand difference between xml-rpc service and a REST service.
    -Sam

    ReplyDelete
  10. Hi,

    basically, An XML-RPC message is an HTTP-POST request. The body of the request is in XML. A procedure executes on the server and the value it returns is also formatted in XML

    Rest basically means that each unique URL is a representation of some object. You can get the contents of that object using an HTTP GET, to delete it, you then might use a POST, PUT, or DELETE to modify the object. REST is more about CRUD operations against a resource. And it can also return JSON

    Hope this helps

    ReplyDelete
  11. Hi

    Thanks for the clarification.
    So that means from OSB we can easily call a xml-rpc based service since it requires HTTP-POST request only? From OSB I just need to POST an xml body with 'methodName' as the actual procedure name and 'params' to pass parameters.

    Let me know if my understanding is correct.

    -Sameer

    ReplyDelete
  12. Yep ,

    you are right ,before you do it , use netmon or something else and monitor the http traffic so you know for sure.

    thanks

    ReplyDelete
  13. Hi Edwin,good article,I have a question i configured jms connetion factory and queue in admin console,i create a business service with jms uri like http://host:port/connectionfactory/queuename.My environment is like one admin server for soa and osb server.when i test the business service i got the invokation error due to connection factory and queue.The connection factrory is targetting the soa jms server,Plz help me,Thanks in advance.

    ReplyDelete
  14. Hi,

    Can you check if you target the cf to the managed servers and else use the internal cf . Check your sub deployments , don't use default targeting

    You can test it with qbrowser , see if you can add a message to the queue.

    Thanks

    ReplyDelete
  15. Hi Edwin thanks for reply,Actually i create a new jms server which targets the osb server with file store and create a jmsmodule.Then i create connection factory and queue.Then in Eclipse i create new business-service in protocal i select jms and url i give it like jms://host:port/cf/queue.but i'm getting the error as The invocation resulted in an error: [JMSPool:169803]JNDI lookup of the JMS connection factory demoCF failed: javax.naming.NameNotFoundException: Unable to resolve 'demoCF'. Resolved '' [Root exception is javax.naming.NameNotFoundException: Unable to resolve 'demoCF'. Resolved '']; remaining name 'demoCF'.Please help it's very urgent for me.Presently I'm working on 11.1.1.5.Thanks again.

    ReplyDelete
  16. Hi,

    you use jms://host:port/cf/queue , so this will lookup the cf on this "host" server . you need to target the CF on this server and not on the jms server. cf is always a connection to a wls server.

    thanks

    ReplyDelete
  17. Hi Edwin,Thx for reply I got it.
    I have another issue regarding the dynamic X-Query.
    I have a requirement like three different requests(schemas) all are converted in to standard format(schema).For this scenario I use dyamic X-query transformation.For Example RequestA,RequestB and RequesrC what ever request it should be converted into one standard format say Response.For this I create three X-Query transformations,and proxy service.If i get the request from RequestA related XQuery will execute (RequstA to Response transformation).
    RequestA------Response
    RequestB------Response
    RequestC------Response
    Actually my idea is based on requset schema name (like RequestA) it will convert,for this scenario how can I set condition in dynamicXquery.

    Once again Thanks for your reply

    ReplyDelete
  18. Hi,

    you can read the soap header, a http property or some element and make an if case for a ,b and in the message flow.

    thanks

    ReplyDelete
  19. Hi Edwin,I have query regarding the x query.I have a stored procedure,how can i retrive the details by using execute-sql function or other function,can u plz explian with one example.

    ReplyDelete
  20. Hi Edwin,

    You said that JAX-WS doesnt support SOAP/JMS but I have found one IBM article saying it does
    http://www.ibm.com/developerworks/websphere/library/tutorials/0903_adams/index.html

    have you tried this in IBM WAS?

    Thanks,
    Deepak.

    ReplyDelete
  21. Hi,

    For execute custom sql inside xquery you can use this fn-bea:execute-sql( $datasource as xs:string, $rowElemName as xs:QName, $sql as xs:string, $param1, ..., $paramk) as element()*


    fn-bea:execute-sql( 'jdbc.hr', xs:QName('hashvalue'), 'select TO_CHAR(ORA_HASH(?)) as value from dual',xs:string('ABC') ) as element()*


    thanks

    ReplyDelete
  22. Hi,

    I see that IBM added this to its own version jax-ws. In Version 7.0, however, the SOAP over JMS capabilities have been expanded to include JAX-WS Web services and clients.

    and you need to have this IBM WebSphere Application Server V7.0 and IBM Rational Application Developer V7.5 installed. And probably you need a license.

    thanks

    this is not standard and probably

    ReplyDelete