|Oracle® Fusion Middleware Developer's Guide for Oracle SOA Suite
11g Release 1 (11.1.1)
Part Number E10224-05
This chapter describes how to use conditional branching in a BPEL process service component. Conditional branching introduces decision points to control the flow of execution of a BPEL process service component.
This chapter includes the following sections:
For additional information on creating conditional branching in a SOA composite application, see the WebLogic Fusion Order Demo application.
BPEL applies logic to make choices through conditional branching. You can use either of the following activities to design your code to select different actions based on conditional branching:
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. Section 10.2, "Creating a Switch Activity to Define Conditional Branching" explains how to create switch activities.
Enables you to create a while loop to select between two actions. Section 10.3, "Creating a While Activity to Define Conditional Branching" 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. Chapter 14, "Using Events and Timeouts in BPEL Processes" explains this feature in detail.
Note:You can also define conditional branching logic with business rules. See Oracle Fusion Middleware User's Guide for Oracle Business Rules and the WebLogic Fusion Order Demo application for details.
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 10-1 provides an overview of a BPEL conditional branching process that has been defined in a switch activity.
Figure 10-1 Conditional Branching
To create a switch activity:
From the Component Palette, drag a Switch activity into the designer., as shown in Figure 10-2.
The Switch activity has two switch case branches by default, each with a box for functional elements. If you want to add more branches, select the entire switch activity, right-click, and select Add Switch Case from the menu.
Figure 10-2 Switch Activity
In the first branch, double-click the condition box.
A dialog for entering a condition is displayed, as shown in Figure 10-3.
Figure 10-3 Condition Dialog
In the Label field, enter a name for the condition branch. When complete, this name is displayed in Oracle BPEL Designer.
In the Description field, enter a description of the capabilities of this condition branch.
In the Condition field, click the Expression Builder icon to access the Expression Builder dialog.
Create your expression. For this example, the expression shown in Example 10-1 is created.
Example 10-1 XPath Expression
bpws:getVariableDate('loanOffer1','payload','/loanOffer/APR') > bpws:getVariableData('loanOffer2','payload','/loanOffer/APR')
In this example, two loan offers from completing loan companies are stored in the global variables
loanOffer2. Each loan offer variable contains the loan offer's APR. The BPEL flow must choose the loan with the lower APR. One of the following switch activities takes place:
The expression is displayed. The value you entered in the Label field of the dialog becomes the name of the condition branch.
Figure 10-4 Completed Condition Dialog
Add and configure additional activities as needed. Figure 10-5 provides details.
Figure 10-5 Switch Activity Design
A switch activity, like a flow activity, has multiple branches. In Example 10-2, 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 if you want.
Example 10-2 Switch Activity
<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>
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.
To create a while activity:
From the Component Palette, drag a While activity into the designer.
Click the + sign to expand the while activity.
The while activity has icons to allow you to build condition expressions and to validate the while definition. It also provides an area for you to drag an activity to define the while loop.
Drag and define additional activities for using the while condition into the Drop Activity Here area of the While activity (for example, a Scope activity).
The activities can be existing or new activities.
Press Ctrl+Space to invoke the XPath Building Assistant or click the XPath Expression Builder icon to open the Expression Builder dialog.
Enter an expression to perform repeatedly, as shown in Figure 10-6. This action is performed until the given boolean while condition is no longer true. In this example, this activity is set to loop while less than
Figure 10-6 While Activity with an Expression
Click OK when complete.
Example 10-3 provides an example of the
.bpel file after design completion. The while activity includes a scope activity. The scope activity includes invoke, assign, and wait activities. Database exception handling tasks are performed by creating a local variable and placing the invoke activity inside the scope activity. The local variable is set to false (represented by 0). You attempt to call the external partner service in the while loop activity until the local variable is satisfied (set to 1). The while activity is set to loop a maximum of five times. In the case of an exception, you reset the flag to false (0).
Example 10-3 While Activity
<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>
You can specify an XPath expression in an activity 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:
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.
This construct is equivalent to a switch/case structured activity with a single case element with a condition that is the opposite of the skip condition.
Example 10-4 provides an example of
bpelx:skipCondition attribute use. If
0, the expression evaluates to true, and the assign activity is skipped. If
10, the expression evaluates to false, and the copy operation of the assign activity is executed.
Example 10-4 Use of bpelx:skipCondition Attribute
<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 Example 10-5.
Example 10-5 Equivalent Functionality with a Switch Activity
<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>
You can also use built-in and custom XPath functions and
$variable references within the skip condition expression. Example 10-6 provides several examples:
Example 10-6 Built-in and Custom XPath Functions and $variable References
<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.
To specify XPath expressions to bypass activity execution:
From the Component Palette, drag the activity into the designer in which to create the skip condition.
Click the Skip Condition tab.
Specify an XPath expression that, when evaluated to true, causes an activity to be skipped. Figure 10-7 provides details.
Figure 10-7 Skip Condition XPath Expression
Click Apply, then OK.
The code segment in the
.bpel file defines the specific operation after design completion.
For example, the following XPath expression shown in Example 10-7, when evaluated to true (for example,
20), causes the assign activity to be skipped.
Example 10-7 skipCondition Attribute For Bypassing Activity Execution
<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>