Monday, July 23, 2012

Routing and Service Chaining with WSO2 ESB Part 3

Part 1 > Part 2 > Part 3 

Creating hcfRequest Sequence


Keep in mind that hcfRequest is the receiving sequence of the response from the GeoService service. 


Let's first analyze the response message that is received by the hcfRequest sequence. 

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <ns:getZipCodeResponse xmlns:ns="http://geo.wso2">
         <ns:return>32746</ns:return>
      </ns:getZipCodeResponse>
   </soapenv:Body>
</soapenv:Envelope>


The response message will contain the zipcode and will be received by hcfRequest sequence. 

Click on 'Sequences' under Service Bus and you will see the following screen. Click on 'Add Sequence'.



Give the following values as shown below. 



A log mediator is first added as shown below.  




Next a property mediator is added.



The property mediator is added to obtain the zipcode value from the response of the GeoService service.

Name - zipcode
Action - Set
Set Action as - Expression
Type - STRING
Expression - //geo:getZipCodeResponse/geo:return/text()




Add another log mediator to log the value of the zipcode as shown below. 



To construct the body of the message we will now be using the payloadfactory mediator instead of the enrich mediator and you will see that it's much easier to use it.  To add a payloadfactory mediator go to  Transform -> PayloadFactory. 



The payload format should contain the body of the message and for the input parameters enter the order of the parameter is prefixed by the dollar sign. In this case we have only one parameter and it will be $1. If we have a 2nd or 3rd paramater (and so on) we can have them as $2, $3.. $n. 

Let's analyze the format of the request message, so that we can construct it accordingly. 

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:heal="http://healthcare.wso2">
   <soap:Header/>
   <soap:Body>
      <heal:getHCCenters>
         <!--Optional:-->
         <heal:postalCode>?</heal:postalCode>
      </heal:getHCCenters>
   </soap:Body>
</soap:Envelope>


Therefore the payload format should be as follows. 

Payload format - 

<heal:getHCCenters xmlns:heal="http://healthcare.wso2">
   <heal:postalCode>$1</heal:postalCode>
</heal:getHCCenters>

The values for the arguments can be given by adding properties. In this case $1 in the message will be replaced by argument expression provided, which is the zipcode in this case. 

Argument Value/Expression - $ctx:zipcode

You can click on the Help link on the top right of the properties view to get more information about the mediator. 




Add another log mediator. 



Add a send mediator to send this message to the HCFacilityLocator service. 





The properties view should look like as given in the following screen. Browse for the HCFacilityLocatorServiceEP from the configuration registry and for the receiving sequence we need to give hciRequest sequence, which needs to be created. After it is created browse for it and update the sequence. Save the hcfRequest sequence. 

  

* Make sure to go back to the HCCService proxy service and browse for the receiving sequence to hcfRequest and update the proxy service, since we just created hcfRequest. 



Creating hciRequest sequence


hciRequest is the receiving sequence of the response from the HCFacilityLocator service. 

Let's analyze the response message that is received by the hciRequest sequence.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <ns:getHCCentersResponse xmlns:ns="http://healthcare.wso2">
         <ns:return>2583</ns:return>
         <ns:return>5201</ns:return>
         <ns:return>5575</ns:return>
         <ns:return>805</ns:return>
         <ns:return>2285</ns:return>
      </ns:getHCCentersResponse>
   </soapenv:Body>
</soapenv:Envelope>

The response message will contain one or more health care center codes.  We need to send these codes to the HCInformation service, one by one, to receive details about each health care center.  Therefore this message needs to be split and several messages need to be sent to the HCInformation service because it only accepts one health care center code. Let's create hciRequest which will do the splitting and routing. 

Create another sequence and provide the name hciRequest.

Add a log mediator. 



Add the following properties.



Next we have to add an iterate mediator. The reason for this is that when the zipcode was sent to HCFacilityLocatorService, it returns a list of health care center codes. A typical response would be as follows.

<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
   <soapenv:Body>
      <ns:getHCCentersResponse xmlns:ns="http://healthcare.wso2">
         <ns:return>0000</ns:return>
         <ns:return>0001</ns:return>
      </ns:getHCCentersResponse>
   </soapenv:Body>
</soapenv:Envelope>

In this case, there are 2 ns:return elements. For each of those elements, we need to extract the healthcare center code value and perform a send operation because to get the healthcare details for one healthcare center, the healthcare center code should be sent.

The iterate mediator will split the message into a number of different messages (2 messages in this case) derived from the parent message by finding matching elements for the XPath expression specified. New messages will be created for each and every matching element and processed in parallel (default behavior) using either the specified sequence or endpoint.

