Skip Headers
Oracle® Fusion Middleware Developer's Guide for Oracle SOA Suite
11g Release 1 (11.1.1)
E10224-03
  Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
 
Next
Next
 

9 Using Parallel Flow in a BPEL Process

This chapter describes how to use parallel flow in a BPEL process service component. Parallel flows enable a BPEL process service component to perform multiple tasks at the same time. Parallel flow is especially useful when you must perform several time-consuming and independent tasks.

This chapter includes the following sections:

For additional information on creating parallel flows in a SOA composite application, see the WebLogic Fusion Order Demo application.

9.1 Introduction to Parallel Flows in BPEL Processes

A BPEL process service component must sometimes gather information from multiple asynchronous sources. Because each callback can take an undefined amount of time (hours or days), it may take too long to call each service one at a time. By breaking the calls into a parallel flow, a BPEL process service component can invoke multiple web services at the same time, and receive the responses as they come in. This method is much more time efficient.

shows the Retrieve_QuotesFromSuppliers flow activity of the WebLogic Fusion Order Demo application. The Retrieve_QuotesFromSuppliers flow activity sends order information to two suppliers in parallel: an internal warehouse (InternalWarehouseService) and an external partner warehouse (PartnerSupplierMediator). The two warehouses return their bids for the order to the flow activity. Here, two asynchronous callbacks execute in parallel. One callback does not have to wait for the other to complete first. Each response is stored in a different global variable.

Figure 9-1 Parallel Flow Invocation

Description of Figure 9-1 follows
Description of "Figure 9-1 Parallel Flow Invocation"

9.2 Creating a Parallel Flow

You can create a parallel flow in a BPEL process service component with the flow activity. The flow activity enables you to specify one or more activities to be performed concurrently. The flow activity also provides synchronization. The flow activity completes when all activities in the flow have finished processing. Completion of this activity includes the possibility that it can be skipped if its enabling condition is false.

9.2.1 How to Create a Parallel Flow

To create a parallel flow:

  1. From the Component Palette, drag a Flow activity into the designer.

  2. Click the + sign to expand the flow activity, as shown in .

    The flow activity includes two branches, each with a box for functional elements. Populate these boxes as you do a scope activity, either by building a function or dragging activities into the boxes.

  3. Drag and define additional activities onto each side of the flow to invoke multiple services at the same time.

    Figure 9-3 Expanded Flow Activity

    Description of Figure 9-3 follows
    Description of "Figure 9-3 Expanded Flow Activity"

    When complete, flow activity design can look as shown in . This example shows the Retrieve_QuotesFromSuppliers flow activity of the WebLogicFusionOrderDemo application. Two branches are defined for receiving bids, one for InternalWarehouseService and the other for PartnerSupplierMediator.

    Figure 9-4 Flow Activity After Design Completion

    Description of Figure 9-4 follows
    Description of "Figure 9-4 Flow Activity After Design Completion"

9.2.2 What Happens When You Create a Parallel Flow

A flow activity typically contains many sequence activities. Each sequence is performed in parallel. Example 9-1 shows the syntax for two sequences of the Retrieve_QuotesFromSuppliers flow activity in the OrderProcessor.bpel file after design completion. However, a flow activity can have many sequences. A flow activity can also contain other activities. In Example 9-1, each sequence in the flow contains assign, invoke, and receive activities.

Example 9-1 Flow Activity

