11 Using Conditional Branching in a BPEL Process
This chapter includes the following sections:
11.1 Introduction to Conditional Branching
BPEL applies logic to make choices through conditional branching. You can use the following activities to design your code to select different actions based on conditional branching:
-
If activity (in a BPEL version 2.0 project)
Enables you to use an if activity when conditional behavior is required for specific activities to decide between two or more branches. The if activity replaces the switch activity that appeared in BPEL 1.1 processes. For information about how to create if activities, see Defining Conditional Branching with the If Activity in BPEL 2.0.
-
Switch activity (in a BPEL version 1.1 project)
Enables you to set up two or more branches, with each branch in the form of an XPath expression. If the expression is true, then the branch is executed. If the expression is false, then the BPEL process service component moves to the next branch condition, until it either finds a valid branch condition, encounters an otherwise branch, or runs out of branches. If multiple branch conditions are true, then BPEL executes the first true branch. For information about how to create switch activities, see Defining Conditional Branching with the Switch Activity in BPEL 1.1 .
-
While activity
Enables you to create a while loop to select between two actions. Defining Conditional Branching with the While Activity describes while activities.
Many branches are set up, and each branch has a condition in the form of an XPath expression.
You can program a conditional branch to have a timeout. That is, if a response cannot be generated in a specified period, the BPEL flow can stop waiting and resume its activities. Using Events and Timeouts in BPEL Processes explains this feature in detail.
Note:
You can also define conditional branching logic with business rules. See Designing Business Rules with Oracle Business Process Management.
11.2 Defining Conditional Branching with the If or Switch Activity
This section describes how to define conditional branching with the following activities:
-
If activity in a BPEL version 2.0 project
-
Switch activity in a BPEL version 1.1 project
11.2.1 Defining Conditional Branching with the If Activity in BPEL 2.0
You can use an if activity when conditional behavior is required for specific activities to decide between two or more branches. Only one activity is selected for execution from a set of branches. The if activity consists of a list of one or more conditional branches that are considered for execution in the following order:
-
The if branch
-
Optional elseif branches
-
An optional else branch
The first branch whose condition evaluates to true is taken, and its contained activity is performed. If no branch with a condition is taken, then the else branch is taken (if present). The if activity is complete when the contained activity of the selected branch completes, or immediately when no condition evaluates to true and no else branch is specified.
The if activity is a BPEL version 2.0 feature that replaces the switch activity that was included in BPEL version 1.1.
The following example shows the if activity syntax:
<if standard-attributes> standard-elements <condition>some conditon expression</condition> activity <elseif>* <condition>some condition expression</condition> some activity </elseif> <else>? some activity </else> </if>
11.2.1.2 What Happens When You Create an If Activity
The following code provides an example of the .bpel
file after design completion. The if activity has if, elseif, and else branches defined. The first branch to evaluate to true is executed.
<sequence> <!-- receive input from requester --> <receive name="receiveInput" partnerLink="client" portType="tns:Test" operation="process" variable="input" createInstance="yes"/> <!-- assign default value --> <assign> <copy> <from>'Value is greater than zero'</from> <to>$output.payload</to> </copy> <assign> <copy> <from>'Value is greater than zero'</from> <to>$output.payload</to> </copy> </assign> <!-- switch depends on the input value field --> <if> <condition>$input.payload > 0</condition> <extensionActivity> <bpelx:exec name="Java_Embedding" version="1.5" language="java"> System.out.println("if condition is true.\n"); </bpelx:exec> </extensionActivity> <elseif> <condition>bpws:getVariableData('input', 'payload') < 0</condition> <assign> <copy> <from>'Value is less than zero'</from> <to>$output.payload</to> </copy> </assign> </elseif> <else> <assign> <copy> <from>'Value is equal to zero'</from> <to>$output.payload</to> </copy> </assign> </else> </if> <!-- respond output to requester --> <reply name="replyOutput" partnerLink="client" portType="tns:Test" operation="process" variable="output"/> </sequence>
11.2.2 Defining Conditional Branching with the Switch Activity in BPEL 1.1
Assume you designed a flow activity in the BPEL process service component that gathered loan offers from two companies at the same time, but did not compare either of the offers. Each offer was stored in its own global variable. To compare the two bids and make decisions based on that comparison, you can use a switch activity.
Figure 11-5 provides an overview of a BPEL conditional branching process that has been defined in a switch activity.
11.2.2.2 What Happens When You Create a Switch Activity
A switch activity, such as a flow activity, has multiple branches. In the example that follows, there are only two branches shown in the .bpel
file after design completion. The first branch, which selects a loan offer from a company named United Loan, is executed if a case condition containing an XPath boolean expression is met. Otherwise, the second branch, which selects the offer from a company named Star Loan, is executed. By default, the switch activity provides two switch cases, but you can add more, as needed.
<switch name="switch-1"> <case condition="bpws:getVariableData('loanOffer1','payload', '/autoloan:loanOffer/autoloan:APR') > bpws:getVariableData('loanOffer2','payload','/autoloan:loanOffer/autoloan:APR ')"> " name="Choose_the_Loan_with_the_Lower_APR"> <bpelx:annotation> <bpelx:general> <bpelx:property name="userLabel">Choose the Loan with the Lower APR</bpelx:property> </bpelx:general> </bpelx:annotation> <assign name="selectUnitedLoan"> <copy> <from variable="loanOffer1" part="payload"> </from> <to variable="selectedLoanOffer" part="payload"/> </copy> </assign> </case> <otherwise> <assign name="selectStarLoan"> <copy> <from variable="loanOffer2" part="payload"> </from> <to variable="selectedLoanOffer" part="payload"/> </copy> </assign> </otherwise> </switch>
11.3 Defining Conditional Branching with the While Activity
Another way to design your BPEL code to select between multiple actions is to use a while activity to create a while loop. The while loop repeats an activity until a specified success criteria is met. For example, if a critical web service is returning a service busy message in response to requests, you can use the while activity to keep polling the service until it becomes available. The condition for the while activity is that the latest message received from the service is busy, and the operation within the while activity is to check the service again. Once the web service returns a message other than service busy, the while activity terminates and the BPEL process service component continues, ideally with a valid response from the web service.
11.3.2 What Happens When You Create a While Activity
The code that follows provides an example of the .bpel
file after design completion. The while activity includes a scope activity. The scope activity includes sequence and fault handlers at the top level. The sequence includes invoke and assign activities and fault handlers that define a catchAll
containing assign and wait activities wrapped in a sequence.
The following code calls an external service. If the external service throws a fault, the fault handler catches the fault and increments the dbStatus
variable value.
Therefore, the exit condition of the while loop is either of the following:
-
There is no exception, upon which the
dbStatus
value is set to a value of10
, which results in the while condition evaluating to false. -
After throwing a fault five times, the
dbStatus
value is5
, and the while condition returns false.
<while name="While_1" condition="bpws:getVariableData('dbStatus') > 5"> <scope name="Scope_1"> <faultHandlers> <catchAll> <sequence name="Sequence_2"> <assign name="assign_DB_retry"> <copy> <from expression="bpws:getVariableData('dbStatus') + 1"/> <to variable="dbStatus"/> </copy> </assign> <wait name="Wait_30_sec" for="'PT31S'"/> </sequence> </catchAll> </faultHandlers> <sequence name="Sequence_1"> <invoke name="Write_DBWrite" partnerLink="WriteDBRecord" portType="ns2:WriteDBRecord_ptt" operation="insert" inputVariable="Invoke_DBWrite_merge_InputVariable"/> <assign name="Assign_dbComplete"> <copy> <from expression="'10'"/> <to variable="dbStatus"/> </copy> </assign> </sequence> </scope> </while>
Note:
The while activity code fragment in the preceding example uses a BPEL 1.1 construct of bpws:getVariableData('dbStatus')
. For BPEL 2.0, variables are referenced directly using $
sign and dot (.
) notation. For example:
<while name="While1"> <condition>$inputVariable.payload/client:counter > 0 </condition>
11.4 Defining Conditional Branching with the repeatUntil Activity
If the body of an activity must be performed at least once, use a repeatUntil activity instead of a while activity. The XPath expression condition in the repeatUntil activity is evaluated after the body of the activity completes. The condition is evaluated repeatedly (and the body of the activity processed) until the provided boolean condition is true.
Note:
This activity is supported in BPEL version 2.0 projects.
11.4.2 What Happens When You Create a repeatUntil Activity
The following provides an example of the .bpel
file after design completion. In this scenario, purchase order validation must be performed at least once, then repeatedly, based on evaluating the completion status until the status is updated to 5
.
<repeatUntil> <sequence> <invoke name="PurchaseOrderValidation" ... /> <receive name="receiveValidation" partnerLink="PurchaseOrderValidation" operation="returnPurchaseOrderValidation" variable="PurchaseOrderStatusResponse" /> </sequence> <condition> bpel:getVariableProperty( "PurchaseOrderStatusResponse","tst:completionStatus") < 5 </condition> </repeatUntil>
11.5 Specifying XPath Expressions to Bypass Activity Execution
Oracle provides an extension that enables you to specify an XPath expression in an activity in BPEL versions 1.1 and 2.0 that, when evaluated to true, causes that activity to be skipped. This functionality provides an alternative to using a switch activity for conditionally executing activities. The skip condition for activities is specified as follows:
<activity bpelx:skipCondition="boolean-expr"/>
The bpelx:skipCondition
attribute causes an XPath expression to be evaluated immediately upon creation of the activity instance. If the skip expression returns a false boolean value, the activity is executed. If the skip expression returns a true boolean value, the activity is completed immediately and execution moves to the activity immediately following that one.
11.5.1 How to Specify XPath Expressions to Bypass Activity Execution
To specify XPath expressions to bypass activity execution:
11.5.2 What Happens When You Specify XPath Expressions to Bypass Activity Execution
The code segment in the .bpel
file defines the specific operation after design completion.
For example, the XPath expression shown in the following code, when evaluated to true (for example, input
is 20
), causes the assign activity to be skipped.
<sequence name="main"> . . . . . . <assign name="Assign_1" bpelx:skipCondition="number(bpws:getVariableData('inputVariable','payload','/client: process/client:input')) > 10"> <copy> <from expression="'Assign Block is not Skipped'"/> <to variable="inputVariable" part="payload" query="/client:process/client:input"/> </copy> </assign> . . . . . . </sequence>
The bpelx:skipCondition
attribute is equivalent to a switch/case structured activity with a single case element with a condition that is the opposite of the skip condition.
The following example shows the bpelx:skipCondition
attribute in BPEL 1.1. If myvalue
is 0
, the expression evaluates to true, and the assign activity is skipped. If myvalue
is 10
, the expression evaluates to false, and the copy operation of the assign activity is executed.
<assign bpelx:skipCondition="bpws:getVariableData('input', 'payload','/tns:inputMsg/tns:myvalue') <= 0"> <copy> <from expression="'Value is greater than zero'"/> <to variable="output" part="payload" query="/tns:resultMsg/tns:valueResult"/> </copy> </assign>
The equivalent functionality used with a switch activity is shown in the following example.
<switch> <case condition="bpws:getVariableData('input', 'payload','/tns:inputMsg/tns:value') > 0"> <assign> <copy> <from expression="'Value is greater than zero'"/> <to variable="output" part="payload" query="/tns:resultMsg/tns:valueResult"/> </copy> </assign> </case> </switch>
In BPEL 2.0, the bpelx:skipCondition
syntax appears as a child element of an activity. The following code provides an example of an assign activity with this convention.
<assign name="Assign4"> <bpelx:skipCondition>ora:getNodeValue($inputVariable.payload/client:input) > 5 </bpelx:skipCondition><copy> <from>"dummy result"</from> <to>$outputVariable.payload/client:result</to> </copy></assign>
You can also use built-in and custom XPath functions within the skip condition expression. The following code provides several examples.
<assign bpelx:skipCondition="bpws:getVariableData( 'crOutput', 'payload', '/tns:rating' ) > 0"> <assign bpelx:skipCondition="custom:validateRating()" ... /> <assign xmlns:fn='http://www.w3.org/2005/xpath-functions' bpelx:skipCondition="fn:false()" ... />
If an error is thrown by the XPath expression evaluation, the error is wrapped with a BPEL fault and thrown from the activity.
An event is added to the BPEL instance audit trail for activities that are bypassed due to the skip condition expression evaluating to true. Even if the skip condition evaluates to false (meaning the activity is performed), the fact that a skip condition expression was evaluated is still logged to the audit trail for debugging purposes.
If the XPath engine fails to evaluate the boolean value, bpws:subLanguageFault
is thrown. This is the same fault thrown when a switch/case condition does not evaluate to a boolean value. This is also logged to the audit trail for debugging purposes.