To add an iterator mediator - Advanced -> Iterate.



When an iterate mediator is added, you will see that a target mediator will be added too. The target mediator can be used to form a new SOAP message from an existing SOAP info-set. For more information on the target mediator, click on the help link that comes in the properties view when the target mediator is selected. 





Click on the iterate mediator and provide the following values:

Iterate ID -  
Sequential Mediation - False
Continue Parent - False
Preserve Payload - True
Iterate Expression* - //hfs:getHCCentersResponse/hfs:return
Attach Path - //hfs:getHCCentersResponse

For more information on the iterate mediator click here.




When you click on the target mediator, you will see the following configurations.




Let's analyze the format of the request message, so that we can construct it accordingly.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:heal="http://healthcare.wso2">
   <soapenv:Header/>
   <soapenv:Body>
      <heal:getHCCenterInfo>
         <!--Optional:-->
         <heal:hcCenterCode>?</heal:hcCenterCode>
      </heal:getHCCenterInfo>
   </soapenv:Body>
</soapenv:Envelope>


Click on the target mediator and add a payloadfactory mediator.




Provide the following information as shown.


Payload format - 

<heal:getHCCenterInfo xmlns:heal="http://healthcare.wso2">
   <heal:hcCenterCode>$1</heal:hcCenterCode>
</heal:getHCCenterInfo>

Argument Expression - //hcc:getHCCentersResponse/hcc:return/text()



Add a log mediator as follows. 



Finally add a send mediator. 



Click on Configuration Registry to point to the HCInformationService endpoint.



Select HCInformationService from the drop down list.



Click on update and save. 



Here's the overview of the sequence we created. Log -> Iterate ->For each iteration create the payload with the healthcare center code and send it to HCInformationService to get the healthcare center details.



* Remember go back to the hcfRequest sequence and browse for the receiving sequence in the send mediator to hciRequest and update hcfRequest sequence, since we just created hciRequest. 


Creating the HCCService Proxy Service (Part 2)


Let's briefly recap what we have completed so far.



  • Created the HCCService proxy service. 
  • Created the in sequence for the proxy service but didn't create the out sequence. 
  • Created the hcfRequest and hciRequest sequences. 
  • Let's create the out sequence for the proxy service now.
Before creating the out sequence, let's check the format of the response messages that HCInformation service sends. Bear in mind that several response messages will be sent.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <ns:getHCCenterInfoResponse xmlns:ns="http://healthcare.wso2">
         <ns:return xsi:type="ax21:HCInfo" xmlns:ax21="http://healthcare.wso2/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <ax21:address>2583 South Volusia Ave (17-92), Suite 300</ax21:address>
            <ax21:approxDistance>13.1</ax21:approxDistance>
            <ax21:city>Orange City,  FL</ax21:city>
            <ax21:hcCenterName>Orange City CBOC</ax21:hcCenterName>
            <ax21:phone>386-456-2080 Or 386-456-2082</ax21:phone>
         </ns:return>
      </ns:getHCCenterInfoResponse>
   </soapenv:Body>
</soapenv:Envelope>

Since, several of these messages will be received by the out sequence, the out sequence must aggregate them into one message and sent to the user, because after all the user send his coordinates to receive information about all the healthcare centers in his vicinity. 

