Thing which seemed very Thingish inside you is quite different when it gets out into the open and has other people looking at it

Saturday, October 12, 2013

How to call multiple soap operations using call out mediator - WSO2 ESB

In this post I will explain how we can call multiple operations inside the same proxy service using the  call out mediator in WSO2 ESB. For this sample I have used my distributed transaction sample where we need to call multiple operation in the same transaction.

In order to do this you need to have WSO2 ESB, as well as sample web service with multiple operations.  For that I will be using WSO2 DSS distributed transaction data service which I have explained in my previous blog post. Where we will insert customer information, in to multiple data bases in the same transaction.

Sample input 

<customer>
  <id>2</id>
  <name>Smith</name>
</customer>

Step 1 - Creating the proxy service.

To create the proxy, you need to start the ESB server under services -> add -> proxy service -> Custom Proxy service. Give an appropriate name. For this sample I am calling it MyTransactionProxy.


In the in sequence I will be calling several mediators.

  1. Log Mediator - To log the incoming request
  2. Property Mediators - To store the input parameters
  3. Payload Factory Mediator - to arrange the payload for each operation
  4. Call out mediator  - to call each operation of the given service 


Sample In sequence

<inSequence xmlns="http://ws.apache.org/ns/synapse">
   <log level="full">
      <property name="M1" value="***************HITTING Transaction PROXY****************"/>
   </log>
   <property name="OUT_ONLY" value="true"/>
   <property name="id" expression="//id/text()"/>
   <property name="name" expression="//name/text()"/>
   <payloadFactory media-type="xml">
      <format>
         <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:dat="http://ws.wso2.org/dataservice">            
            <soapenv:Header/>            
            <soapenv:Body/>      
         </soapenv:Envelope>
      </format>
   </payloadFactory>
   <callout serviceURL="https://localhost:9445/services/DTPDS/" action="urn:begin_boxcar">
      <source type="envelope"/>
      <target xmlns:s12="http://www.w3.org/2003/05/soap-envelope" xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/" xpath="s11:Body/child::*[fn:position()=1] | s12:Body/child::*[fn:position()=1]"/>
   </callout>
   <payloadFactory media-type="xml">
      <format>
         <p:my_insert xmlns:p="http://ws.wso2.org/dataservice">          
            <xs:id xmlns:xs="http://ws.wso2.org/dataservice">$1</xs:id>          
            <xs:name xmlns:xs="http://ws.wso2.org/dataservice">$2</xs:name>      
         </p:my_insert>
      </format>
      <args>
         <arg expression="get-property('id')" evaluator="xml"/>
         <arg expression="get-property('name')" evaluator="xml"/>
      </args>
   </payloadFactory>
   <callout serviceURL="https://localhost:9445/services/DTPDS/" action="urn:my_insert">
      <source xmlns:s12="http://www.w3.org/2003/05/soap-envelope" xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/" xpath="s11:Body/child::*[fn:position()=1] | s12:Body/child::*[fn:position()=1]"/>
      <target xmlns:s12="http://www.w3.org/2003/05/soap-envelope" xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/" xpath="s11:Body/child::*[fn:position()=1] | s12:Body/child::*[fn:position()=1]"/>
   </callout>
   <payloadFactory media-type="xml">
      <format>
         <p:pos_insert xmlns:p="http://ws.wso2.org/dataservice">          
            <xs:id xmlns:xs="http://ws.wso2.org/dataservice">$1</xs:id>          
            <xs:name xmlns:xs="http://ws.wso2.org/dataservice">$2</xs:name>      
         </p:pos_insert>
      </format>
      <args>
         <arg expression="get-property('id')" evaluator="xml"/>
         <arg expression="get-property('name')" evaluator="xml"/>
      </args>
   </payloadFactory>
   <callout serviceURL="https://localhost:9445/services/DTPDS/" action="urn:pos_insert">
      <source xmlns:s12="http://www.w3.org/2003/05/soap-envelope" xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/" xpath="s11:Body/child::*[fn:position()=1] | s12:Body/child::*[fn:position()=1]"/>
      <target xmlns:s12="http://www.w3.org/2003/05/soap-envelope" xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/" xpath="s11:Body/child::*[fn:position()=1] | s12:Body/child::*[fn:position()=1]"/>
   </callout>
   <payloadFactory media-type="xml">
      <format>
         <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:dat="http://ws.wso2.org/dataservice">          
            <soapenv:Header/>          
            <soapenv:Body/>      
         </soapenv:Envelope>
      </format>
   </payloadFactory>
   <callout serviceURL="https://localhost:9445/services/DTPDS/" action="urn:end_boxcar">
      <source type="envelope"/>
      <target xmlns:s12="http://www.w3.org/2003/05/soap-envelope" xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/" xpath="s11:Body/child::*[fn:position()=1] | s12:Body/child::*[fn:position()=1]"/>
   </callout>
</inSequence>


