Section 5.2. BPEL Example


5.2. BPEL Example

The best way to learn a language is to dive into it.This section provides an extended example to illustrate some of the main elements of the BPEL language. The BPEL process in Example 5-1, which is similar to that presented in Chapter 10 (and also described in the discussion of state machines in Chapter 3), manages the processing of an insurance claim.

Example 5-1. BPEL example: InsuranceClaim.bpel
 1    <process name="InsuranceClaim" 2       targetNamespace="http://acm.org/samples" 3       suppressJoinFailure="yes" 4       xmlns:tns=http://acm.org/samples 5       xmlns=http://schemas.xmlsoap.org/ws/2003/03/business-process/ 6       xmlns:xsd=http://www.w3.org/2001/XMLSchema 7       xmlns:addressing=http://schemas.xmlsoap.org/ws/2003/03/addressing 8       xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/"> 9 10       <!-- 11          Partners in the process: 12            client - app that can initiate and kill 13            worklist - service that manages manual activities 14       --> 15       <partnerLinks> 16          <!-- 17          <partnerLink name="client" partnerLinkType="tns:InsuranceClaim" 18             myRole="InsuranceClaimProvider"/> 19          <partnerLink name="worklist" partnerLinkType="task:TaskManager" 20             partnerRole="TaskManager" myRole="TaskManagerRequester"/> 21       </partnerLinks> 22 23       <!-- Process-level variables --> 24       <variables> 25          <variable name="status" type="xsd:string"/> 26          <variable name="initiateMsg" messageType="tns:InsuranceClaimMsg"/> 27          <variable name="killEv" messageType="tns:InsuranceClaimMsg"/> 28          <variable name="taskResponse" messageType="task:taskMessage"/> 29       </variables> 30 31       <!-- Message correlation to be performed on the ClaimID field --> 32       <correlationSets> 33          <correlationSet name="claim" properties="tns:claimID"/> 34       </correlationSets> 35 36       <!-- Catch any errors and fix manually --> 37       <faultHandlers> 38          <catchAll> 39             <empty name="PlaceholderForManualFix"/> 40          </catchAll> 41       </faultHandlers> 42 43       <!-- Globally receive a kill event (correlated with the claim ID from the 44            original initate) and terminate the process. --> 45       <eventHandlers> 46          <onMessage partnerLink="client" portType="tns:InsuranceClaim" 47             operation="kill" variable="killEv"> 48             <correlations> 49                <correlation set="claim" initiate="no"/> 50             </correlations> 51             <sequence> 52                <empty/><!-- Do something, like notify internal systems of kill --> 53                <terminate name="killClaim"/> 54             </sequence> 55          </onMessage> 56       </eventHandlers> 57 58       <sequence> 59 60          <!-- We start with a receive activity: get the initiate message. Will 61             correlate on claim set defined earlier 62          --> 63          <receive partnerLink="client" portType="tns:InsuranceClaim" 64             operation="initiate" variable="initiateMsg" createInstance="yes" 65             name="initiateEvent"> 66             <correlations> 67                <correlation set="claim" initiate="yes"/> 68             </correlations> 69          </receive> 70 71          <!-- Let an agent evaluate it. Call worklist partner to do this --> 72          <invoke name="evalClaim" partnerLink="worklist"  portType="task:TaskManager" 73            operation="evalClaim" inputVariable="initiateMsg"/> 74 75          <!-- Get either the response or a timeout --> 76          <pick name="analyzePick"> 77             <onMessage partnerLink="worklist" portType="task:TaskManagerCallback" 78                operation="onTaskResult" variable="taskResponse"> 79                <!-- From response extract status and set to variable 'status' --> 80                <assign name="setStatus"> 81                   <copy> 82                      <from variable="taskResponse" part="payload" 83                         query="/tns:taskMessage/tns:result="/> 84                      <to variable="status"/> 85                   </copy> 86                </assign> 87             </onMessage> 88             <!-- Timeout! 10 days have passed. Escalate --> 89             <onAlarm for="PT10D"> 90                <sequence> 91                   <!-- Call partner service to escalate --> 92                   <invoke name="evalClaim" partnerLink="worklist" 93                      portType="task:TaskManager" operation="escalateClaim" 94                      inputVariable="initiateMsg"/> 95                   <!-- Get the escalation response --> 96                   <receive name="receiveTaskResult" partnerLink="worklist" 97                      portType="task:TaskManagerCallback" 98                      operation="onTaskResult" variable="taskResponse"/> 99                 <!-- From response extract status and set to variable 'status' --> 100                   <assign name="setStatus"> 101                      <copy> 102                         <from variable="taskResponse" part="payload" 103                            query="/tns:taskMessage/tns:result="/> 104                         <to variable="status"/> 105                      </copy> 106                   </assign> 107                </sequence> 108             </onAlarm> 109          </pick> 110 111          <!-- Look at result of claim process and act accordingly: 112               'rejected' and 'accepted' are good. Anything else, throw a fault --> 113          <switch name-"resultEval"> 114             <case condition="bpws:getVariableData('status')='rejected'"> 115                <empty> <!-- perform rejection actions --> 116             </case> 117             <case condition="bpws:getVariableData('status')='accepted'"> 118                <empty> <!-- perform acceptance actions --> 119             </case> 120             <otherwise> 121                <throw name="illegalStatus" faultName="illegalStatus"/> 122             </otherwise> 123          </switch> 124       </sequence> 125    </process> 