We need to send a response such as the following:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <ns:getHCCenterInfoResponse xmlns:ns="http://healthcare.wso2">
         <ns:return xsi:type="ax21:HCInfo" xmlns:ax21="http://healthcare.wso2/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <ax21:address>2583 South Volusia Ave (17-92), Suite 300</ax21:address>
            <ax21:approxDistance>13.1</ax21:approxDistance>
            <ax21:city>Orange City,  FL</ax21:city>
            <ax21:hcCenterName>Orange City CBOC</ax21:hcCenterName>
            <ax21:phone>386-456-2080 Or 386-456-2082</ax21:phone>
         </ns:return>
      </ns:getHCCenterInfoResponse>
      <ns:getHCCenterInfoResponse xmlns:ns="http://healthcare.wso2">
         <ns:return xsi:type="ax21:HCInfo" xmlns:ax21="http://healthcare.wso2/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <ax21:address>5201 Raymond Street</ax21:address>
            <ax21:approxDistance>14.1</ax21:approxDistance>
            <ax21:city>Orlando,  FL</ax21:city>
            <ax21:hcCenterName>Orlando VA Medical Center</ax21:hcCenterName>
            <ax21:phone>407-629-1599 Or 800-922-7521</ax21:phone>
         </ns:return>
      </ns:getHCCenterInfoResponse>
      <ns:getHCCenterInfoResponse xmlns:ns="http://healthcare.wso2">
         <ns:return xsi:type="ax21:HCInfo" xmlns:ax21="http://healthcare.wso2/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <ax21:address>5575 S. Semoran Blvd. #30</ax21:address>
            <ax21:approxDistance>18.3</ax21:approxDistance>
            <ax21:city>Orlando,  FL</ax21:city>
            <ax21:hcCenterName>Orlando Vet Center</ax21:hcCenterName>
            <ax21:phone>407-857-2800</ax21:phone>
         </ns:return>
      </ns:getHCCenterInfoResponse>
      <ns:getHCCenterInfoResponse xmlns:ns="http://healthcare.wso2">
         <ns:return xsi:type="ax21:HCInfo" xmlns:ax21="http://healthcare.wso2/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <ax21:address>805 Oakley Seaver Drive</ax21:address>
            <ax21:approxDistance>28.7</ax21:approxDistance>
            <ax21:city>Clermont,  FL</ax21:city>
            <ax21:hcCenterName>Clermont CBOC</ax21:hcCenterName>
            <ax21:phone>352-536-8200 Or 877-469-9037</ax21:phone>
         </ns:return>
      </ns:getHCCenterInfoResponse>
      <ns:getHCCenterInfoResponse xmlns:ns="http://healthcare.wso2">
         <ns:return xsi:type="ax21:HCInfo" xmlns:ax21="http://healthcare.wso2/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <ax21:address>2285 North Central Avenue</ax21:address>
            <ax21:approxDistance>31.5</ax21:approxDistance>
            <ax21:city>Kissimmee,  FL</ax21:city>
            <ax21:hcCenterName>Kissimmee CBOC</ax21:hcCenterName>
            <ax21:phone>407-518-5004</ax21:phone>
         </ns:return>
      </ns:getHCCenterInfoResponse>
   </soapenv:Body>
</soapenv:Envelope>


Let's create the out sequence. In the Manage menu, Go to Web Services -> List and click on HCCService. Click Edit under Specific Configuration to edit the proxy service.
Proceed to step 3 of 3 to create the out sequence as shown below. 



Add a log mediator as shown below.



We will now add an aggregate mediator as shown below. Core -> Aggregate. The purpose of adding the aggregate mediator is to aggregate the messages and compose 1 message. An aggregate mediator usually always follows an iterate mediator, as is the case here.  For more information on aggregate mediators, click here.



Add the following properties for the aggregate mediator as shown in the image.


Aggregation Expression -//hcc:getHCCenterInfoResponse

This is an XPath expression specifying based on which elements to aggregate. 

Completion Max-messages -  -1
Completion Min-messages -  -1


These are the maximum and minimum number of messages that can exist in an aggregation. In this case we specify both as -1 because we want all of the messages to be aggregated and will not specify a max or min number. 


On Complete - Anonymous




Click on the aggregate mediator and add a log mediator.



Give the following properties to the log mediator.



Finally, add a send mediator under the aggregate mediator.


In the send mediator we will not specify an endpoint, thereby sending the message back to the original
sender.


We have now completed the creation of the out sequence, so click on Finish.



We have now completed configuring the set up in the WSO2 ESB. Here's the source view of the HCCService proxy service. 


<proxy xmlns="http://ws.apache.org/ns/synapse" name="HCCService" transports="https,http" statistics="disable" trace="disable" startOnLoad="true">
   <target>
      <inSequence>
         <property xmlns:heal="http://healthcare.wso2" name="longitude" expression="//heal:getHealthcareCenterInfo/heal:longitude/text()" scope="default" />
         <property xmlns:heal="http://healthcare.wso2" name="latitude" expression="//heal:getHealthcareCenterInfo/heal:latitude/text()" scope="default" />
         <log level="custom">
            <property name="Longitude" expression="$ctx:longitude" />
            <property name="Latitude" expression="$ctx:latitude" />
         </log>
         <enrich>
            <source type="inline" clone="true">
               <geo:getZipCode xmlns:geo="http://geo.wso2">                        
                  <geo:longitude>0</geo:longitude>                        
                  <geo:latitude>0</geo:latitude>                    
               </geo:getZipCode>
            </source>
            <target type="body" />
         </enrich>
         <enrich>
            <source type="property" clone="true" property="longitude" />
            <target xmlns:geo="http://geo.wso2" xpath="//geo:getZipCode/geo:longitude/text()" />
         </enrich>
         <enrich>
            <source type="property" clone="true" property="latitude" />
            <target xmlns:geo="http://geo.wso2" xpath="//geo:getZipCode/geo:latitude/text()" />
         </enrich>
         <log level="full" />
         <send receive="hcfRequest">
            <endpoint key="GeoEP" />
         </send>
      </inSequence>
      <outSequence>
         <log level="full" />
         <aggregate>
            <completeCondition>
               <messageCount min="-1" max="-1" />
            </completeCondition>
            <onComplete xmlns:hcc="http://healthcare.wso2" expression="//hcc:getHCCenterInfoResponse">
               <log level="full" />
               <send />
            </onComplete>
         </aggregate>
      </outSequence>
   </target>