<flow name="Retrieve_QuotesFromSuppliers">
    <sequence name="Sequence_4">
        <assign name="Assign_InternalWarehouseRequest">
            <copy>
                <from variable="gOrderInfoVariable"
                    query="/ns4:orderInfoVOSDO/ns4:OrderId"/>
                <to variable="lInternalWarehouseInputVariable"
                    part="payload"
                    query="/ns1:WarehouseRequest/ns1:orderId"/>
            </copy>
        </assign>
        <invoke name="Invoke_InternalWarehouse"
            inputVariable="lInternalWarehouseInputVariable"
            partnerLink="InternalWarehouseService"
            portType="ns1:InternalWarehouseService"
            operation="process"/>
        <receive name="Receive_InternalWarehouse"
            createInstance="no"
            variable="lInternalWarehouseResponseVariable"
            partnerLink="InternalWarehouseService"
            portType="ns1:InternalWarehouseServiceCallback"
            operation="processResponse"/>
        <assign name="Assign_InterWHResponse">
            <bpelx:append>
                <bpelx:from variable="lInternalWarehouseResponseVariable"
                       part="payload"
                       query="/ns1:WarehouseResponse"/>
                <bpelx:to variable="gWarehouseQuotes"
                       query="/ns1:WarehouseList"/>
            </bpelx:append>
        </assign>
    </sequence>
    <sequence name="Sequence_4">
        <assign name="Assign_PartnerRequest">
            <copy>
                <from variable="gOrderInfoVariable"
                    query="/ns4:orderInfoVOSDO"/>
                <to variable="lPartnerSupplierInputVariable"
                    part="request" query="/ns4:orderInfoVOSDO"/>
            </copy>
        </assign>
        <invoke name="Invoke_PartnerSupplier"
            partnerLink="PartnerSupplierMediator"
            portType="ns15:execute_ptt" operation="execute"
            inputVariable="lPartnerSupplierInputVariable"/>
        <receive name="Receive_PartnerResponse"
            createInstance="no"
            variable="lPartnerResponseVariable"
            partnerLink="PartnerSupplierMediator"
            portType="ns15:callback_ptt" operation="callback"/>
            <assign name="Assign_PartnerWHResponse">
                <bpelx:append>
                    <bpelx:from variable="lPartnerResponseVariable"
                           part="callback"
                           query="/ns1:WarehouseResponse"/>
                           <bpelx:to variable="gWarehouseQuotes"
                           query="/ns1:WarehouseList"/>
                    </bpelx:append>
            </assign>
    </sequence>
</flow>

9.3 Customizing the Number of Flow Activities with the flowN Activity

In the flow activity, the BPEL code determines the number of parallel branches. However, often the number of branches required is different depending on the available information. The flowN activity creates multiple flows equal to the value of N, which is defined at runtime based on the data available and logic within the process. An index variable increments each time a new branch is created, until the index variable reaches the value of N.

The flowN activity performs activities on an arbitrary number of data elements. As the number of elements changes, the BPEL process service component adjusts accordingly.

The branches created by flowN perform the same activities, but use different data. Each branch uses the index variable to look up input variables. The index variable can be used in the XPath expression to acquire the data specific for that branch.

For example, suppose there is an array of data. The BPEL process service component uses a count function to determine the number of elements in the array. Then the process sets N to be the number of elements. The index variable starts at a preset value (zero is the default), and flowN creates branches to retrieve each element of the array and perform activities using data contained in that element. These branches are generated and performed in parallel, using all the values between the initial index value and N. flowN terminates when the index variable reaches the value of N. For example, if the array contains 3 elements, N is set to 3. Assuming the index variable begins at 1, the flowN activity creates three parallel branches with indexes 1, 2, and 3.

The flowN activity can use data from other sources as well, including data obtained from web services.

Figure 9-5 shows the runtime flow of a flowN activity in Oracle Enterprise Manager Fusion Middleware Control Console that looks up three hotels. This is different from the view because instead of showing the BPEL process service component, it shows how the process has actually executed. In this case, there are three hotels, but the number of branches changes to match the number of hotels available.

Figure 9-5 Oracle Enterprise Manager Fusion Middleware Control Console View of the Execution of a flowN activity

Description of Figure 9-5 follows
Description of "Figure 9-5 Oracle Enterprise Manager Fusion Middleware Control Console View of the Execution of a flowN activity"

9.3.1 How to Create a flowN Activity

To create a flowN activity:

  1. From the Component Palette, drag a FlowN activity into the designer.

  2. Click the + sign to expand the FlowN activity.

  3. Double-click the FlowN activity.

    Figure 9-6 shows the flowN dialog.

    The flowN dialog enables you to:

    • Name the activity

    • Enter a value or an expression for calculating the value of N (the number of branches to create)

    • Define the index variable (the time to wait in each branch)

  4. Drag and define additional activities in the flowN activity.

    Figure 9-7 shows how a FlowN activity appears with additional activities.

    Figure 9-7 FlowN Activity with Additional Activities

    Description of Figure 9-7 follows
    Description of "Figure 9-7 FlowN Activity with Additional Activities "