Here I have created payload factory mediator and a call out mediator to call each operation. In the call our service URL I have given the end point for my service. For example I have an operation called my_insert. So I created a payload factory mediator and defined the payload format inline as shown below (parameters for the operation is given as $1,$2 which are later replaced by the id, and the name properties.

<payloadFactory xmlns="http://ws.apache.org/ns/synapse" media-type="xml">
   <format>
      <p:my_insert xmlns:p="http://ws.wso2.org/dataservice">                                                
         <xs:id xmlns:xs="http://ws.wso2.org/dataservice">$1</xs:id>                                                
         <xs:name xmlns:xs="http://ws.wso2.org/dataservice">$2</xs:name>                                  
      </p:my_insert>
   </format>
   <args>
      <arg expression="get-property('id')" evaluator="xml"/>
      <arg expression="get-property('name')" evaluator="xml"/>
   </args>
</payloadFactory>

Likewise, I have called each operation with the same format.

In the out sequence I have used an empty send mediator which will send back the response to the same service.

Complete proxy xml is attached below.

<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="TransactionProxy"
       transports="http"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target>
      <inSequence>
         <log level="full">
            <property name="M1"
                      value="*************HITTING Transaction PROXY*************"/>
         </log>
         <property name="OUT_ONLY" value="true"/>
         <property name="id" expression="//id/text()"/>
         <property name="name" expression="//name/text()"/>
         <payloadFactory media-type="xml">
            <format>
               <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                                 xmlns:dat="http://ws.wso2.org/dataservice">
                  <soapenv:Header/>
                  <soapenv:Body/>
               </soapenv:Envelope>
            </format>
         </payloadFactory>
         <callout serviceURL="https://localhost:9445/services/DTPDS/"
                  action="urn:begin_boxcar">
            <source type="envelope"/>
            <target xmlns:s12="http://www.w3.org/2003/05/soap-envelope"
                    xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/"
                    xpath="s11:Body/child::*[fn:position()=1] | s12:Body/child::*[fn:position()=1]"/>
         </callout>
         <payloadFactory media-type="xml">
            <format>
               <p:my_insert xmlns:p="http://ws.wso2.org/dataservice">
                  <xs:id xmlns:xs="http://ws.wso2.org/dataservice">$1</xs:id>
                  <xs:name xmlns:xs="http://ws.wso2.org/dataservice">$2</xs:name>
               </p:my_insert>
            </format>
            <args>
               <arg expression="get-property('id')" evaluator="xml"/>
               <arg expression="get-property('name')" evaluator="xml"/>
            </args>
         </payloadFactory>
         <callout serviceURL="https://localhost:9445/services/DTPDS/"
                  action="urn:my_insert">
            <source xmlns:s12="http://www.w3.org/2003/05/soap-envelope"
                    xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/"
                    xpath="s11:Body/child::*[fn:position()=1] | s12:Body/child::*[fn:position()=1]"/>
            <target xmlns:s12="http://www.w3.org/2003/05/soap-envelope"
                    xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/"
                    xpath="s11:Body/child::*[fn:position()=1] | s12:Body/child::*[fn:position()=1]"/>
         </callout>
         <payloadFactory media-type="xml">
            <format>
               <p:pos_insert xmlns:p="http://ws.wso2.org/dataservice">
                  <xs:id xmlns:xs="http://ws.wso2.org/dataservice">$1</xs:id>
                  <xs:name xmlns:xs="http://ws.wso2.org/dataservice">$2</xs:name>
               </p:pos_insert>
            </format>
            <args>
               <arg expression="get-property('id')" evaluator="xml"/>
               <arg expression="get-property('name')" evaluator="xml"/>
            </args>
         </payloadFactory>
         <callout serviceURL="https://localhost:9445/services/DTPDS/"
                  action="urn:pos_insert">
            <source xmlns:s12="http://www.w3.org/2003/05/soap-envelope"
                    xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/"
                    xpath="s11:Body/child::*[fn:position()=1] | s12:Body/child::*[fn:position()=1]"/>
            <target xmlns:s12="http://www.w3.org/2003/05/soap-envelope"
                    xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/"
                    xpath="s11:Body/child::*[fn:position()=1] | s12:Body/child::*[fn:position()=1]"/>
         </callout>
         <payloadFactory media-type="xml">
            <format>
               <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                                 xmlns:dat="http://ws.wso2.org/dataservice">
                  <soapenv:Header/>
                  <soapenv:Body/>
               </soapenv:Envelope>
            </format>
         </payloadFactory>
         <callout serviceURL="https://localhost:9445/services/DTPDS/"
                  action="urn:end_boxcar">
            <source type="envelope"/>
            <target xmlns:s12="http://www.w3.org/2003/05/soap-envelope"
                    xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/"
                    xpath="s11:Body/child::*[fn:position()=1] | s12:Body/child::*[fn:position()=1]"/>
         </callout>
      </inSequence>
      <outSequence>
         <send/>
      </outSequence>
   </target>
   <description/>
</proxy>
                               

Calling the proxy service

Here I am calling the proxy service using the curl tool.

curl -v --request POST -d '2Smith' -H Content-Type:"text/xml" http://amani-ThinkPad-T520:8280/services/MyTransactionProxy




2 comments:

  1. HI poohdedoo ,
    First Thank you for posting this.
    i am working on the above exampe, i am getting request but i am not getting any response from this.

    Could you please explain me why i am not getting response.
    Thanks in Advance
    Anil

    ReplyDelete
  2. Is this post tested or not .I am doing same but its not working box_car working in dss tryit tool only not from wso2esb
    please refer this
    http://stackoverflow.com/questions/21135505/wso2dss-box-carring-not-working-in-wso2esb4-8-0
    http://stackoverflow.com/questions/21228546/wso2esb-transaction-for-local-database

    ReplyDelete