</proxy>

Testing the Scenario

1) Run the WSO2 ESB with the configurations. 
2) Run the WSO2 Application Server instance that hosts the services created. 
3) Run soapUI and create a soapUI project with the WSDL for the HCCService proxy service, which can be found here











Thursday, July 5, 2012

Routing and Service Chaining with WSO2 ESB Part 2

Part 1 > Part 2Part 3 

Part 2 of this series will cover the following:

Deployment of GeoService, HCFacilityLocatorService and HCInformationService in the WSO2 Application Server. 
Creation of the endpoints GeoEP, HCFacilityLocatorServiceEP and HCInformationService in the WSO2 ESB. 
Creation of HCCService proxy service in the WSO2 ESB.

Bear in mind that all the artifacts can be downloaded from - https://sites.google.com/site/duckysfilecabinet/dlmi . This will be a step-by-step guide to creating the artifacts that are  given.

Abbreviations

AS - Application Server
EPR - Endpoint Reference
ESB - Enterprise Service Bus

Prerequisites

1) Read part 1 of this tutorial to understand the demo scenario. 

2) Have the following installed:

WSO2 ESB Version - 4.0.3 
WSO2 Application Service Version - 4.1.2  Go to repository/conf/carbon.xml in from the home folder of the application server and set port offset to 1. The reason being that the ESB and the Application server both need to run at the same time on the same machine and they are configured to run on the same port - 9443. When the port offset is set to 1 in the Application Server, it will now run on port 9444. 
soapUI - 2.5

Adding the Services to AS

Download the following services and deploy them to AS.  

Go to the management console of the WSO2 Application Server.

Add -> Axis2 Service



Browse and choose the file as shown below. 



Deploy the given .aar files - GeoService (geows-SNAPSHOT.aar), HCFacilityLocatorService (hcfacilitylocator-SNAPSHOT.aar) and HCInformationService (hcinformationservice-SNAPSHOT.aar)



If you click on the GeoService service, the service dashboard will appear. On the endpoints section you will see the http and https endpoint URLs. Similarly you can obtain information about the other services as well. 


Creating Endpoints 

Go to the management console of the ESB. Click on Endpoints under Service Bus and the following screen will appear. Click on Address Endpoint.


An Address endpoint is an endpoint defined by specifying the EPR and other attributes of the endpoint directly in the configuration. The 'uri' attribute of the address element contains the EPR of the target endpoint.

To create the first endpoint, fill in with the following details as given in the screenshot.  

Name - GeoEP



After the endpoint is created, if you click on the source view tab you will see the following - 

<endpoint xmlns="http://ws.apache.org/ns/synapse" name="GeoEP">
   <address uri="http://localhost:9764/services/GeoService/" format="soap11" >
      <suspendOnFailure>
         <progressionFactor>1.0</progressionFactor>
      </suspendOnFailure>
      <markForSuspension>
         <retriesBeforeSuspension>0</retriesBeforeSuspension>
         <retryDelay>0</retryDelay>
      </markForSuspension>
   </address>
</endpoint>

Similarly create the HCFacilityLocatorServiceEP endpoint with the following properties - 

Name - HCFacilityLocatorServiceEP
Address - http://10.200.3.38:9764/services/HCFacilityLocatorService/



And the HCInformationService endpoint with the following properties.

Name - HCInformationService



After saving each of the endpoints that were created, you will now be able to view the list of endpoints available in the Defined Endpoints tab. 




Creating the HCCService Proxy Service (Part 1) 

As mentioned in the previous post, HCCService will be the proxy service used. The In Sequence of the HCCService will first call the GeoService service with the longitude and latitude values. 

Go to the management console of the WSO2 ESB. Go to Add -> Proxy Service as shown below. 





Select Custom Proxy.


Next a 3 step wizard will appear. Step 1 of 3 will be to fill in basic settings.

Proxy Service Name - HCCService (leave everything else as they are).

(Alternatively you could publish a WSDL for the proxy service if required. You can find the WSDL for the HCCService here).

