Friday, September 18, 2009

Correlation with BPEL

An application must maintain data integrity when messages are exchanged between services. A manufacturer that receives orders, for example, must not mix data for one order with the data for another.

A BPEL process addresses this issue with correlation sets, each of which is a list of properties whose values are expected to remain constant throughout a process or throughout a specific scope, even as data is transmitted to and from partner services.

For purposes of an example, here is a process that records the purchase orders of custumers, so it needs to identify each specific custumer-order. This is the diagram of the whole process:



The following steps describe how to identify a process using correlation sets:

  1. First, the following namespace into your WSDL file:
              xmlns:bpws="http://docs.oasis-open.org/wsbpel/2.0/varprop"

  2. Create the property to be used to identify your process. In this example we will use 2 values to identify the process or the PO of the customer, so add the following at the end of your WSDL.
                    <bpws:property name="customerID" type="p:string" />
                    <bpws:property name="orderNumber" type="p:string" />

  3. The process will start after answer the first request, for example, when the customer puts a new Purchase Order, the process will return the PO number, then the BPEL process will identify an specific process using the CustomerID and the OrderNumer. To do the previous logic, add the following to your WSDL. This is telling that the CID and Order will be used as a combined key.

                <!-- sendResponse -->
                <bpws:propertyAlias propertyName="tns:customerID" messageType="tns:sendPOResponse" part="confirmation">
                    <bpws:query><![CDATA[/tns:CID]]></bpws:query>
                </bpws:propertyAlias>
                <bpws:propertyAlias propertyName="tns:orderNumber" messageType="tns:sendPOResponse" part="confirmation">
                        <bpws:query><![CDATA[/tns:Order]]></bpws:query>
                </bpws:propertyAlias>

  4. Also, for each subsequent message sent to the BPEL process we will require that the user sends the CID and Order, to do that, define that while requesting a operation those values must be sent. Example:
                <!-- QUERY Request -->
                <bpws:propertyAlias propertyName="tns:customerID" messageType="tns:queryPORequest" part="query">
                    <bpws:query><![CDATA[/tns:CID]]></bpws:query>
                </bpws:propertyAlias>
                <bpws:propertyAlias propertyName="tns:orderNumber" messageType="tns:queryPORequest" part="query">
                    <bpws:query><![CDATA[/tns:Order]]></bpws:query>
                </bpws:propertyAlias>


  5. Now, define the correlationSets into your BPEL process
               <bpws:correlationSets>
                    <bpws:correlationSet name="PurchaseOrder" properties="tns:customerID tns:orderNumber"/>
                </bpws:correlationSets>

  6. As previously mentioned, the process will start when answering to the first request, so we define that inside the first reply activity:
                <bpws:reply name="replyOutput" operation="sendPO" partnerLink="POLink" portType="tns:purchaseOrderProcess" variable="output">
                    <bpws:correlations>
                        <bpws:correlation
    initiate="yes" set="PurchaseOrder"/>
                    </bpws:correlations>
                </bpws:reply>

       
  7. And in subsequent requests, the correlation only will be used, not initiated again. For example, while querying the process:

           <bpws:onMessage operation="queryPO" partnerLink="POLink" portType="tns:purchaseOrderProcess" variable="queryInput">
               <bpws:correlations>
                        <bpws:correlation
initiate="no" set="PurchaseOrder"/>
                </bpws:correlations>




Download the example from here.

Monday, September 14, 2009

Consuming external web services

Example of how to call an external Web Service from a BPEL process:

Follow these steps:
  1. First, download and install "HelloWorld" Web Service into your servlet container. This simple service has 2 operations:
    1. sum: returns the result of adding two numbers. This is the operation we will use.
    2. example: concatenates your input with "External WebService".
  2. Before calling this WS check if the web service is working fine. Test the "sum" operation.
  3. Open your Eclipse and create a new BPEL project. Name it as "HelloCaller".
  4. Create a new BPEL process file with the following data:
    1. BPEL Process name: helloCaller
    2. Namespace: http://mydomain.org/bpel/helloCaller
    3. Template: Synchronous BPEL process
  5. Add the HelloWorld WSDL file into the process. Be sure your file is visible to your project.



  6. Add a Partner Link and named it as "helloLnk".
  7. Open the details of "helloLnk" and click on "Browse" button. Then a dialog will appear, at the bottom click over the "Add WSDL" button. Select the HelloWorld WSDL file.
  8. Select the port named as "HelloWorldServicePortType"and click "OK" button; a new dialog will appear.
    1. Define the name of your Partner Link Type as "helloPLType" and click "Next" button.
    2. Type a Role Name as "helloProvider" and click "Finish" button.
  9. Bellow the "Partner Role" section select "helloProvider".



  10. Open the BPEL process (helloCaller.bpel) with the BPEL designer and add the following activities and name them as suggested:
    1. Assign: InitializeVars
    2. Invoke: SumNumbers
    3. Assign: SetResult

    You should see your diagram as the following:



  11. Open the properties of "SumNumbers" and select the "sum" operation from the "HelloWorldPortType".











  12. Open the properties of "InitializeVars" activity and add a copy step.
    1. From: Fixed Value

      <ns0:sum xmlns:ns0=http://webservice.augusto.org>
      <ns0:in0/>
      <ns0:in1/>
      </ns0:sum>

    2. To: Variable
    3. Select helloLnkRequest the "and then "parameters"


  13. Add a new copy step to "InitializeVar" with the following data:



  14. And add the last copy step to the "InitializeVars"


  15. Now, select the "SetResult" and add 2 steps. In the first one initialize the response:
    1. From: Fixed Value

      <tns:helloCallerResponse xmlns:tns="http://mydomain.org/bpel/helloCaller">
      <tns:result/>
      </tns:helloCallerResponse>
    2. To: Variable
    3. Select output the and then "payload"
  16. Finally, copy the result from the "HelloWorld" service to the output of your BPEL process.
  17. You need to define the service and the location of it.
  18. Define the deployment descriptor. Remember that for every partner link used with a <receive> activity must be matched with a <provide> element, and every partnerLink used in an <invoke> activity must be matched with an <invoke> element in deploy.xml. For example, for this process the following code is used:
<process name="pns:helloCaller">
<active>true</active>
<provide partnerLink="client">
<service name="pns:helloCallerService" port="helloCallerPort" />
</provide>
<!-- Hello World Web Service -->
<invoke partnerLink="helloLnk">
<service name="wns:HelloWorldService" port="HelloWorldServiceHttpPort" />
</invoke>
</process>

  1. Now, deploy your helloCaller service and test it. Download the example from here.


Software required to run the example:
  1. Eclipse
  2. BPEL designer for Eclipse - http://www.eclipse.org/bpel/
  3. Apache ODE 1.3.2

References

  1. How to create a Partner Link