6.2. BPMLBPML is an XML process definition language that, like BPEL, describes the structural representation of a process and the semantics of its execution. As with BPEL, the vision of BPML is to run XML processes on an engine element by element, according to precisely defined semantics. The code of a BPML processladen with familiar constructs such as loops, decisions, parallel paths, variables, and structured exception handlingis readily understood by a programmer. 6.2.1. BPML ExampleOnce again, the best way to start learning a new language is to dive into an example . Example 6-1 demonstrates several features of BPML, including event-driven processes, context, properties, schedules, exception processes, fault handlers, compensation, and several activity types. Example 6-1. BPML sample: placing an order1 <wsdl:message name="requestMessage"> 2 <wsdl:part name="details" element="type:orderDetails"/> 3 </wsdl:message> 4 5 <wsdl:message name="requestAck"> 6 <wsdl:part name="orderID" element="type:orderID"/> 7 <wsdl:message> 8 9 <wsdl:message name="cancelMessage"> 10 <wsdl:part name="orderID" element="type:orderID"/> 11 <wsdl:message> 12 13 <wsdl:message name="requestComplete"> 14 <wsdl:part name="orderID" element="type:orderID"/> 15 </wsdl:message> 16 17 <wsdl:portType name="requesterService"> 18 <wsdl:operation name="onComplete"> 19 <wsdl:input name="requestComplete"/> 20 </wsdl:operation> 21 </wsdl:portType> 22 23 <wsdl:portType name="serverService"> 24 <wsdl:operation name="request"> 25 <wsdl:input name="requestMessage"/> 26 <wsdl:output name="requestAck"/> 27 </wsdl:operation> 28 <wsdl:operation name="cancel"> 29 <wsdl:input name="cancelMessage"/> 30 </wsdl:operation> 31 </wsdl:portType> 32 33 <!-- BPML main process is called orderProcess. It is started by the action 34 "receiveOrder below. --> 35 <bpml:process name="orderProcess"> 36 <bpml:event activity="receiveOrder"/> 37 38 <!-- The context element defines an exception handler and a fault handler for 39 the main process. --> 40 <bpml:context> 41 <bpml:property name="orderID"/> 42 <bpml:property name="details"/> 43 <bpml:property name="timeLimit" type="xsd:duration"/> 44 45 <!-- Set a timer. When it expires, generate a fault to trigger the 46 fault handler --> 47 <bpml:schedule name="timeToComplete" code="tns:timeout" 48 duration="timeLimit"/> 49 50 <!-- Handle a cancellation event here --> 51 <bpml:exception name="cancelRequest"> 52 <bpml:event activity="receiveCancelRequest"/> 53 54 <bpml:action name="receiveCancelRequest" portType="serverService" 55 operation="cancel" correlate="orderID"> 56 <bpml:input element="orderID" property="orderID"/> 57 </bpml:action> 58 59 <bpml:empty/> <!--placeholder for exception processing --> 60 </bpml:exception> 61 62 <!-- Handle faults here, specifically a timeout in the schedule defined 63 above --> 64 <bpml:faults> 65 <bpml:case code="tns:timeout> 66 <bpml:empty/> <!-- placeholder for exception processing --> 67 </bpml:case> 68 </bpml:faults> 69 </bpml:context> 70 71 <!--- Step 1 of process: This action starts the process, responding to the web 72 service operation request on the portType serverService, accepting as input 73 "details" and returning "orderID". --> 74 <bpml:action name="receiveOrder" portType="serverService" operation="request"> 75 <bpml:input element="details" property="details"/> 76 <bpml:output element="orderID"> 77 <bpml:source property="orderID"/> 78 </bpml:output> 79 <bpml:assign property="orderID" xpath="func:newIdentifier('orderID')"/> 80 </bpml:action> 81 82 <!-- Step 2: call the subprocess "chargeCustomer" passing in "details" --> 83 <bpml:call process="chargeCustomer"> 84 <bpml:output parameter="details"> 85 <bpml:source property="details"/> 86 </bpml:output> 87 </bpml:call> 88 89 <!-- Step 3: call the subprocess "shipProduct" passing in "details" --> 90 <bpml:call process="shipProduct"> 91 <bpml:output parameter="details"> 92 <bpml:source property="details"/> 93 </bpml:output> 94 </bpml:call> 95 96 <!-- Step 4: invoke the callback web service "onComplete" of the requester, 97 sending back the orderID --> 98 <bpml:action name="notifyComplete" portType="requestService" 99 operation="onComplete"> 100 <bpml:output element="orderID"> 101 <bpml:source property="orderID"/> 102 </bpml:output> 103 </bpml:action> 104 105 <!-- If we need to revert the main process after it has run, then just 106 compensate the "chargeCustomer" process --> 107 <bpml:compensation> 108 <bpml:event activity="receiveCancelRequest"/> 109 <bpml:action name="receiveCancelRequest" portType="serverService" 110 operation="cancel" correlate="orderID"> 111 <bpml:input element="orderID" property="orderID"/> 112 </bpml:action> 113 <bpml:compensate process="chargeCustomer"/> 114 </bpml:compensation> 115 </bpml:process> Example 6-1, adapted from two of the examples presented in the BPML 1.0 specification,[*] begins when the main process receives a receiveOrder event (lines 74-80); it immediately responds to the caller with a generated order ID (line 76, which gets its value from line 79). The mainline processing that follows consists of successive calls to subprocesses chargeCustomer (lines 83-87) and shipProduct (lines 90-94), followed by the sending of a completion event to the caller (lines 98-103).
The compensation process in lines 107-114, executed if a cancellation event is received sometime after the process has completed, triggers the compensation of the process chargeCustomer, so that the charge made earlier will be rescinded. If the cancellation event is received while the process is active, the exception handler process (lines 51-60) defined in the context is launched. Also in the context is a scheduled event (lines 47-48), that on expiry trigger the fault tns:timeout in the fault handler in lines 64-68. The WSDL elements required by the process are defined in lines 1-31. 6.2.2. BPML in a NutshellThe following sections examine the essential language constructs that designers will need to create a BPML process: the basic process structure, variables and assignments, exception handling and compensation, split and join, loops, participant exchange, transactions, and extensions. 6.2.2.1 Basic process structure: start, end, activities, sequenceBPML processes are enveloped in a package. Each process has a name, a set of activities, and optionally, a compensation handler. A process can have subprocesses, as well as a context, which in turn can contain fault handlers, exception processes, subprocesses, and properties. Context is hierarchical: if activity set B is a child of activity set A, the context of B inherits from the context of A. There are three ways to start a process: through an activity, a message, or a signal. A process starts from an activity when it is called from another process using the spawn, call, or compensate activities, or the process is launched from the BPML scheduler according to a predefined timed event. In the following code sample, the process activity_start accepts two input parameters (i1 and i2, the first of which is required) and returns one output parameter (o1). When it is started, the process executes its main logic in the sequence statement. <process name="activity_start"> <parameters> <input name="i1" required="true"/> <input name="i2" required="false"/> <output name="o1" /> </parameters> <sequence> main body here </sequence> </process> A process starts from a message if it receives one or more messages from a web service. The process can be configured to start when any one of the messages arrives, or only when all arrive. For a message-triggered process, the event element is populated with the list of action activities representing web service calls into the process and an exclusive flag that is true if only one event is required and false otherwise. For example, the or_event process in the following code sample is triggered by either event ev1 or event ev2. The event ev1 occurs when the method method1 is called on the service with port type myService; ev2 occurs when method2 is called. The and_event process is similar, except that it requires both ev1 and ev2 to occur before beginning. In each example, the main logic begins with the sequence statement. <process name="or_event"> <event activity="ev1 ev2" exclusive="true"/> <action name="ev1" portType="myService" operation="method1"/> <action name="ev2" portType="myService" operation="method2"/> <sequence> main body here </sequence> </process> <process name="and_event"> <event activity="ev1 ev2" exclusive="false"/> <action name="ev1" portType="myService" operation="method1"/> <action name="ev2" portType="myService" operation="method2"/> <sequence> main body here </sequence> </process> A process starts from a signal if it receives one or more raised signals from within its context from another process using the raise activity. The process can be configured to trigger when any one of the signals arrives, or only when all arrive. Setting this up in the XML code is similar to setting up message-based starts, except that the event list refers to synch rather than action activities. In the next example, the process or_signal is started when either signal s1 or signal s2 is raised by another process: <process name="or_signal"> <event activity="s1 s2" exclusive="true"/> <synch signal="s1"/> <synch signal="s2"/> <sequence> main body here </sequence> </process> A basic BPML process that executes A, B, and C in sequence resembles the following: <process name="EZProcess"> <event activity="A" /> <action name="A" . . . /> <action name="B" . . . /> <action name="C" . . . /> </process> 6.2.2.2 Variables and assignmentsBPML variables are called properties, which can be declared at the scope of a package or a context. A property has an XML-schema-based type and can have an initial value. In the following code sample, the variable x has initial value 1: <property name="x" type="xsd:int"> <value>1</value> </property> The assign activity sets the value of a property, as in the following case, where it increments the value of x by 1: <assign property="x"> <value>x + 1</value> </assign> The language used to read and modify property content is XPath. 6.2.2.3 Exception handling and compensationBPML has three error handling approaches:
6.2.2.4 Split and joinThe all activity executes a set of actions in parallel and merges its results. This activity is sometimes called the AND split and join. In the following sample, actions a, b, and c are executed in parallel; when the last of them completes the process continues with its next step: <all> <action name="a"> ... </action> <action name="b"> ... </action> <action name="c"> ... </action> </all> The switch activity, sometimes called the XOR split and join, executes exactly one action from a set. Inside the switch activity is a sequence of case statements, each of which has a condition and associated activity. The activity to be executed is the one defined in the first case statement whose condition evaluates to true. If no case's condition is true, the activity belonging to the default case is run. The following sample illustrates this behavior: <switch> <case> <condition>$tns:val>100</condition> <action name="a"> ... </action> </case> <case> <condition>$tns:val>50 and $tns:val<100</condition> <action name="b"> ... </action> </case> <default> <action name="c"> ... </action> </case> </switch> 6.2.2.5 LoopsBPML supports three types of loops, each defined as a complex activity type: while, until, and foreach. while executes a set of activities zero or more times, checking a Boolean-valued condition at the beginning of the loop to determine whether to continue. until is similar, but it checks the condition at the end of the loop. foreach loops through a list of items, executing a set of activities for each item in the list. The following while loop runs five times, when the value of the property myCounter is from 0 and 4 (inclusive): <process name="WhileSample"> <context> <property name="myCounter" type="xsd:integer"> <value>0</value> </property> </context> <while> <condition>myCounter < 5</condition> <assign property="myCounter"> <value>myCounter + 1</value> </assign> <empty> <!--placeholder for real work à </while> </process> The foreach loop in the next sample iterates over the list myList, gathering values 0, 2, 5, and 7 over the course of its iterations. The built-in property inst:current is set to the current position in the list in a given iteration of the loop. <process name="ForEachSample"> <context> <property name="myList"> <value>0 2 5 7</value> </property> </context> <foreach select="myList"> <assign property="nextItem"> <value>$inst:current</value> </assign> <empty> <!--placeholder for real work à </foreach> </process> 6.2.2.6 Participant exchangeA BPML process can exchange messages with external participants through web services in its action and choice activities. action can either call a web service or implement a web service that, when called, triggers an event in the process. Whereas BPEL cleanly separates these operations into invoke, receive, and reply. BPML overloads the action activity to serve all three purposes. An action is specified with a name, a WSDL port type and operation, a set of inputs and/or outputs (mapping to WSDL input and output messages types, respectively, for the given operation), and an optional correlation expression, which filters action events to trigger only for given input values. Several examples of action are provided in Example 6-1. choice, similar to BPEL's pick, waits for exactly one of two or more events to occur, where each event is defined as an action activity, a synch activity, or a delay activity. action events in this case are asynchronous receives. Each candidate event has a set of activities defined that are executed if the event fires. Syntactically, choice consists of a set of event elements, each of which contains an activity set that begins with an action, synch, or delay. In the following code sample, the process waits for either events A or B or a timeout to occur: <choice> <event> <action portType="myService" operation="A"/> <empty/> <!-- placeholder --> </event> <event> <action portType="myService" operation="B"/> <empty/> <!-- placeholder --> </event> <event> <delay duration="maxResponseTime"/> <empty/> <!-- placeholder --> </event> </choice> 6.2.2.7 TransactionsBPML is interoperable with open transaction standards such as WS-Transaction and XA. BPML defines a special fault type, bpml:rollback, that a process can use to trigger rollback handlers . 6.2.2.8 ExtensionsBPML supports adding custom attributes or elements to most of its elements. Using the extension mechanism to add Java support (e.g., data types and invocations) would be a useful idea. 6.2.3. BPML and PatternsRated on its support for the 20 process patterns described in Chapter 4, BPML gets an average grade. According to the evaluation by members of the P4,[6] BPML directly supports 11 patterns, and indirectly supports 1. The remaining 8 patterns are either impossible or difficult to implement. Table 6-9 summarizes the results.
|