Monday, November 16, 2015

How to use Iterator Mediate in WSO2 ESB

Iterator mediator is used when a message needs to be split into multiple messages by finding the XPATH expression. A new message is created in each matching elements.

Test Case:

We have a Manager Management portal in which we have to keep records like how many departments are taken care or come in one manager. For example one manager can handle more than 1 or 2 department like IT and CS department.

We have created a request in which we can submit the manager records with his owned departments.

Use of Iterator in this test case:


When we are submitting the department records, department may be more than one so we will use Iterator to create new messages everything for each department and save it into our database.

Database:


We have created 3 tables which contain Department mapping, department details and manager details.

  • Department
  • department_details
  • manager_detail

Now we have to create a stored procedure which will be called from the DSS to store the manager details with their department.

Stored Procedure:

-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$

CREATE DEFINER=`root`@`localhost` PROCEDURE `MANAGE_MANAGER_DETAIL`(
IN MANAGER_ID VARCHAR(50),
IN MANAGER_NAME VARCHAR(50),
IN ADDRESS VARCHAR(50),
IN DEPARTMENT_NAME VARCHAR(50),
IN NO_OF_PEOPLE VARCHAR(50),
IN OFFICE_LOCATION VARCHAR(50) ,
OUT RESULT_CODE VARCHAR(10),
OUT RESULT_DESC VARCHAR(50)
)
BEGIN
declare DEPARTMENT_ID INT;

SELECT DEPARTMENT_ID_N INTO DEPARTMENT_ID FROM DEPARTMENT WHERE DEPARTMENT_NAME_V=DEPARTMENT_NAME;

IF DEPARTMENT_ID IS NOT NULL THEN
INSERT INTO MANAGER_DETAIL VALUES (MANAGER_ID, MANAGER_NAME, ADDRESS, DEPARTMENT_ID);
INSERT INTO DEPARTMENT_DETAILS VALUES (DEPARTMENT_NAME, NO_OF_PEOPLE, OFFICE_LOCATION);
SET RESULT_CODE = '0';
SET RESULT_DESC='SUCCESS';
elseif DEPARTMENT_ID is null then
SET RESULT_CODE = '1';
SET RESULT_DESC='FAILED';
rollback;
END if;
commit;
END

Create DSS (ManageManagerDetailsService.dbs):

<data name="ManageManagerDetailsService">
   <description>This service manage the managers details</description>
    <config id="DataSourceEmp">     
      <property name="org.wso2.ws.dataservice.driver">com.mysql.jdbc.Driver</property>     
      <property name="org.wso2.ws.dataservice.protocol">jdbc:mysql://localhost:3308/emp</property>     
      <property name="org.wso2.ws.dataservice.user">root</property>     
      <property name="org.wso2.ws.dataservice.password">root</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="ManageManagerDetailsQuery" useConfig="DataSourceEmp">
      <sql>call MANAGE_MANAGER_DETAIL(?,?,?,?,?,?,?,?)</sql>
      <result defaultNamespace="http://shriwithjava.blogspot.co.nz/managemanagerdetails" element="ManageManagerDetailsResponse" rowName="">
         <element column="RESULT_CODE" name="ResultCode" xsdType="xs:string"/>
         <element column="RESULT_DESC" name="ResultDescription" xsdType="xs:string"/>
      </result>
      <param name="MANAGER_ID" ordinal="1" paramType="SCALAR" sqlType="STRING" type="IN"/>
      <param name="MANAGER_NAME" ordinal="2" paramType="SCALAR" sqlType="STRING" type="IN"/>
      <param name="ADDRESS" ordinal="3" paramType="SCALAR" sqlType="STRING" type="IN"/>
      <param name="DEPARTMENT_NAME" ordinal="4" paramType="SCALAR" sqlType="STRING" type="IN"/>
      <param name="NO_OF_PEOPLE" ordinal="5" paramType="SCALAR" sqlType="STRING" type="IN"/>
                                    <param name="OFFICE_LOCATION" ordinal="6" paramType="SCALAR" sqlType="STRING" type="IN"/>
      <param name="RESULT_CODE" ordinal="7" paramType="SCALAR" sqlType="STRING" type="OUT"/>
      <param name="RESULT_DESC" ordinal="8" paramType="SCALAR" sqlType="STRING" type="OUT"/>
   </query>
   <operation name="ManageManagerDetails">
      <description>This service manage the managers details</description>
      <call-query href="ManageManagerDetailsQuery">
         <with-param name="MANAGER_ID" query-param="ManagerId"/>
         <with-param name="MANAGER_NAME" query-param="ManagerName"/>
         <with-param name="ADDRESS" query-param="Address"/>
         <with-param name="DEPARTMENT_NAME" query-param="DepartmentName"/>
         <with-param name="NO_OF_PEOPLE" query-param="NoOfPeople"/>
         <with-param name="OFFICE_LOCATION" query-param="OfficeLocation"/>
      </call-query>
   </operation>