The underlying business logic for this process is straightforward: when a claim arrives, an agent evaluates it and determines whether to accept or reject it. If the agent does not respond within 10 days, the activity is escalated to a manager, who then makes an accelerated accept/reject decision. At any point, the processing can be terminated with a kill event.

The code implementing this logic is an XML document with root element process; from that element, we learn that the name of the process is InsuranceClaim (line 1). The heart of the process is the sequence activity in lines 58-124, which in turn contains a set of child activities and runs them sequentially. In this example , those children are a receive activity (lines 63-69), an invoke activity (lines 72-73), a pick activity (lines 76-109), and a switch activity (lines 113-123).

The purpose of the receive activity (lines 63-69) is to listen for an inbound message containing the claims request. The process, as you will see, has a WSDL interface and implements a web service interface; the receive represents an inbound operation of that service (in this case, initate, as stated in line 64). The attribute createInstance="yes" in line 64 means that this receive activity is the trigger that starts the process.

In the invoke activity in lines 72-73, the process calls a web service operation, offered by another partner (in this example, operation evalClaim for partner worklist), to evaluate the claim. The partner service chooses an insurance agent to evaluate the claim. Several days might pass before the agent makes a decision about the claim, but the invoke call is asynchronous; it returns immediately, and the process waits for a response in the pick in lines 76-109.

The pick activity waits for one of two events to occur: the response from the worklist (handled by the onMessage element in lines 77-87) or a timeout (in onAlarm in lines 89-108). In the former case, the response arrives as another inbound message; the worklist service calls back the process by invoking its onTaskResult operation (line 78). The assign activity in lines 80-86 extracts the result field from the worklist message and copies it into a process variable called status (declared in the variables section in line 25), which is used later in the process as a decision point for acceptance or rejection processing.

CORRELATION METHOD 1: WS-ADDRESSING

How does the process correlate the response with the request made in the invoke? In other words, how can the process be sure that the response is for the right insurance claim? The answer, in this case, is the WS-Addressing standard : when the process sends a request to the worklist, it embeds a unique message ID into the SOAP header; when the worklist responds, it passes back that ID. The logic is handled at the web services container level, transparent to the BPEL code.

The BPEL specification does not require that the container support WS-Addressing. To use this method of correlation, check the capabilities of your BPEL platform. This example was test on Oracle's BPEL Process Manager, which encourages the WP-Addressing approach.