Then click on Next.




For step 2 of 3, which is to create the in sequence, select Define Inline and click on Create.
(You can define an endpoint if you do not want to mediate the incoming message instead of defining the in sequence).




You will now see a graphical editor to add mediators to sequences. Click on Add Child. 



We will first add a property mediator. Add Child -> Core -> Property. 


The editor will now have a new child node, which is the property mediator.


Let's take a look at the request message before we set the properties of the property mediator. We need to obtain the longitude and latitude values to  pass on to the GeoService service. 


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:heal="http://healthcare.wso2">
   <soapenv:Header/>
   <soapenv:Body>
      <heal:getHealthcareCenterInfo>
         <!--Optional:-->
         <heal:longitude>3</heal:longitude>
         <!--Optional:-->
         <heal:latitude>4</heal:latitude>
      </heal:getHealthcareCenterInfo>
   </soapenv:Body>
</soapenv:Envelope>
The property mediators will be used to store the values of longitude and latitude. Click on the property mediator and go to the properties view below. Give the following values.
Name - longitude
Action - Set  (The action can be set or remove. 'Set' to add a new property and 'Remove' to remove a property with the given name).
Set Action as - Expression (Specify which type of value to store) 
Type - String
Expression - //heal:getHealthcareCenterInfo/heal:longitude/text()  (XPath expression)




Add another property mediator and add the following properties as shown below.

Name - latitude
Action - Set  
Set Action as - Expression 
Type - String
Expression - //heal:getHealthcareCenterInfo/heal:latitude/text()




For more information on the property mediator check here

Let's now add a log mediator. 


In the properties section add the properties as given below. 
Log Category - INFO  (Log messages will be logged in log4j with selected log category. The default log category is INFO)

Log level - Custom (Custom: Only properties specified to the Log mediator)
Log Seperator - , (The log separator is used to separate the attributes being logged. The default separator is ',' (comma))

Add properties for the log mediator. Longitude and Latitude values will be loggged because the Log level is Custom. 

$ctx:longitude and $ctx:latitude ($ctx is the prefix for Synapse message context properties)



For more information on the log mediator check here.

As shown in the screenshot below, let's add an enrich mediator now. For more information on enrich mediator check here. Actually, we can avoid using the enrich mediator here and use the payloadfactory mediator instead. You can see the reason for this later where I explain about its use.  

With the enrich mediator we will be replacing the body of the message with the body of a request message that goes to the GeoService. 



Give the following values for the enrich mediator as shown.

Source:
Clone - true (By setting the clone configuration, the message can be cloned or else used as a reference during the enriching)
Type - inline (Specifies an inline xml value)
Inline Content should be chosen from the radio buttons. 
Inline XML -

<geo:getZipCode xmlns:geo="http://geo.wso2">
                        <geo:longitude>0</geo:longitude>
                        <geo:latitude>0</geo:latitude>
                    </geo:getZipCode>

Target:
Action - replace  (By specifying the action type the relevant action can be applied to outgoing message. By specifying the replace action type it replaces the xml message based on the target type specified on the target configuration)
Type - body (Body of the original message will be used for enriching)




Add another enrich mediator and add the following values.  This is used to replace the longitude value of the body with the longitude value received by the proxy service. 

Source:
Clone - true
Type - property (Specifies a property)
Property - longitude

Target:
Action - replace
Type - custom (To give custom XPath value) 
XPath Expression - //geo:getZipCode/geo:longitude/text()



Add a 3rd enrich mediator as shown below. This is used to replace the latitude value of the body with the latitude value received by the proxy service.  This will be similar to the previous endpoint except for the values for the following properties. 

Property - latitude
XPath Expression - //geo:getZipCode/geo:latitude/text()



Add another log mediator as shown below with the given properties. 



Finally add a send mediator as shown below. Add Child -> Core -> Send. 



Following is the screenshot when everything is complete for the send mediator.




Select Endpoint type - Pick from Registry (browse in the configuration registry as shown and select GeoEP endpoint).



In the properties view of the send mediator, the receiving sequence type should be selected as static (or dynamic if calculated using a XPath).

The receiving sequence (hcfRequest) can be selected and given as shown below.



For more information on the send mediator click here

Note that hcfRequest is a sequence that needs to be created. When the screenshot was taken hcfRequest was already created and added as the receiving sequence for the ease of understanding. Since you have not created hcfRequest sequence at this point, after creating the send mediator, save the proxy service and let's get on to creating the hcfRequest sequence. After creating it, come back to the send mediator and add the sequence as shown above. hcfRequest will be created in part 3 of this tutorial series.