Version 5.0 - 06/08
Asynchronous Exchange
<< 1 2 3 4 5 6 >>    
Introduction
Synch vs. Asynch Operations
Getting Set Up
Use Case & Implementation
Build & Test the Requester
Build & Test the Initiator
Build & Test the Responder
Using the SOAP ReplyTo Header
Adding Message Correlation

Asynchronous Message Exchange, cont.

Using the SOAP ReplyTo Header

As noted in the previous section, our Responder is currently limited to communicating back to a service at a specific, hard-coded endpoint reference. Ideally, we want any client to be able to submit a request message to the Responder and get a response, so we need a different way to set up the endpoint reference used by the Invoke activity.

One way to do this would be to use a dynamic endpoint reference. This would involve modifying the actual contents of the Invoke activity's Partner Link immediately prior to executing the Invoke itself. While feasible, this may not be preferable, since the process will need some way to know which endpoint reference to set up, and the Responder's process logic will have to be modified to do this.

Another option that avoids modifying either the Requester or the Responder processs logic is to change both process' deployment configurations.

Essentially, what we want to do is change the Responder deployment in such a way that it simply responds to the client that invoked it based on information contained in a <ReplyTo> element in the SOAP Message Header, which is placed there by the caller. For this to work, we'll also need to modify the Requester deployment so that it includes endpoint reference information in the SOAP Header's <ReplyTo> element, indicating where the response should be sent.

Modifying the WSDL Definitions for Callback

Before we proceed with the deployment modifications using ActiveVOS, one set of steps we'll need to perform involves moving both of the roles used by the Responder into a single partnerLinkType definition. This change is necessary due to the manner in which the ActiveVOS engine implements the callback mechanism, which requires that both roles involved be defined in the same partnerLinkType. Since an invoker-based callback is specific to the individual engine implementation, other engines may have different restrictions.

These two roles are currently split across two separate partnerLinkTypes - the ones we defined earlier in Responder.wsdl and ResponderCallback.wsdl. We'll move some of the definitions from the latter file into the former and modify our BPEL processes to accomodate this change.

Switch back to the ActiveVOS Perspective by selecting Window / Open Perspective / Other / ActiveVOS.
From the Project Explorer, open both the wsdl/Responder.wsdl and wsdl/ResponderCallback.wsdl files by double-clicking on them.

In ResponderCallback.wsdl, select and copy the plnk:role from the plnk:partnerLinkType definition to the clipboard (e.g., using Ctrl-C). Switch to Responder.wsdl and paste the plnk:role definition into the ResponderPLT plnk:partnerLinkType definition. The resulting definition in Responder.wsdl should look like this (the added role is highlighted in red below):

 

<plnk:partnerLinkType
  xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype"
  name="ResponderPLT">
  <plnk:role name="responder" portType="tns:ResponderPT" />
  <plnk:role name="responderCallback"
    portType="tns:ResponderCallbackPT" />

</plnk:partnerLinkType>

 

Switch back to ResponderCallback.wsdl and copy the wsdl:message and wsdl:portType definitions in their entirety to the clipboard. Switch to Responder.wsdl and paste them into the file just above the last tag (</wsdl:definitions>). Optionally, you can rearrange the definitions to group the message and portType definitions. Below the </wsdl:types> end tag, you should now have the following elements defined (new elements are in red):

 

  . . .
             
  </wsdl:types>
             
  <wsdl:message name="getAsynchResponseRequest">
    <wsdl:part name="getAsynchResponseRequest"
      element="types1:Document" />
  </wsdl:message>
             
  <wsdl:message name="invokeResponderCallbackRequest">
    <wsdl:part name="invokeResponderCallbackRequest"
      element="types1:Document" />
  </wsdl:message>

 
  <wsdl:portType name="ResponderPT">
    <wsdl:operation name="getAsynchResponse">
      <wsdl:input message="tns:getAsynchResponseRequest" />
    </wsdl:operation>
  </wsdl:portType>

  <wsdl:portType name="ResponderCallbackPT">
    <wsdl:operation name="invokeResponderCallback">
      <wsdl:input message="tns:invokeResponderCallbackRequest" />
    </wsdl:operation>
  </wsdl:portType>


</wsdl:definitions>

 

Save the Responder.wsdl file.

 

Delete ResponderCallback.wsdl. Note that the corresponding Port Type and Partner Link Type definitions in the Interfaces view will disappear when you do this.

Modifying the Requester and Responder Processes

Open both the Requester.bpel and Responder.bpel processes by double-clicking on them. Note that they are now adorned with a red error indicator and that when you open the Problems view with one of these files selected, errors are now displayed. Correct these errors as follows.

Open Requester.bpel in the editor. In the Outline view, navigate the hierarchy into the Partner Links branch, locate the ResponderCallbackPL partner link and delete it.
In the Outline view, navigate the hierarchy into the Imports branch, located the ResponderCallback.wsdl and delete it.
Double-click on the ResponderPL partner link to view its Properties. In the Properties view, select a Role - My Role of responderCallback.