The timeout occurs after 10 days, an interval determined by the condition for="PT10D" in line 89. The timeout triggers escalation: if, after ten days, no response has arrived from the worklist on the original claim request, the process uses an invoke to call the worklist's escalateClaim service operation (lines 92-94). Like the earlier invoke, this call is asynchronous. The receive activity in lines 96-98 waits for the result, which might take several hours or days to arrive. The assign in lines 100-106 captures the result in the status variable.

Finally, the switch activity in lines 113-132 is an exclusive-OR construct that performs either acceptance or rejection logic based on the value of the status variable, which records the result returned by the worklist. The acceptance case is handled in lines 114-116; its logic (not shown in the code example for brevity) probably involves sending an acceptance letter and a check to the subscriber. The rejection handler in lines 117-119 may involve sending a rejection letter. If the result is neither an accept nor a reject (the otherwise case in lines 120-122), the activity throws a fault called illegalStatus, which triggers the faultHandler in lines 37-42. The handler in this example does very little, but it can have arbitrarily complex exception handling logic.

The requirement to kill the claim at any point is met by the eventHandlers construct in lines 45-56. The onMessage handler listens on the inbound kill web service operation (lines 46-47), using a BPEL correlation set (lines 48-50) to ensure that the kill event is for the same claim as the one under consideration in this instance of the process. The event handler explicitly terminates the process using the terminate activity in line 53.

CORRELATION METHOD 2: BPEL CORRELATION SET

Unlike WS-Addressing, which matches IDs in the message header, BPEL's correlation mechanism matches particular data fields embedded in the message body. The receive activity in lines 63-69 populates a correlation set, to be used for subsequent correlations, with data embedded in its message. In the kill event handler, the data from the kill event is compared with the data in the correlation set; if it matches, the kill event is processed; if it does not match, the kill event is rejected.


The partnerLinks element, in lines 15-21, specifies the web service interface offered by the process, as well as interfaces that are used by the process. Two partner links are listed: client represents the interface implemented by the process, which includes the inbound operations to initiate and kill a claim. The client interface is specified in a WSDL, a portion of which is displayed here:

        <portType name="InsuranceClaim">           <operation name="initiate">              <input message="tns:InsuranceClaimMsg"/>           </operation>           <operation name="kill">              <input message="tns:InsuranceClaimMsg"/>           </operation>        </portType>        <plnk:partnerLinkType name="InsuranceClaim">           <plnk:role name="InsuranceClaimProvider">              <plnk:portType name="tns:InsuranceClaim"/>           </plnk:role>        </plnk:partnerLinkType> 

The WSDL includes the definition of a partnerLinkType called InsuranceClaim, which defines a role called InsuranceClaimProvider, which maps to the port type InsuranceClaim, which in turn defines the initiate and kill operations. The client partner link supports the InsuranceClaimProvider role, implying that it implements the kill and initiate operation of that role's port type.

The worklist partner link is a service that this process calls to evaluate and escalate the claim; worklist calls the process back with results. The WSDL for worklist has the following port types and partner link types:

        <portType name="TaskManager">           <operation name="evalClaim">              <input message="tns:taskMessage"/>           </operation>           <operation name="escalateClaim">              <input message="tns:taskMessage"/>           </operation>        </portType>        <portType name="TaskManagerCallback">           <operation name="onTaskResult">              <input message="tns:taskMessage"/>           </operation>        </portType>        <plnk:partnerLinkType name="TaskManager">           <plnk:role name="TaskManager">              <plnk:portType name="tns:TaskManager"/>           </plnk:role>           <plnk:role name="TaskManagerRequester">              <plnk:portType name="tns:TaskManagerCallback"/>           </plnk:role>        </plnk:partnerLinkType> 

The expression myRole="TaskManagerRequester" in line 20 of the process means that the process implements the TaskManagerCallback service, which defines an onTaskResult operation. The expression partnerRole="TaskManager" means that the worklist partner implements the port type TaskManager with operations evalClaim and escalateClaim.



    Essential Business Process Modeling
    Essential Business Process Modeling
    ISBN: 0596008430
    EAN: 2147483647
    Year: 2003
    Pages: 122
    Authors: Michael Havey

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net