Monday, August 1, 2016

How to use Clone Mediator in WSO2 ESB

Clone mediator is used to send same massage to multiple endpoints. It basically clone same message to multiple message based on our requirement and send it to multiple endpoints. We can aggregate the response which we get from the multiple endpoints and show as one response.

Requirement:

Suppose there is a requirement where we have to get the entire IT employee details who all works overseas. We have different databases and different places and each database has employee records. We have only one input parameter which is department, all I need is IT employee details.

Solution:

I have created 3 data services, first provides Indian employee detail, second provide USA employee details and 3rd provides New Zealand employee details. I have created same format DSS with same namespace with one input parameter and 4 output parameter in one employee list and response can have multiple employee list.


DSS:
<data name="EmployeeDetailsNZ" enableBatchRequests="false" enableBoxcarring="false" serviceStatus="active">
   <description>This provides Employee details</description>
   <config id="EMPDS">
      <property name="org.wso2.ws.dataservice.driver">oracle.jdbc.driver.OracleDriver</property>
      <property name="org.wso2.ws.dataservice.protocol">jdbc:oracle:thin:SYSTEM/SYSTEM@localhost:1521/xe</property>
      <property name="org.wso2.ws.dataservice.user">SYSTEM</property>
      <property name="org.wso2.ws.dataservice.password">SYSTEM</property>
      <property name="org.wso2.ws.dataservice.minpoolsize"></property>
      <property name="org.wso2.ws.dataservice.maxpoolsize"></property>
      <property name="org.wso2.ws.dataservice.validation_query"></property>
   </config>
   <query id="EmpDetailsQuery" useConfig="EMPDS">
      <sql>select * from EMP_DETAILS_NZ where DEPARTMENT_V=?</sql>
      <result element="EmployeeDetails" rowName="EmployeeData" defaultNamespace="http://shriwithjava.blogspot.co.nz/">
         <element name="EmployeeId" column="EMP_ID_N" xsdType="xs:string" />
   <element name="EmployeeName" column="EMP_NAME_V" xsdType="xs:string" />
   <element name="EmployeeAddress" column="EMP_ADD_V" xsdType="xs:string" />
   <element name="Department" column="DEPARTMENT_V" xsdType="xs:string" />
   </result>
      <param name="Department" paramType="SCALAR" sqlType="STRING" type="IN" />
   
   </query>
   <operation name="getEmployeeDetails">
      <description></description>
      <call-query href="EmpDetailsQuery">
         <with-param name="Department" query-param="Department" />
   
      </call-query>
   </operation>
</data>

DSS request and response format:

Request:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:shr="http://shriwithjava.blogspot.co.nz/">
   <soapenv:Header/>
   <soapenv:Body>
      <shr:getEmployeeDetails>
         <shr:Department>IT</shr:Department>
      </shr:getEmployeeDetails>
   </soapenv:Body>
</soapenv:Envelope>

Response:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <EmployeeDetails xmlns="http://shriwithjava.blogspot.co.nz/">
         <EmployeeData>
            <EmployeeId>201</EmployeeId>
            <EmployeeName>Shri</EmployeeName>
            <EmployeeAddress>Auckland</EmployeeAddress>
            <Department>IT</Department>
         </EmployeeData>
         <EmployeeData>
            <EmployeeId>202</EmployeeId>
            <EmployeeName>Bhajan</EmployeeName>
            <EmployeeAddress>Wellington</EmployeeAddress>
            <Department>IT</Department>
         </EmployeeData>
      </EmployeeDetails>
   </soapenv:Body>
</soapenv:Envelope>



ESB Changes:

I have created a service which will get all the details of the overseas employee for different department. I will call all the endpoints (Indian, USA and New Zealand employee details) and aggregate the response into one. I have to use same input and that will be cloned for each endpoint from the clone mediator.

Synapse Code:

<definitions>
<proxy name="OverseasEmpDetailsProxy" transports="http" startOnLoad="true" trace="disable" statistics="enable">
   <target inSequence="OverseasEmpDetails_IN" outSequence="OverseasEmpDetails_OUT" faultSequence="CommonFaultHandler"/>
   <publishWSDL key="OverseasEmpDetails_wsdl"/>
</proxy>
<localEntry key="OverseasEmpDetails_wsdl" src="file:repository/conf/employee/OverseaseEmployee.wsdl"/>
 
<sequence name="OverseasEmpDetails_IN">
 <clone>
  <target>
   <endpoint key="NZEmployeeDetails_EPR"/>
  </target>
  <target>
   <endpoint key="INDEmployeeDetails_EPR"/>
  </target>
  <target>
   <endpoint key="USAEmployeeDetails_EPR"/>
  </target>
 </clone>