</data>


Create WSDL:

Now we have to create a WSDL in which multiple departments can be accepted for one employee id.

Request XML:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:man="http://shriwithjava.blogspot.co.nz/managerdetails/">
   <soapenv:Header/>
   <soapenv:Body>
      <man:ManagerDetailsRequest>
         <man:Id>?</man:Id>
         <man:Name>?</man:Name>
         <man:Address>?</man:Address>
         <man:Departments>
            <!--1 or more repetitions:-->
            <man:DepartmentDetails>
               <man:DepartmentName>?</man:DepartmentName>
               <man:NoOfPeople>?</man:NoOfPeople>
               <man:OfficeLocation>?</man:OfficeLocation>
            </man:DepartmentDetails>
         </man:Departments>
      </man:ManagerDetailsRequest>
   </soapenv:Body>
</soapenv:Envelope>

Response XML:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:man="http://shriwithjava.blogspot.co.nz/managerdetails/">
   <soapenv:Header/>
   <soapenv:Body>
      <man:ManagerDetailsResponse>
         <man:ResponseCode>?</man:ResponseCode>
         <man:ResponseDescription>?</man:ResponseDescription>
      </man:ManagerDetailsResponse>
   </soapenv:Body>
</soapenv:Envelope>

Use Iterator:

We have created a IN sequence, OUT sequence and fault sequence for this service, to use Iterator mediator go to below highlighted IN sequence and click on Edit.


You can find the Iterator mediator in Advance list. Select Iterator Mediator


There are some parameters which you need to define and also the Iterate Expression from which you need to split messages.


  • Iterator Id: we have to define a unique id for the iterator so than all the split message can be identify with this mediator. It is useful in case of aggregation.
  • Sequence Mediator: it defines that how message needs to be split parallel (False) or sequentially (True). By default it is False.
  • Continue Parent: Defines that original message needs to be continue or dropped. Default value is false.
  • Preserve Payload: Specify that original message needs to be used as a template for split message or not. Default value is False.
  • Iterate Expression: This is important parameter this expression matches the string that from where message needs to be split.
  • Attached Path: You can specify the XPATH expression for the new messages that split elements are attached to:



You will get the above screen once you click on the Target Configuration.
  • SOAP Action: Define the message Action.
  • To Address: Defines the endpoint address.
  • Sequence: You can define any sequence from the registry or define a new sequence by adding mediator to current target mediator as children.
  • Endpoint: Send the message from endpoints, you can pick up from registry or can define new one.


Synapse Code:

