A Simple Example of Using Correlation Sets in Hydra

Article ID: 1220
Last updated: 06 Nov, 2023
Article ID: 1220
Last updated: 06 Nov, 2023
Revision: 3
Views: 1839
Posted: 04 Feb, 2008
by Dean J.
Updated: 06 Nov, 2023
by Gifford C.

Problem


We will be looking at a web service where a client may asynchronously access the service.  Not only that, but multiple clients may access the service at the same time.  An example would be a web service that allows the user to put multiple items into a shopping cart.  The service needs to keep the items chosen by one user separate from those chosen by another user but still allow each user to choose multiple items.  How can the service know when a request comes in that the user has already initiated contact with the service and connect the new request with any previous requests?  We will use correlation sets to accomplish this.
 


Action


Overview of Solution

Correlations sets are the BPEL mechanism to provide a connection between multiple asynchronous messages to an instance of a service so that the state of the service is maintained between requests.  Some token (or group of tokens) is necessary to identify the client to the service.  That token is used to “correlate” the messages to a particular instance of the service.

 

In this example, we will modify the PurchaseApprovalJava tutorial that ships with Hydra.  The original example sends a message containing an item description and a price.  The service uses a java node to determine whether the price is less than $100 or not.  Items costing less than $100 are approved and the rest are declined.  In our modified version, the string sent in the message will identify the client instead of the item being purchased.  This client string will be the token that we will use for the correlation.

 

The xflow will be modified to include a new receive/reply as shown in Figure 1.

 

Figure 1

 

The first receive, ReceivePurchaseRequest, receives a request that initiates the correlation.  The following reply, AcknowledgeReceive, simply acknowledges receipt of the request.  The client ignores the acknowledgement.  This part could easily be changed to a one-way message dropping the acknowledgement.  The service waits for the second request, does the java calculation and responds with a message indicating whether the purchase is approved or not.

 

Procedures

Copy PurchaseApprovalJava tutorial directory to your Eclipse workspace.  Change the name of the directory to CorrelationSets.  Edit <workspace>/CorrelationSets/.project changing the name of the project to CorrelationSets.  At this point you may manually reproduce the following steps or copy the changed files from the attached example into your CorrelationSets directory.

 

·        Modify PurchaseApprovalJava.wsdl as follows:

#code

<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"

   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"

   xmlns:tns="http://www.roguewave.com/projects/PurchaseApprovalJava.wsdl"

   xmlns:xsd="http://www.w3.org/2001/XMLSchema"

   xmlns:PurchaseApprovalJava="http://www.roguewave.com/projects/PurchaseApprovalJava.xsd"

   xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/"

   targetNamespace="http://www.roguewave.com/projects/PurchaseApprovalJava.wsdl"

   name="PurchaseApprovalJava">

 <import namespace="http://www.roguewave.com/projects/PurchaseApprovalJava.xsd" location="PurchaseApprovalJava_types.xsd"/>

 

 <message name="requestMessage">

   <part name="item" type="PurchaseApprovalJava:item"/>

 </message>

<!--  requestDecision message – added  -->

 <message name="requestDecision">

                <part name="identity" type="xsd:string"/>

 </message>

 <message name="responseMessage">

   <part name="response" type="xsd:string"/>

 </message>

 

<!--  correlation section – added   -->

 <bpws:property name="clientIDProperty" type="xsd:string" /> 

 <bpws:propertyAlias propertyName="clientIDProperty"

        messageType="requestMessage"

        part="item" query="item/name" />

 <bpws:propertyAlias propertyName="clientIDProperty"

        messageType="requestDecision"

        part="identity" query="identity/"/>

 

 <portType name="PurchaseApprovalJavaPortType">

   <operation name="PurchaseApprovalJavaOperation">

     <input message="tns:requestMessage"/>

     <output message="tns:responseMessage"/>

   </operation>

<!--  PurchaseApprovalDecision operation – added   -->

   <operation name="PurchaseApprovalDecision">

                <input message="tns:requestDecision"/>

                <output message="tns:responseMessage"/>

   </operation>

 </portType>

 

 <binding name="PurchaseApprovalJavaBinding" type="tns:PurchaseApprovalJavaPortType">

   <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>

   <operation name="PurchaseApprovalJavaOperation">

     <soap:operation soapAction="PurchaseApprovalJavaOperation"/>

 <input>

       <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"

         namespace="http://www.roguewave.com/projects/PurchaseApprovalJava"/>

     </input>

     <output>

       <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"

         namespace="http://www.roguewave.com/projects/PurchaseApprovalJava"/>

     </output>

   </operation>

<!--  PurchaseApprovalDecision operation – added   -->

   <operation name="PurchaseApprovalDecision">

                <soap:operation />

                <input>

         <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"

           namespace="http://www.roguewave.com/projects/PurchaseApprovalJava"/>

                </input>

                <output>

         <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"

           namespace="http://www.roguewave.com/projects/PurchaseApprovalJava"/>

                </output>

   </operation>

 </binding>

   <service name="PurchaseApprovalJavaService">

   <port name="PurchaseApprovalJavaPort" binding="tns:PurchaseApprovalJavaBinding">

     <soap:address location="http://localhost:8090/PurchaseApprovalJava/PurchaseApprovalJava"/>

   </port>

 </service>

</definitions>

#endcode

Figure 2

 

 

·        Changes to the XFlow:

We will need to modify the xflow to take advantage of the new message that we have created.  We will create a new variable, decisionID, for the new requestDecision message.  The receive for the new message must be added to the xflow as well as a reply that acknowledges the initial request to the service. 

 

It is also necessary to let the process know how to identify which incoming messages belong together.  Recall the correlation set that was added to the WSDL (see Figure 3).

