|Oracle® BPEL Process Manager Developer's Guide
Part Number B28981-03
This chapter contains the following topics:
In Chapter 5, "Invoking an Asynchronous Web Service" you learned how to call an asynchronous Web service for the United Loan service. Because the United Loan service can take up to several days to return a loan offer but you need to collect another loan offer from Star Loan, you can define your BPEL process so both tasks run in parallel.
This use case shows how to program the BPEL flow to perform two asynchronous callbacks to loan services in parallel.
See Also:The following sample:
Sometimes a BPEL process must 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 can invoke multiple Web services at once, and receive the responses as they come in. This method is much more time efficient.
Figure 6-1 provides an overview of a BPEL process performing a parallel flow to retrieve loan offers from two different Web services. Here, two asynchronous callbacks execute in parallel, so that one callback does not have to wait for the other to complete first. Each response is stored in a different global variable.
Figure 6-1 Parallel Flow Invocation
flow activity typically contains a number of
sequence activities, and each sequence is performed in parallel. A
flow activity can also contain other activities (although not in this example). For example:
<flow name="flow-1"> <sequence> <scope name="UnitedLoan"> <sequence> <invoke name="invoke-2" partnerLink="unitedLoan" portType="services:LoanService" operation="initiate" inputVariable="loanApplication"/> <receive createInstance="no" name="receive-1" partnerLink="unitedLoan" portType="services:LoanServiceCallback" operation="onResult" variable="loanOffer1"/> </sequence> </scope> </sequence> <sequence> <scope name="StarLoan"> <sequence> <invoke name="invoke-1" partnerLink="StarLoan" portType="services:LoanService" operation="initiate" inputVariable="loanApplication"/> <pick name="pick-1">. . . </pick> </sequence> </scope> </sequence> </flow>
This example shows two sequences, but the flow activity can have many sequences.
The following instructions explain how to create a flow activity and a global input variable named
request. This activity initiates an asynchronous BPEL process activity with a loan offer Web service (United Loan). The loan offer service uses the request input variable to receive the loan request from the client.
This example shows how to create a flow activity in Oracle JDeveloper.
Drag and drop a flow activity into a scope activity.
Click the + sign to expand the flow activity.
A scope activity is a container for a group of activities that you want to process as one unit. "Using the Scope Activity to Manage a Group of Activities" describes scope activities in detail.
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 from the Process Activities list into the boxes.
At this point, you can drag and drop activities onto each side of the flow in order to invoke multiple services at once.
See Also:The following documentation for examples of creating flow activities in Oracle JDeveloper:
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 run time 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 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 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.
shows an Oracle BPEL Control view of a flowN activity that looks up three hotels. This is different from the view because instead of showing the BPEL process, 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 6-2 An Oracle BPEL Control View of the Execution of a flowN activity
shows how a flowN activity appears in Oracle JDeveloper.
Figure 6-3 FlowN Activity Setup in the Diagram Window
Figure 6-4 shows the flowN Window, which appears when you double-click the flowN activity.
Figure 6-4 flowN Window
The flowN windows enables you to name the flowN activity, enter an expression for calculating the value of
N, and define the index variable.
See Also:"FlowN Activity"
The following code is a reference implementation from a
.bpel file that uses the
flowN activity to look up information on an arbitrary number of hotels. The following actions take place:
First, you name the
<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 needs to define
N and look up hotel information:
<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. For lisibility, an intermediate varaible 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.
<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. -->
Next, the following copy rule uses the index variable to concatenate the hotel entries into a list:
<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:
<!-- 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 doesn't do anything with the retrieved inforamtion. In the real life, it could be then used to continue the process. Note: Meanwhile an indexing variable is used, unlike a while loop, the activities a executed in parallel, not sequentially. --> </sequence> </bpelx:flowN>
Finally, the BPEL process sends detailed information on each hotel to the client partner link:
<invoke name="callbackClient" partnerLink="client" portType="client:NflowHotelsCallback" operation="onResult" inputVariable="outputVariable"/> </sequence> </sequence>
This chapter shows how to create a parallel flow using the flow activity to perform multiple tasks simultaneously. This BPEL process performs two asynchronous callbacks in parallel, which can take considerably less time than performing the two callbacks in series. Another activity, called a flowN activity, allows Oracle BPEL Process Manager to use data to spawn the necessary number of parallel flows at run time, and to perform the same activities on multiple data elements. Therefore, as the information available to the BPEL process changes, so does the behavior of the process.