<definitions xmlns="http://ws.apache.org/ns/synapse">
    <proxy name="ManageManagerServiceProxy" transports="http" startOnLoad="true" trace="disable" statistics="enable">
        <target inSequence="ManageManagerService_IN" outSequence="ManageManagerService_OUT" faultSequence="ManageManagerServiceFaultHandler"/>
        <publishWSDL key="ManageManagerService_WSDL"/>
    </proxy>
                                  <localEntry key="ManageManagerService_WSDL" src="file:repository/conf/managerDetails/wsdl/ManagerDetails.wsdl"/>
    <localEntry key="ManageManagerServiceScript" src="file:repository/conf/managerDetails/scripts/ManagerDetails.js"/>
                                   <sequence name="ManageManagerServiceFaultHandler">
        <payloadFactory>
            <format>
                <man:ManagerDetailsResponse xmlns:man="http://shriwithjava.blogspot.co.nz/managerdetails/">
                    <man:ResponseCode>-1</man:ResponseCode>
                    <man:ResponseDescription>Unknown Exception</man:ResponseDescription>
                </man:ManagerDetailsResponse>
            </format>
        </payloadFactory>
        <property name="RESPONSE" value="true"/>
        <header name="To" action="remove"/>
        <log level="full"/>
        <send/>
        <drop/>
    </sequence>
                                   <sequence name="ManageManagerService_IN">
        <property xmlns:man="http://shriwithjava.blogspot.co.nz/managerdetails/" name="Id" expression="//man:Id/text()"/>
        <property xmlns:man="http://shriwithjava.blogspot.co.nz/managerdetails/" name="Name" expression="//man:Name/text()"/>
        <property xmlns:man="http://shriwithjava.blogspot.co.nz/managerdetails/" name="Address" expression="//man:Address/text()"/>
        <property xmlns:man="http://shriwithjava.blogspot.co.nz/managerdetails/" name="NoOfDepartment" expression="count(//man:Departments/man:DepartmentDetails)"/>
<!—ITERATOR CODE -à
        <iterate xmlns:man="http://shriwithjava.blogspot.co.nz/managerdetails/" id="3ITR_AGG" expression="//man:Departments/man:DepartmentDetails">
            <target>
                <sequence>
                    <property name="DepartmentName" expression="//man:DepartmentName/text()"/>
                    <property name="NoOfPeople" expression="//man:NoOfPeople/text()"/>
                    <property name="OfficeLocation" expression="//man:OfficeLocation/text()"/>
                    <script language="js" key="ManageManagerServiceScript" function="ManageManagerDetailsServiceRequest"/>
<!—Calling DSS - à
                    <send>
                        <endpoint key="DSS_ManageManagerDetails_EPR"/>
                    </send>
                </sequence>
            </target>
        </iterate>
    </sequence>
                                  <sequence name="ManageManagerService_OUT">
        <log level="full"/>
        <aggregate id="ITR_AGG">
            <completeCondition>
                <messageCount min="-1" max="-1"/>
            </completeCondition>
            <onComplete xmlns:s12="http://www.w3.org/2003/05/soap-envelope" xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/" expression="s11:Body/child::*[position()=1] | s12:Body/child::*[position()=1]">
                <property xmlns:man="http://shriwithjava.blogspot.co.nz/managemanagerdetails" name="ResultCode" expression="//man:ManageManagerDetailsResponse/man:ResultCode/text()"/>
                <property xmlns:man="http://shriwithjava.blogspot.co.nz/managemanagerdetails" name="ResultDescription" expression="//man:ManageManagerDetailsResponse/man:ResultDescription/text()"/>
                <filter xpath="contains(get-property('ResultCode'),'1')">
                    <then>
                        <property xmlns:man="http://shriwithjava.blogspot.co.nz/managemanagerdetails" name="RESCULT_CODE" expression="//man:ManageManagerDetailsResponse[man:ResultCode='1'][1]/man:ResultCode/text()"/>
                        <property xmlns:man="http://shriwithjava.blogspot.co.nz/managemanagerdetails" name="RESCULT_DESC" expression="//man:ManageManagerDetailsResponse[man:ResultCode='1'][1]/man:ResultDescription/text()"/>
                    </then>
                    <else>
                        <property name="RESCULT_CODE" value="0"/>
                        <property name="RESCULT_DESC" value="Success"/>
                    </else>
                </filter>
                <payloadFactory>
                    <format>
                        <man:ManagerDetailsResponse xmlns:man="http://shriwithjava.blogspot.co.nz/managerdetails/">
                            <man:ResponseCode>$1</man:ResponseCode>
                            <man:ResponseDescription>$2</man:ResponseDescription>
                        </man:ManagerDetailsResponse>
                    </format>
                    <args>
                        <arg expression="get-property('RESCULT_CODE')"/>
                        <arg expression="get-property('RESCULT_DESC')"/>
                    </args>
                </payloadFactory>
                <property name="RESPONSE" value="true"/>
                <header name="To" action="remove"/>
                <log level="full"/>
                <send/>
                <drop/>
            </onComplete>
        </aggregate>
    </sequence>