#code

<bpws:property name="clientIDProperty" type="xsd:string" /> 

 <bpws:propertyAlias propertyName="clientIDProperty"

        messageType="requestMessage"

        part="item" query="item/name" />

 <bpws:propertyAlias propertyName="clientIDProperty"

        messageType="requestDecision"

        part="identity" query="identity/"/>

#endcode

Figure 3

 

This code defines a correlation set type, clientIDProperty, that correlates the item/name from the requestMessage with the identity from the requestDecision.

 

·        Open the properties sheet for the Process node and add the variable, decisionID which is a requestDecision message.  Select the correlation set tab and add a new set, clientID, of type clientIDProperty.  Apply these properties.

 

·        To associate the ReceivePurchaseRequest message with the correlation set, clientID, open the properties sheet for the Receive Purchase Request node.  On the correlations tab, add the correlation set, clientID.  Because this is the first message our service will receive, set the Initiate field to yes. Apply these properties.

 

·        Because our service will acknowledge the initial message, drag and drop a reply node onto the Receive Purchase Request node. Figure 4 shows the settings for this node.

 

Figure 4

 

·        Now our service will listen for the client to request that the service complete its tasks.  Drag and drop a receive node onto the Acknowledge Receive node.  Open the properties sheet and complete it as shown in Figure 5.  Also select the Correlations tab and add the clientID correlation set to the receive.  This time, however, initiate should be set to no.

 

 

Figure 5

·        The final reply node, Reply, needs to be associated with the receive node, GetDecision.  Modify Reply so that the operation is PurchaseApprovalDecision and the variable is response.

·        Creating the Client

 

·         Instead of using the servlet normally used to test a tutorial, we will use the sample client cpp file, PurchaseApprovalJavaPortClient.cpp.  In Eclipse, open an ant panel with the build.xml for the CorrelationSets project.  Double click the generate-client target.  This generates the data type files and a sample client file in a temp directory.  Edit the file <workspace>/CorrelationSets/temp/client/app/client/PurchaseApprovalJavaPortClient.cpp or copy the file in the attachment.

 

·         Modify the invoke_purchaseApprovalJavaOperation as shown in Figure 6.  Note that the function has been modified to take an Item as its second argument.

 

#code

void invoke_purchaseApprovalJavaOperation(PurchaseApprovalJavaBindingProxy& proxy, PurchaseApprovalJava::Item item_in )

{

  rwsf::CString response_ret;

  rwsf::CallInfo  callInfo;

 

  try {

                  std::cout << "initiate" << std::endl;

    response_ret = proxy.purchaseApprovalJavaOperation(callInfo, item_in);

  } catch(const rwsf::SoapFaultException& e) {

    std::cout << "Fault Code: " << e.getFault().getFaultcode().asString() << std::endl;

    std::cout << "Fault String: " << e.getFault().getFaultstring() << std::endl;

  }

}

#endcode

Figure 6

 

·         Modify the invoke_purchaseApprovalDecision as shown in Figure 7.  Here too the function has been modified to take a second argument only this time it is simply a string.

 

#code

void invoke_purchaseApprovalDecision(PurchaseApprovalJavaBindingProxy& proxy, rwsf::CString identity_in)

{

  rwsf::CString response_ret;

  rwsf::CallInfo  callInfo;

 

  try {

                std::cout << "getting decision" << std::endl;

    response_ret = proxy.purchaseApprovalDecision(callInfo, identity_in);

                std::cout << response_ret << std::endl;

  } catch(const rwsf::SoapFaultException& e) {

    std::cout << "Fault Code: " << e.getFault().getFaultcode().asString() << std::endl;

    std::cout << "Fault String: " << e.getFault().getFaultstring() << std::endl;

  }

}

#endcode

 

·         Modify the try block in main as shown in Figure 8.  Both clients initiate requests and then each requests the results of their purchase request. 

 

#code

try {

    // initialize config files

    rwsf::NamingContext::loadGlobal("../conf/client-objects.xml");

    rwsf::HandlerManager::loadConfiguration("../conf/client-handlers.xml");

    rwsf::TransportManager::initialize("../conf/client-transports.xml");

 

    PurchaseApprovalJavaBindingProxy proxy = PurchaseApprovalJavaBindingProxy::make(location);

 

    if(!proxy.isValid()) {

      std::cerr << "Unable to create proxy. " << "\nExiting" << std::endl;

      return 1;

    }

 

    PurchaseApprovalJava::Item request;

    request.setName("Client1");

    request.setCost("99.99");

    invoke_purchaseApprovalJavaOperation(proxy, request);

    request.setName("Client2");

    request.setCost("999.99");

    invoke_purchaseApprovalJavaOperation(proxy, request);

    invoke_purchaseApprovalDecision(proxy, "Client2");

    invoke_purchaseApprovalDecision(proxy, "Client1");

#endcode

Figure 8

 

 

·        Procedure to Run

 

From Eclipse in the ant panel:

  • build
  • build-client
  • deploy
  • deploy-client
  • startServer

 

From the command line:

  • cd <workspace>/CorrelationSets/temp/client/bin
  • PurchaseApprovalJavaPortClient.exe

The expected results:

in the client

initiate

initiate

getting decision

You've exceeded the $100 limit.

getting decision

Purchase approved.

 

 

See the attached file for a complete example. click here to download

This article was:   Helpful | Not helpful
Report an issue
Article ID: 1220
Last updated: 06 Nov, 2023
Revision: 3
Views: 1839
Posted: 04 Feb, 2008 by Dean J.
Updated: 06 Nov, 2023 by Gifford C.

Others in this category