BPEL BluePrint 4

Message-Based Coordination of Events Using BPEL

Kiran Bhumana, Ryan Kennedy, Shauna Pickett-Gordon

Problem Description

Message-driven execution has become an important aspect of many programming languages. If you are familiar with JMS or any other messaging architecture, especially with the usage of event listener patterns, you'll find a similar approach in the BPEL language.

Consider the purchase order service example discussed in the first three BluePrints. It would also be useful to be able to respond to an event--external or internal--that might occur after the BPEL process begins executing. An example of such an event is a client sending a cancellation message or a confirmation message.

The Java language itself supports message-based coordination of events. However, BPEL provides a message-driven execution pattern that helps minimize the additional code needed for coordination. BPEL also provides an important and useful construct: a timer-based execution path, as an alternative to a message-driven path. These advantages leave developers free to spend more time thinking about the core business logic of their BPEL processes.

This BluePrint focuses on the design aspects and common usage patterns of message-driven event coordination using BPEL.

Solution

BPEL lets developers define alternative execution paths based on Timer or Message events.

A Message event, defined by an onMessage construct, waits for a corresponding message to arrive before proceeding with a specified execution path. An onMessage construct is defined exactly the same way as a receive activity where partnerLink, portType, and operation attributes are specified.

A Timer event, defined by an onAlarm activity, waits for a specified duration or deadline before triggering the appropriate execution path.

BPEL provides a pick construct for situations requiring multiple alternative execution paths. When a BPEL process encounters a pick activity, it waits until either an onMessage or an onAlarm construct occurs. In this manner, onAlarm and onMessage constructs contend for the execution path of the instance. Of the multiple alternative paths provided by the pick construct, only one path is ultimately executed.

If you worked through the second BluePrint, Asynchronous Web Service Interactions Using BPEL, you noticed two usage patterns of the pick construct: a timer-based path and an alternative message-event-based path. Both BluePrints use correlation, too; if you're not already familiar with it, see the second BluePrint.

Design Details

The services used in this BluePrint go beyond the scope of the first three BluePrints. For the basic BPEL business logic and behavior of this example, see the first BPEL BluePrint. For more information on using correlation, see the second BPEL BluePrint.

In addition to the BPEL processes POService and InventoryService as defined in the first BluePrint, this BluePrint uses the web services confirmPO and cancelPO. The POService process orchestrates all purchase-order-related services, and it provisions the two additional web services.

The following figure shows a message-driven path implementing an asynchronous service.

Message-driven Path with Asynchronous Service Implementation

Figure 1: A Message-driven Path With Asynchronous Service Implementation

The following constructs are used in this BluePrint's scenario:

When you're developing a BPEL process, carefully consider the events to which the process should react, as well as how long a process should wait when orchestrating services.

A pick activity demonstrates the orchestration of the process in which a different path of execution is chosen, based on either the arrival of messages or a time-triggered event.

Business Logic of the Services

Let's look at how a message-driven execution path can be used. In this pattern, four services are involved. Three of those services are consumed by an external client through SOAP over HTTP:

The fourth is an inventory check service consumed by the BPEL process that provisions the purchase order service.

An external client consumes POService. Upon receiving a request, POService checks with InventoryService and returns either a reply or a fault to the external consumer. If the returned value is a valid reply, the instance is associated with a correlation ID. If a fault is replied, the instance is terminated.

Upon receiving the reply, the external consumer decides whether to send a confirmation of the purchase order, to send a cancellation of the purchase order, or to not take any action at all. The purchase order service, after returning a valid response, awaits either a confirmation or cancellation of the order within a specified length of time. The POService BPEL process defined here waits for 100 seconds, as stipulated.

Since the purchase order request and the request's confirmation or cancellation are events that need to be coordinated, correlation is used to route the associated messages. The purchase order instance is associated with the correlation ID while the reply to the purchase order service is being executed. The same correlation ID is expected to appear in the orderId attribute of the confirmation or cancellation message.

Define the WSDL

Refer to the first BluePrint for an explanation of how the POService and InventoryService WSDLs are declared.

The POStatus WSDL defines two operations: a confirmation and a cancellation.

   <portType name="POStatusPortType">
<operation name="confirmPO">
<input name="confirmPO"
message="tns:POConfirmMesg"></input>
<output name="confirmPOStatus"
message="tns:POStatusMesg"></output>
<fault name="confirmPOFault"
message="ns:orderFaultType"></fault>
</operation>
<operation name="cancelPO">
<input name="cancelPO"
message="tns:POCancelMesg"></input>
<output name="cancelPOStatus"
message="tns:POStatusMesg"></output>
<fault name="cancelPOFault"
message="ns:orderFaultType"></fault>
</operation>
</portType>
The postatus WSDL defines a property, OrderID, and three property aliases.
    <bpws:property name="OrderID"
type="xsd:int"/>
<bpws:propertyAlias part="purchaseOrder"
propertyName="tns:OrderID"
messageType="tns:POConfirmMesg">
<bpws:query>/purchaseOrder/orderId</bpws:query>
</bpws:propertyAlias>
<bpws:propertyAlias part="purchaseOrder"
propertyName="tns:OrderID"
messageType="tns:POCancelMesg">
<bpws:query>/purchaseOrder/orderId</bpws:query>
</bpws:propertyAlias>
<bpws:propertyAlias part="purchaseOrder"
propertyName="tns:OrderID"
messageType="ns:POMessage">
<bpws:query>/purchaseOrder/orderId</bpws:query>
</bpws:propertyAlias>