9.3.2 What Happens When You Create a FlowN Activity

The following code shows the .bpel file that uses the flowN activity to look up information on an arbitrary number of hotels. The following actions take place.

Example 9-2 shows the sequence name.

Example 9-2 Sequence Name

  <sequence name="main">
  <!-- Received input from requester. 
    Note: This maps to operation defined in NflowHotels.wsdl
    The requester sends a set of hotels names wrapped into the "inputVariable"
    -->

A receive activity calls the client partner link to get the information that the flowN activity must define N times and look up hotel information. Example 9-3 provides an example.

Example 9-3 Receive Activity

    <receive name="receiveInput" partnerLink="client"
 portType="client:NflowHotels" operation="initiate" variable="inputVariable"
 createInstance="yes"/>
    <!-- 
       The 'count()' Xpath function is used to get the number of hotelName
       noded passed in.
       An intermediate variable called "NbParallelFlow" is
       used to store the number of N flows being executed
       -->
    <assign name="getHotelsN">
      <copy>
        <from 
expression="count(bpws:getVariableData('inputVariable','payload','/client:Nflow
HotelsProcessRequest/client:ListOfHotels/client:HotelName'));"/>
        <to variable="NbParallelFlow"/>
      </copy>
    </assign>
    <!-- Initiating the FlowN activity
        The N value is initialized with the value stored in the
 "NbParallelFlow" variable
        The variable call "Index" is defined as the index variable
        NOTE: Both "NbParallelFlow" and "Index" variables have to be declared
        -->

The flowN activity begins next. After defining a name for the activity of flowN, N is defined as a value from the inputVariable, which is the number of hotel entries. The activity also assigns index as the index variable. Example 9-4 provides an example.

Example 9-4 FlowN Activity

<bpelx:flowN name="FlowN" N="bpws:getVariableData('NbParallelFlow')
indexVariable="Index'>
      <sequence name="Sequence_1">
        <!-- Fetching each hotelName by indexing the "inputVariable" with the
 "Index" variable.
            Note the usage of the  "concat()" Xpath function to create the
 expression accessing the array element.
            -->

The copy rule shown in Example 9-5 then uses the index variable to concatenate the hotel entries into a list:

Example 9-5 Assign Activity

<assign name="setHotelId">
  <copy>
    <from expression=
"bpws:getVariableData('inputVariable','payload',concat('/client:Nflo
wHotelsProcessRequest/client:ListOfHotels/client:HotelName[',
bpws:getVariableData('Index'),']'))"/>
            <to variable="InvokeHotelDetailInputVariable" part="payload"
 query="/ns2:hotelInfoRequest/ns2:id"/>
          </copy>
        </assign>

Using the hotel information, an invoke activity looks up detailed information for each hotel through a web service. Example 9-6 provides an example.

Example 9-6 Invoke Activity

 <!-- For each hotel, invoke the web service giving detailed information
 on the hotel -->
        <invoke name="InvokeHotelDetail" partnerLink="getHotelDetail"
 portType="ns2:getHotelDetail" operation="process"
 inputVariable="InvokeHotelDetailInputVariable"
 outputVariable="InvokeHotelDetailOutputVariable"/>
        <!-- This procees does not do anything with the retrieved information.
        In real life, it could then be used to continue the process.
        Note: Meanwhile an indexing variable is used. Unlike a while loop, the
 activities are executed in parallel, not sequentially.
        -->
      </sequence>
    </bpelx:flowN>

Finally, the BPEL process sends detailed information on each hotel to the client partner link. Example 9-7 provides an example.

Example 9-7 Invoke Activity

    <invoke name="callbackClient" partnerLink="client"
 portType="client:NflowHotelsCallback" operation="onResult"
 inputVariable="outputVariable"/>
  </sequence>
  </sequence>