|Oracle® Fusion Middleware Developer's Guide for Oracle SOA Suite
11g Release 1 (11.1.1)
Part Number E10224-01
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 Oracle Fusion Middleware Tutorial for Running and Building an Application with Oracle SOA Suite.
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 10-1 Parallel Flow Invocation
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.
To create a parallel flow:
From the Component Palette, drag a Flow activity into the designer.
Click the + sign to expand the flow activity, as shown in .
Figure 10-2 Flow Activity
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.
Drag and define additional activities onto each side of the flow to invoke multiple services at the same time.
Figure 10-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 10-4 Flow Activity After Design Completion
A flow activity typically contains many sequence activities. Each sequence is performed in parallel. Example 10-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 10-1, each sequence in the flow contains assign, invoke, and receive activities.
Example 10-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>
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
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
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 10-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 10-5 Oracle Enterprise Manager Fusion Middleware Control Console View of the Execution of a flowN activity
To create a flowN activity:
From the Component Palette, drag a FlowN activity into the designer.
Click the + sign to expand the FlowN activity.
Double-click the FlowN activity.
Figure 10-6 shows the flowN dialog.
Figure 10-6 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)
Drag and define additional activities in the flowN activity.
Figure 10-7 shows how a FlowN activity appears with additional activities.
Figure 10-7 FlowN Activity with Additional Activities
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 10-2 shows the sequence name.
Example 10-2 Sequence Name
<sequence name="main"> <!-- Received input from requestor. Note: This maps to operation defined in NflowHotels.wsdl The requestor send a set of hotels names wrapped into the "inputVariable" -->
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 10-3 provides an example.
Example 10-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 -->
flowN activity begins next. After defining a name for the activity of
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 10-4 provides an example.
Example 10-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 10-5 then uses the index variable to concatenate the hotel entries into a list:
Example 10-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 10-6 provides an example.
Example 10-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 10-7 provides an example.