# BPEL BluePrint 2

# Asynchronous Web Service Interactions Using BPEL

Kiran Bhumana, Ryan Kennedy, Shauna Pickett-Gordon

## Problem Description

Supporting asynchronous interactions between web services can be a tedious task. Since many real-world business processes often perform long-lived operations in the course of their workflow, developers have had to implement complex synchronization requirements to support these types of interactions. The common usage pattern is to match the asynchronous response with the corresponding request that was sent earlier.

This document focuses on implementing asynchronous interactions between web services by leveraging key aspects of the Business Process Execution Language (BPEL).

## Solution

Using BPEL to describe long-running business interactions between partner web services, a developer can more easily support the asynchronous characteristics of a business process.

This solution demonstrates the following aspects:

- A BPEL process that provisions a synchronous operation
- A BPEL process that provisions an asynchronous operation
- A BPEL process that consumes an asynchronous operation on a partner web service
- Declarative coordination constructs that BPEL requires for the asynchronous request and response
- General design aspects to be considered when using asynchronous patterns, and how they are achieved in BPEL

### Provisioning a Synchronous Operation

See BluePrint 1, Synchronous Web Services Interactions Using BPEL.

### Provisioning an Asynchronous Operation

An asynchronous operation involves two in-only WSDL operations, which together make a request-response combination. BPEL defines an `invoke` activity to consume an in-only service. To enable provisioning of the in-only service, BPEL defines the `receive` and `pick-onMessage` constructs.

BPEL defines `correlation` constructs that declaratively provide the matching capability. Also, WSDL extension elements `propertyAlias` and `property` are used to define the correlation values.

Business processes are usually long-running, and the orchestration of web services is primarily asynchronous. It is important to combine the asynchronous consumption of services with timer-based constructs so that a consumer of a web service doesn't wait indefinitely for a response. The `pick-onAlarm` construct defined in BPEL helps the developer achieve this functionality.

From defining relationships and specific roles between partner services, to handling the asynchronous response associated with a request, using BPEL to describe a business process alleviates the need to implement many of the complex synchronization requirements involved when supporting asynchronous interactions.

You'll need to consider certain design details when you use the Business Process Execution Language (BPEL) to describe the following:

- An executable business process that provisions one or more synchronous operations
- An executable business process that provisions one or more asynchronous operations
- An executable business process that consumes one or more asynchronous operations

Provisioning synchronous operations (also called request-response or in-out operations) involves receiving a message and replying with a message defined by the web service.

Provisioning and consuming asynchronous operations involves two in-only WSDL operations: a request-response combination. BPEL defines the `invoke` activity to consume an in-only operation, and defines `receive` and `pick-onMessage` as provisioning the in-only operation.

## Design Details

When designing a business process that incorporates asynchronous web service interactions, the following constructs are needed.

- `partnerLinks` representing partner web services
- `variables` that store data exchanged between web services
- An `invoke` activity to consume a service
- A `receive` activity to provide a service
- A `pick-OnMessage` construct to provide the service for the asynchronous response
- A `pick-OnAlarm` construct to provide for the alternative timer path
- Input and output data mapping to achieve some meaningful business logic

The following solution shows how to create and use the BPEL artifacts to both provision and consume synchronous and asynchronous web service operations. First, an external client consumes a synchronous operation provided by a BPEL process. Then, this BPEL process consumes an asynchronous operation provided by another BPEL process. The solution is depicted here.

Figure 1: Asynchronous Message Exchanges in a BPEL Process

### Business Logic of the Services

Two web services are involved here: a purchase order service, `POService`, which is consumed by an external client through SOAP over HTTP; and an inventory check service, `InventoryService`, consumed by the BPEL process that provisions the purchase order service. Both `POService` and `InventoryService` are implemented as BPEL services.

The business process that provisions the purchase order service, upon receiving the request, checks with the inventory by calling `InventoryService`. The business process that provisions the inventory check service verifies whether the requested order is available and sends a status of the inventory asynchronously. Based on the asynchronous status returned by `InventoryService`, `POService` returns either a fault or a valid response to the HTTP client.

Correlation is used to route the messages from `InventoryService` to the proper executing instances of `POService`. The value of `orderID` in the `purchaseOrder` message is used as the correlation identifier.

### Design of Correlation Values

A response that is sent back asynchronously to the requester must be routed to the correct business process instance. To make this match, BPEL uses unique, embedded correlation tokens within the application data (application-level routing), instead of enforcing additional routing information. The location and type of correlation tokens are statically declared in the business process. The developer must enforce unique constraints and make sure that, at execution, unique values are maintained for the life of the business process.

An instance of correlation in BPEL is defined on a property, and, in turn, on a property alias. `propertyAlias` points to a unique ID in the received message. See Important Artifacts Defined in BPEL and WSDL for details.