In the Process Editor canvas, double-click the Receive that implements the callback (hint: it's the one that follows the Empty activity). In the Properties view, note that there are unresolved values selected. Change them to the following:


ResponderPL
invokeResponderCallback
replyValue

 

Save the Requester process. Ensure that there are no errors remaining. You should still see a Warning and some Infos in the Problems view, but you can continue to ignore these for now.
Open Responder.bpel in the editor. Once again, in the Outline view, navigate to the ResponderCallbackPL partner link and delete it.
Once again, in the Outline view, navigate to the ResponderCallback.wsdl wsdl import and delete it..
Double-click on the ResponderPL partner link to view its Properties. In the Properties view, select a Role - Partner Role of responderCallback.

In the Process Editor canvas, double-click the Invoke activity. In the Properties view, note that there are unresolved values selected. Change them to the following:

 

ResponderPL
invokeResponderCallback
replyValue

 

Save the Responder process. Ensure that there are no errors remaining.

 

Now that we've consolidated the callback roles into a single partnerLinkType definition, and dealt with the resulting BPEL changes required, we can now re-deploy our two processes. When we do, as mentioned above, we need to make some changes to the way the callback endpoint reference information is determined at run-time, as follows.

 

Modifying the Responder's Deployment Descriptor

To modify the PDD for the Responder, use the following steps.

In the Project Explorer, double-click on deploy/Responder.pdd to open it in the PDD Editor.
Select the Partner Links tab at the bottom of the editor and then select ResponderPL, which is at the top of the Partner LInks list. The values for the Partner Role definition for this Partner Link are displayed below the list.
Set the Invoke Handler setting to address. Change the Endpoint type to invoker. The Endpoint Reference window is cleared when you do this because we'll now be getting the endpoint reference information from the calling entity, i.e., the ResponderPL partner link will now be set up (at run-time) with endpoint reference information supplied by the invoker.
Ensure that the embedded BPEL engine is running. Save and Deploy the Responder process using the same steps we used earlier to deploy the Requester: right-click on the PDD, select Export..., etc. Be sure to select the deploy folder and change the .bpr and .bprd file names from "Requester" to "Responder" where appropriate.

 

Modifying the Requester's Deployment Descriptor

With the Responder re-deployed, we turn to modification of the Requester's PDD.

In the Project Explorer, double-click on deploy/Requester.pdd to open it in the PDD Editor.

Select the Partner Links tab at the bottom of the editor and then select ResponderPL, which is the second item in the Partner Links list.
In the My Role section below the list, to the right, set the Binding to Document Literal and the Service to ResponderCallbackService.

In the Partner Role section below the list, to the left, ensure that the Invoke Handler is set to address and the Endpoint type is set to static.

In the Endpoint Reference text window, modify the XML to add a new <wsa:ReferenceProperties> element just below the <wsa:ServiceName> entry, as shown below:

 

  . . .
  
  <wsa:ServiceName PortName="ResponderPT">s:ResponderService</wsa:ServiceName>
  <wsa:ReferenceProperties>
    <wsa:ReplyTo>
      <wsa:Address>
      http://localhost:8080/active-bpel/services/ResponderCallbackService
      </wsa:Address>
    </wsa:ReplyTo>
  </wsa:ReferenceProperties>

  
  . . .

 

Save the PDD and Export... it to deploy the Requester process.

 

Testing Your Changes

With our modified processes redeployed, we can test the changes using InitiatorClient.

Switch to the Java perspective and right-click on the IniatorClient.java file. Select Run As / Java Application from the cascading pop-up menu.

After a moment, the following message appears in the console (again, you can ignore warnings about attachment support, if present):

Success! Requester returned: 'Initiated AME from thread 'main' - Requester #5 - Responder: Process 6 - Requester out: Process 5'

As before, the message displayed reflects the journey of the data, in this case from the InitiatorClient's main() method, to an instance (process #5, in the instance above) of the Requester process, to an instance (process #6) of the Responder process, back to the Requester process (process #5) and then to the InitiatorClient, which displays the message in the console.

Note the difference here, however: the Responder is actually using endpoint reference information in the request message's SOAP Header to determine where to send the response when its Invoke activity is executed. You can verify this by looking at the Deployed Processes in the ActiveVOS Admin Console. If you click on the Responder in the list of Deployed Processes and view its Deployment Descriptor, you can see that there is no longer any hard-coded endpoint reference information for the callback.You can also examine the Partner Link information for the Active Processes to further satisfy any question of how the response is sent.

Summary

Now any client can call Requester and get an asynchronous response - provided that the caller includes endpoint reference information for a callback in the SOAP <ReplyTo> Header. This makes for an even more loosely coupled message exchange, and is closer to what we would want in a real-world application.