Important Design Note

Three property aliases--different because they are associated with different messages--are defined on the same property. If you define a correlation on such a property (in this case, OrderID), you can use the correlation for multiple messages with which this property is associated. The association is made indirectly through the property aliases.

In this case, the same correlation set can be used for the messages POService WSDL's POMessage and POStatus WSDL's POConfirmMesg and POCancelMesg.

For details on how to use correlation, refer to the BPEL specification.

Define the BPEL

See the first BluePrint for information on how the POService and InventoryService processes are defined.

The following correlationSet is defined in POService.

    <correlationSets>
<correlationSet name="POConfirmationSet"
properties="ns0:OrderID"/>
</correlationSets>

Correlation is initialized here when the reply is executed.

    <reply name="sendPurchaseOrder.Reply"
partnerLink="POServicePLink"
portType="pos:purchaseOrderPT"
operation="sendPurchaseOrder"
variable="purchaseOrderRequest">
<correlations>
<correlation set="POConfirmationSet"
initiate="yes"/>
</correlations>
</reply>

Within a pick activity, you can define one or more onMessage activities and zero or more onAlarm activities. The following code sample shows how multiple onMessage activities can be used to receive either an order confirmation message or an order cancellation message.

Correlation value is evaluated and set during the process of the reply activity.

   <reply name="sendPurchaseOrder.Reply"
partnerLink="POServicePLink"
portType="pos:purchaseOrderPT"
operation="sendPurchaseOrder"
variable="purchaseOrderRequest">
<correlations>
<correlation set="POConfirmationSet"
initiate="yes"/>
</correlations>
</reply>

The onMessage activity has the same set of attributes as the receive activity. Notice also how correlations are used to route these messages to the appropriate process instance.

   <pick>
<onMessage partnerLink="POStatusPLink"
portType="ns0:POStatusPortType"
operation="confirmPO"
variable="confirmPORequest">
<correlations>
<correlation set="POConfirmationSet"
initiate="no"/>
</correlations>

<onMessage partnerLink="POStatusPLink"
portType="ns0:POStatusPortType"
operation="cancelPO"
variable="cancelPORequest">
<correlations>
<correlation set="POConfirmationSet"
initiate="no"/>
</correlations>
....
</pick>

Within a pick, the developer can also use an onAlarm activity to specify either a duration or a deadline expression. In this example, a for attribute is used to specify the duration of 100 seconds, after which an alarm will occur.

  <pick>
....
<onAlarm>
<for>'P0Y0DT100S'</for>
<sequence>
....
</sequence>
</onAlarm>
</pick>

You would use the following expression to specify a duration of 2 years, 10 months, 14 days, 7 hours, 11 minutes, and 44 seconds:

P2Y10M14DT7H11M44S

When you specify a point in time, the until attribute decides the exact date on which the alarm occurs.

A visual form of the POService  BPEL process is shown next. For implementation details, see the source files.

POService.bpel
Figure 2: The POservice BPEL Process

The following diagram illustrates the InventoryService BPEL process.

InventoryService.bpel
Figure 3: The InventoryService BPEL Process

Input Data XML for Different Scenarios

To run the scenarios, the user needs to first invoke the poServiceRequest and then call either a poRequestConfirm or poRequestCancel. Notice that the orderId value is same in all the requests.

This instance of input XML initiates a PORequest:

<soapenv:Envelope xmlns="http://manufacturing.org/xsd/purchase" 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.xmlsoap.org/soap/envelope/ http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<sendPurchaseOrder>
<purchaseOrder>
<purchaseOrder xmlns="http://manufacturing.org/xsd/purchase">
<orderId>00001234</orderId>
<customerId>999666333</customerId>
<orderDescription>OrderVal_Any_Description</orderDescription>
<price></price>
</purchaseOrder>
</purchaseOrder>
</sendPurchaseOrder>
</soapenv:Body>
</soapenv:Envelope>

This instance of input XML confirms the earlier requested purchase order:

<soapenv:Envelope xmlns="http://manufacturing.org/xsd/purchase" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:pur="http://manufacturing.org/xsd/purchase" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.xmlsoap.org/soap/envelope/ http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<pur:purchaseOrder>
<pur:orderId>00001234</pur:orderId>
<pur:customerId>999666333</pur:customerId>
<pur:orderDescription>I Want to confirm the order</pur:orderDescription>
</pur:purchaseOrder>
</soapenv:Body>
</soapenv:Envelope>

This instance of input XML cancels the earlier requested purchase order:

<soapenv:Envelope xmlns="http://manufacturing.org/xsd/purchase" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:pur="http://manufacturing.org/xsd/purchase" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.xmlsoap.org/soap/envelope/ http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<pur:purchaseOrder>
<pur:orderId>00001234</pur:orderId>
<pur:customerId>999666333</pur:customerId>
<pur:orderDescription>Naa, i will cancel the oder</pur:orderDescription>
</pur:purchaseOrder>
</soapenv:Body>
</soapenv:Envelope>

References


© Sun Microsystems 2006. All of the material in The Java BluePrints Solutions Catalog is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.