Correlation tokens are defined in the BPEL process `POservice`. A unique correlation ID is associated with every instance of `POService` that is created in the execution environment. The correlation token is initialized when the `POService` BPEL process invokes the `inventoryService` process; the token is associated with the instance of `POService`.

The callback from `inventoryService` is received by the `onMessage` branch of the `pick` activity. When the asynchronous `inventoryStatus` message is received, BPEL uses `xpath` to evaluate the `propertyAlias` defined on the `inventoryStatus` message, obtains the `correlationSet` value, and routes the message to the appropriate instance of the business process.

### Aspects of BPEL Design for Consuming Asynchronous Operations

Provisioning asynchronous operations requires a timer-based alternative execution path. If the inventory status is not received within a specified period of time, the purchase order service goes ahead with its timer execution path, and returns a fault to its consumer. Here are some possible reasons for a callback's failure:

- The partner implementation failed
- It took too long for the partner to execute the service
- There were not enough resources for the partner to execute the service on time

These failures can't be propagated to a `POService` process instance that is waiting for a callback from the `inventoryService` BPEL process instance: Hence, the necessity of a timer-based path. After a timeout in the `POService` process, if messages messages with the old correlation token ID arrive from the inventory service, these late messages are not consumed by the `POService` process instance, and a fault is sent to the consumer of the service--that is, the `inventoryService` process.

### Important Artifacts Defined in BPEL and WSDL

The `InventoryService` WSDL file defines a `partnerLinkType` with two roles: `inventoryService` and `inventoryServiceRequester`.

- The `inventoryService` role refers to the `inventoryService` operation through the `portType` called `inventoryPortType`.
- The `inventoryServiceRequester` role refers to the `inventoryServiceResponse` operation through `inventoryServiceCallbackPortType`.

The `inventoryService` operation expects a `purchaseOrder` message, and `inventoryServiceResponse` expects an `InventoryMessage`.

        <plink:partnerLinkType name="inventoryRequestingLT">

            <plink:role portType=tns:"inventoryPortType"
                        name="inventoryService"></plink:role>
            <plink:role portType="tns:inventoryServiceCallbackPortType"
                        name="inventoryServiceRequester"></plink:role>
        </plink:partnerLinkType>

        <portType name="inventoryPortType">
            <operation name="inventoryService">

                <input name="purchaseOrder"
                       message="tns:POMessage"></input>
            </operation>
        </portType>

        <portType name="inventoryServiceCallbackPortType">
            <operation name="inventoryServiceResponse">

                <input name="inventoryResponse"
                       message="tns:InventoryMessage"></input>
            </operation>
        </portType>

The `POService` BPEL process defines a `partnerLink` called `inventoryRequesting`. This partnerlink's role is to consume the service `inventoryService. I`ts partner's role is to consume the service `inventoryServiceResponse`.

            <partnerLink name="inventoryRequesting"
                         partnerLinkType="invs:inventoryRequestingLT"
                         myRole="inventoryServiceRequester"
                         partnerRole="inventoryService"/>

On the other hand, the `inventoryService` BPEL process defines a `partnerLink` called `inventoryServicing` , whose role is to provide the service `inventoryService`. Its partner's role is to provide `inventoryServiceResponse`.

            <partnerLink name="inventoryServicing"
                         partnerLinkType="invs:inventoryRequestingLT"
                         myRole="inventoryService"
                         partnerRole="inventoryServiceRequester"/>

The `inventoryService` WSDL file declares the properties `orderID` and `propertyAlias` on `POMessage` and `InventoryMessage`, which are defined, respectively, on the operations `inventoryService` and `inventoryServiceResponse`. The value of `orderID` is designed to be of `xsd:int` value. Property is an abstract concept, while `propertyAlias` is the corresponding concrete aspect. The property aliases tie the property to a value defined in the web service message using an `xpath` query or a similar technology. This much-needed indirection decouples the abstract from the concrete.

        <bpws:property name="orderID"
                       type="xsd:int"/>

        <bpws:propertyAlias propertyName="tns:orderID"
                            messageType="tns:POMessage"
                            part="purchaseOrder">
            <bpws:query>/purchaseOrder/orderId</bpws:query>
        </bpws:propertyAlias>

        <bpws:propertyAlias propertyName="tns:orderID"
                            messageType="tns:InventoryMessage"
                            part="inventoryPart">
            <bpws:query>/inventory/orderId</bpws:query>
        </bpws:propertyAlias>

The `POService` process defines a correlation set on this property.

        <correlationSets>
            <correlationSet name="POCorrelationSet"
                            properties="invs:orderID"/>
        </correlationSets>

The `POService` process uses a one-way `invoke` operation--signaled by the fact that there is no `outputVariable` for this invoke activity. Correlation is also initialized here, and when the `invoke` is executed, a unique ID is associated with the `POService` process instance.

            <invoke name="inventoryService"
                    partnerLink="inventoryRequesting"
                    portType="invs:inventoryPortType"
                    operation="inventoryService"
                    inputVariable="inventoryServiceRequest">
                <correlations>
                    <correlation set="POCorrelationSet"
                                 initiate="yes"/>
                </correlations>
            </invoke>

