6 min read

Loops

When defining business processes, we will sometimes want to perform a certain activity or a set of activities in a loop; for example, perform a calculation or invoke a partner web service operation several times, and so on.

BPEL supports three types of loops:

  • <while> loops
  • <repeatUntil> loops
  • <forEach> loops

The <while> and <repeatUntil> loops are very similar to other programming languages. The <forEach> loop, on the other hand, provides the ability to start the loop instances in parallel.

Loops are helpful when dealing with arrays. In BPEL, arrays can be simulated using XML complex types where one or more elements can occur more than once (using the maxOccurs attribute in the XML Schema definition). To iterate through multiple occurrences of the same element, we can use XPath expressions.

Let us now look at the <while> loop.

While

The <while> loop repeats the enclosed activities until the Boolean condition no longer holds true. The Boolean condition is expressed through the condition element, using the selected expression language (the default is XPath 1.0). The syntax of the <while> activity is shown in the following code excerpt:

<while>
<condition> boolean-expression </condition>
<!– Perform an activity or a set of activities enclosed by
<sequence>, <flow>, or other structured activity –>
</while


Let us consider a scenario where we need to check flight availability for more than one person. Let us also assume that we need to invoke a web service operation for each person. In addition to the variables already present in the example, we would need two more NoOfPassengers to hold the number of passengers and Counter to use in the loop. The code excerpt with variable declarations is as follows:

<variables>
<variable name=”NoOfPassengers” type=”xs:int”/>
<variable name=”Counter” type=”xs:int”/>
</variables>


We also need to assign values to the variables. The NoOfPassengers can be obtained from the Employee Travel web service. In the following code, we initialize both variables with static values:

<assign>
<copy>
<from>number(5)</from>
<to variable=”NoOfPassengers”/>
</copy>
<copy>
<from>number(0)</from>
<to variable=”Counter”/>
</copy>
</assign>


The loop to perform the web service invocation is shown in the following code excerpt. Please remember that this excerpt is not complete:

<while>
<condition>$Counter &lt; $NoOfPassengers</condition>
<sequence>
<!– Construct the FlightDetails variable with passenger data –>

<!– Invoke the web service –>
<invoke partnerLink=”AmericanAirlines”
portType=”aln:FlightAvailabilityPT”
operation=”FlightAvailability”
inputVariable=”FlightDetails” />
<receive partnerLink=”AmericanAirlines”
portType=”trv:FlightCallbackPT”
operation=”FlightTicketCallback”
variable=”FlightResponseAA” />

<!– Process the results … –>

<!– Increment the counter –>
<assign>
<copy>
<from>$Counter + 1</from>
<to variable=”Counter”/>
</copy>
</assign>
</sequence>
</while>


Repeat Until

The <repeatUntil> loop repeats the enclosed activities until the Boolean condition becomes true. The Boolean condition is expressed through the condition element, the same way as in the <while> loop. The syntax of the <repeatUntil> activity is shown in the following code excerpt:

<repeatUntil>
<!– Perform an activity or a set of activities enclosed by
<sequence>, <flow>, or other structured activity –>
<condition> boolean-expression </condition>
</repeatUntil>


A similar example of a loop as mentioned in the previous section, but using <repeatUntil>, is as follows:

<repeatUntil>
<sequence>
<!– Construct the FlightDetails variable with passenger data –>

<!– Invoke the web service –>
<invoke partnerLink=”AmericanAirlines”
portType=”aln:FlightAvailabilityPT”
operation=”FlightAvailability”
inputVariable=”FlightDetails” />
<receive partnerLink=”AmericanAirlines”
portType=”trv:FlightCallbackPT”
operation=”FlightTicketCallback”
variable=”FlightResponseAA” />

<!– Process the results … –>

<!– Increment the counter –>
<assign>
<copy>
<from>$Counter + 1</from>
<to variable=”Counter”/>
</copy>
</assign>
</sequence>
<condition>$Counter &gt;= $NoOfPassengers</condition>
</repeatUntil>


For Each

The <forEach> loop is a for type loop, with an important distinction. In BPEL the <forEach> loop can execute the loop branches in parallel or serially. The serial <forEach> is very similar to the for loops from various programming languages, such as Java. The parallel <forEach> executes the loop branches in parallel (similar to <flow>), which opens new possibilities in relatively simple parallel execution (for example, invocation of services).

The <forEach> loop requires us to specify the BPEL variable for the counter (counterName), the startCounterValue, and the finalCounterValue. The <forEach> loop will execute (finalCounterValue – startCounterValue + 1) times.

The <forEach> requires that we put all activities, which should be executed within the branch, into a <scope>. The <scope> allows us to perform group-related activities.

The syntax of <forEach> is shown in the following:

<forEach counterName=”BPELVariableName” parallel=”yes|no”>
<startCounterValue>unsigned-integer-expression</startCounterValue>
<finalCounterValue>unsigned-integer-expression</finalCounterValue>
<scope>
<!– The activities that are performed within forEach have to be
nested within a scope. –>
</scope>
</forEach>


Such a <forEach> loop will complete when all branches (<scope>) have completed.

A similar example of a loop as in the previous section is as follows:

<forEach counterName=”Counter” parallel=”no”>
<startCounterValue>number(1)</startCounterValue>
<finalCounterValue>$NoOfPassengers</finalCounterValue>
<scope>
<sequence>
<!– Construct the FlightDetails variable with passenger data
–>

<!– Invoke the web service –>
<invoke partnerLink=”AmericanAirlines”
portType=”aln:FlightAvailabilityPT”
operation=”FlightAvailability”
inputVariable=”FlightDetails” />
<receive partnerLink=”AmericanAirlines”
portType=”trv:FlightCallbackPT”
operation=”FlightTicketCallback”
variable=”FlightResponseAA” />

<!– Process the results … –>

</sequence>
</scope>
</forEach>


Sometimes it would be useful if the <forEach> loop would not have to wait for all branches to complete. Rather, it would wait until at least some branches complete. In <forEach> we can specify that the loop will complete after at least N branches have completed. We do this using the <completionCondition> . We specify the number N of <branches>. The <forEach> will complete after at least N branches have completed. We can specify if we would like to count only successful branches or all branches. We do this using the successfulBranchesOnly attribute. If set to yes, only successful branches will count. If set to no (default), successful and failed branches will count. The syntax is as shown in the following:

<forEach counterName=”BPELVariableName” parallel=”yes|no”>
<startCounterValue>unsigned-integer-expression</startCounterValue>
<finalCounterValue>unsigned-integer-expression</finalCounterValue>
<completionCondition> <!– Optional –>
<branches successfulBranchesOnly=”yes|no”>
unsigned-integer-expression
</branches>
</completionCondition>
<scope>
<!– The activities that are performed within forEach have to be
nested within a scope. –>
</scope>
</forEach>


LEAVE A REPLY

Please enter your comment!
Please enter your name here