</sequence>
 
<sequence name="OverseasEmpDetails_OUT">
   <aggregate>
  <completeCondition>
   <messageCount min="-1" max="-1"/>
  </completeCondition>
  <onComplete xmlns:shr="http://shriwithjava.blogspot.co.nz/" expression="//shr:EmployeeDetails/shr:EmployeeData">
   <send/>
  </onComplete>
 </aggregate>
</sequence>
 
 <endpoint name="NZEmployeeDetails_EPR">
 <address uri="http://localhost:9763/services/EmployeeDetailsNZ">
  <timeout>
   <duration>10000</duration>
   <responseAction>fault</responseAction>
  </timeout>
  <suspendOnFailure>
   <errorCodes>101500,101501,101506,101507,101508</errorCodes>
   <progressionFactor>0.0</progressionFactor>
  </suspendOnFailure>
  <markForSuspension>
   <errorCodes>101504,101505</errorCodes>
  </markForSuspension>
 </address>
</endpoint>
 <endpoint name="INDEmployeeDetails_EPR">
 <address uri="http://localhost:9763/services/EmployeeDetailsIndia">
  <timeout>
   <duration>10000</duration>
   <responseAction>fault</responseAction>
  </timeout>
  <suspendOnFailure>
   <errorCodes>101500,101501,101506,101507,101508</errorCodes>
   <progressionFactor>0.0</progressionFactor>
  </suspendOnFailure>
  <markForSuspension>
   <errorCodes>101504,101505</errorCodes>
  </markForSuspension>
 </address>
</endpoint>
 <endpoint name="USAEmployeeDetails_EPR">
 <address uri="http://localhost:9763/services/EmployeeDetailsUSA">
  <timeout>
   <duration>10000</duration>
   <responseAction>fault</responseAction>
  </timeout>
  <suspendOnFailure>
   <errorCodes>101500,101501,101506,101507,101508</errorCodes>
   <progressionFactor>0.0</progressionFactor>
  </suspendOnFailure>
  <markForSuspension>
   <errorCodes>101504,101505</errorCodes>
  </markForSuspension>
 </address>
</endpoint>
 
<sequence name="CommonFaultHandler">
 <log level="custom">
  <property name="MESSAGE" value="Executing default &quot;fault&quot; sequence"/>
  <property name="ERROR_CODE" expression="get-property('ERROR_CODE')"/>
  <property name="ERROR_MESSAGE" expression="get-property('ERROR_MESSAGE')"/>
 </log>
 <header name="To" action="remove"/>
 <drop/>
</sequence>
 
 
</definitions>


Restart the ESB and load the WSDL in SOAP UI results will look like:

Request:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:shr="http://shriwithjava.blogspot.co.nz/">
   <soapenv:Header/>
   <soapenv:Body>
      <shr:getEmployeeDetails>
         <shr:Department>IT</shr:Department>
      </shr:getEmployeeDetails>
   </soapenv:Body>
</soapenv:Envelope>


Response:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <EmployeeDetails xmlns="http://shriwithjava.blogspot.co.nz/">
         <EmployeeData>
            <EmployeeId>201</EmployeeId>
            <EmployeeName>Shri</EmployeeName>
            <EmployeeAddress>Auckland</EmployeeAddress>
            <Department>IT</Department>
         </EmployeeData>
         <EmployeeData>
            <EmployeeId>202</EmployeeId>
            <EmployeeName>Bhajan</EmployeeName>
            <EmployeeAddress>Wellington</EmployeeAddress>
            <Department>IT</Department>
         </EmployeeData>
         <EmployeeData>
            <EmployeeId>004</EmployeeId>
            <EmployeeName>Viru</EmployeeName>
            <EmployeeAddress>Kanpur</EmployeeAddress>
            <Department>IT</Department>
         </EmployeeData>
         <EmployeeData>
            <EmployeeId>111</EmployeeId>
            <EmployeeName>Tahseen</EmployeeName>
            <EmployeeAddress>New York</EmployeeAddress>
            <Department>IT</Department>
         </EmployeeData>
         <EmployeeData>
            <EmployeeId>113</EmployeeId>
            <EmployeeName>JD</EmployeeName>
            <EmployeeAddress>Washington</EmployeeAddress>
            <Department>IT</Department>
         </EmployeeData>
      </EmployeeDetails>
   </soapenv:Body>
</soapenv:Envelope>

You can see the response from different service have been merged into one and we only sent a single request with a department parameter.