`POService` also defines a `pick` activity. This activity has an `OnMessage` branch to consume the asynchronous response from the inventory, and it has an `onAlarm` to fall back in some unforeseen conditions.

            <onMessage partnerLink="inventoryRequesting"
                           portType="invs:inventoryServiceCallbackPortType"
                           operation="inventoryServiceResponse"
                           variable="inventoryServiceReply">

                    <correlations>
                        <correlation set="POCorrelationSet"
                                     initiate="no"/>
                    </correlations>
            </onMessage>

            <onAlarm>
                    <for>'P0Y0DT300S'</for>
    	</onAlarm>

Notice the usage of the correlation on `onMessage`. The initiate value gives a hint either to associate the correlation ID with the instance, or that a message with the correlation ID should be routed to the instance. In this situation, when a message arrives that is to be consumed by the `pick-onMessage`construct, the message needs to be routed to the appropriate `POService` process instance.

The `inventoryService` BPEL process uses a `receive` activity construct to provide a one-way inventory service. It uses a one-way `invoke` for the call-back functionality, and sends the `inventoryService` response to the `POService`.

            <receive name="inventoryService"
                     partnerLink="inventoryServicing"
                     portType="invs:inventoryPortType"
                     operation="inventoryService"
                     variable="inventoryServiceVar"
                     createInstance="yes">
            </receive>

            <invoke name="inventoryServiceResponse"
                    partnerLink="inventoryServicing"
                    portType="invs:inventoryServiceCallbackPortType"
                    operation="inventoryServiceResponse"
                    inputVariable="inventoryServiceResponseVar">
            </invoke>

The visual form of the `InventoryService` BPEL process is shown next. For implementation details, see the source files.

Figure 2: The InventoryService BPEL Process

The POService BPEL process is illustrated below.

Figure 3: The POService BPEL Process

### Schema

The code for ```purchaseorder.schema` is as follows.

    <?xml version="1.0" encoding="UTF-8"?>

    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
         targetNamespace="http://manufacturing.org/xsd/purchase"
         xmlns:tns ="http://manufacturing.org/xsd/purchase"
         elementFormDefault="qualified" attributeFormDefault="unqualified">

      <xs:element name="purchaseOrder" type="tns:purchaseOrderType">
      </xs:element>
      <xs:complexType  name="purchaseOrderType">
         <xs:sequence>

            <xs:element name="orderId" type="xs:int"/>
            <xs:element name="customerId" type="xs:int" />

            <xs:element name="orderDescription" type="xs:string" />
            <xs:element name="price" type="xs:double" />

         </xs:sequence>
      </xs:complexType>
    </xs:schema>

Next is the `inventoryservice.schema` code.

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"

         targetNamespace="http://manufacturing.org/xsd/inventory"
         xmlns:tns ="http://manufacturing.org/xsd/inventory"
         elementFormDefault="qualified" attributeFormDefault="unqualified">
      <xs:element name="inventory" type="tns:inventoryType">

      </xs:element>
      <xs:complexType  name="inventoryType">
         <xs:sequence>
            <xs:element name="orderId" type="xs:int"/>

            <xs:element name="inventoryStatus" type="xs:boolean"/>
            <xs:element name="inventoryStatusMessage" type="xs:string" />

         </xs:sequence>
      </xs:complexType>
    </xs:schema>

The `orderId` element in the `purchaseOrderType` and `inventoryType` is an important part of the message data. The value of this element provides the unique ID for the correlations used in the BPEL processes. See the definitions of correlations, `property`, and `propertyAlias`.

### Input Data XML

The following input XML instance gives a valid response.

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:pur="http://manufacturing.org/wsdl/purchase">
      <soapenv:Body>
        <pur:sendPurchaseOrder>
          <purchaseOrder>

            <orderId>1234</orderId>
    	  <customerId>9876</customerId>
    	  <orderDescription>OrderVal_Any_Description</orderDescription>
    	  <price></price>

          </purchaseOrder>
        </pur:sendPurchaseOrder>
      </soapenv:Body>
    </soapenv:Envelope>

The following input XML instance causes a `cannotCompleteOrder` fault to be thrown to the client.

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:pur=http://manufacturing.org/wsdl/purchase">
      <soapenv:Body>
        <pur:sendPurchaseOrder>
          <purchaseOrder>

            <orderId>1234</orderId>
    	  <customerId>9876</customerId>
    	  <orderDescription>SomeVal_OrderVal_Any_Description</orderDescription>
    	  <price></price>

          </purchaseOrder>
        </pur:sendPurchaseOrder>
      </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 details on correlation, refer to the BPEL specification.

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