# 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.

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

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

- `pick`

- `onMessage` with correlations
- `onAlarm`

- Correlations

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:

- A purchase order service
- A purchase order confirmation service
- A purchase order cancellation service

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.

Figure 2: The `POservice` BPEL Process

The following diagram illustrates the `InventoryService` BPEL process.

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

- Browse the source code for this BluePrint, including the BPEL process files and WSDL files.
- See the BPEL BluePrint sample projects included in the NetBeans Enterprise Pack 5.5 Beta IDE.
- For general information on BPEL, see Business Process Execution Language, Part 1: An Introduction.

© 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.