<!—DSS Endpoint -à
<endpoint name="DSS_ManageManagerDetails_EPR">
        <address uri="http://localhost:9763/services/ManageManagerDetailsService">
            <timeout>
                <duration>10000</duration>
                <responseAction>fault</responseAction>
            </timeout>
            <suspendOnFailure>
                <errorCodes>101500,101501,101506,101507,101508</errorCodes>
                <initialDuration>3000</initialDuration>
                <progressionFactor>0.0</progressionFactor>
            </suspendOnFailure>
            <markForSuspension>
                <errorCodes>101504,101505</errorCodes>
                <retriesBeforeSuspension>3</retriesBeforeSuspension>
                <retryDelay>1</retryDelay>
            </markForSuspension>
        </address>
    </endpoint>


Used JS:

<x><![CDATA[  
function ManageManagerDetailsServiceRequest(mc) {
var Id = mc.getProperty("Id");
var Name = mc.getProperty("Name");
var Address = mc.getProperty("Address");
var DepartmentName = mc.getProperty("DepartmentName");
var NoOfPeople = mc.getProperty("NoOfPeople");
var OfficeLocation = mc.getProperty("OfficeLocation");
                                 
 mc.setPayloadXML(
    <man:ManageManagerDetails xmlns:man="http://shriwithjava.blogspot.co.nz/managemanagerdetails">
         <man:ManagerId>{Id}</man:ManagerId>
         <man:ManagerName>{Name}</man:ManagerName>
         <man:Address>{Address}</man:Address>
         <man:DepartmentName>{DepartmentName}</man:DepartmentName>
         <man:NoOfPeople>{NoOfPeople}</man:NoOfPeople>
         <man:OfficeLocation>{OfficeLocation}</man:OfficeLocation>
      </man:ManageManagerDetails>

                                     );
}                                 
]]></x>


Execution:

To execute this service, load the project in SOAP UI and hit below request, in this request we are trying to insert data in database while using Iterator mediator. If you see below request you can find that one manager is handles 2 department (CS and IT) and same data we will insert into our database.

Request:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:man="http://shriwithjava.blogspot.co.nz/managerdetails/">
   <soapenv:Header/>
   <soapenv:Body>
      <man:ManagerDetailsRequest>
         <man:Id>1234</man:Id>
         <man:Name>Shri</man:Name>
         <man:Address>Raebareli</man:Address>
         <man:Departments>
            <!--1 or more repetitions:-->
            <man:DepartmentDetails>
               <man:DepartmentName>IT</man:DepartmentName>
               <man:NoOfPeople>30</man:NoOfPeople>
               <man:OfficeLocation>Noida</man:OfficeLocation>
            </man:DepartmentDetails>
            <man:DepartmentDetails>
               <man:DepartmentName>COMPUTER SCIENCE</man:DepartmentName>
               <man:NoOfPeople>40</man:NoOfPeople>
               <man:OfficeLocation>Delhi</man:OfficeLocation>
            </man:DepartmentDetails>
         </man:Departments>
      </man:ManagerDetailsRequest>
   </soapenv:Body>
</soapenv:Envelope>

Response:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <man:ManagerDetailsResponse xmlns:man="http://shriwithjava.blogspot.co.nz/managerdetails/">
         <man:ResponseCode>0</man:ResponseCode>
         <man:ResponseDescription>Success</man:ResponseDescription>
      </man:ManagerDetailsResponse>
   </soapenv:Body>
</soapenv:Envelope>

Now if you look at the database you can find the records.