この章では、BPELプロセス・サービス・コンポーネントでのパラレル・フローの使用方法について説明します。パラレル・フローを使用すると、BPELプロセス・サービス・コンポーネントで複数のタスクを同時に実行できます。パラレル・フローは、時間を要する独立した複数のタスクを実行する必要がある場合に特に役立ちます。
項目は次のとおりです。
SOAコンポジット・アプリケーションでのパラレル・フローの作成方法の詳細は、WebLogic Fusion Order Demoアプリケーションを参照してください。
BPELプロセスでは、複数の非同期ソースからの情報の収集が必要になる場合があります。各コールバックに要する時間(時間数または日数)は明らかでないため、各サービスを一度に1つずつコールするのでは時間がかかりすぎることがあります。複数のコールを1つのパラレル・フローに分解することにより、BPELプロセス・サービス・コンポーネントは複数のWebサービスを同時に起動し、レスポンスが到着するたびに受信できます。この方法は時間の節約に効果的です。
次の図は、WebLogic Fusion Order Demoアプリケーションの「Retrieve_QuotesFromSuppliers」flowアクティビティを示しています。「Retrieve_QuotesFromSuppliers」flowアクティビティは、注文情報を社内倉庫(InternalWarehouseService)と外部パートナ倉庫(PartnerSupplierMediator)の2つのサプライヤにパラレルで送信します。2つの倉庫は、注文に対する入札をflowアクティビティに返します。ここでは、2つの非同期コールバックがパラレルで実行されます。一方のコールバックは、もう一方のコールバックが先に完了するまで待機する必要がありません。各レスポンスは異なるグローバル変数に格納されます。
BPELプロセス・サービス・コンポーネントにパラレル・フローを作成するには、flowアクティビティを使用します。flowアクティビティを使用すると、1つ以上のアクティビティを同時に実行するように指定できます。flowアクティビティは同期性も備えています。flowアクティビティは、フロー内のすべてのアクティビティが処理を終了したときに完了します。このアクティビティが完了しても、許可条件がfalseの場合はスキップされている可能性があります。
パラレル・フローを作成する手順は、次のとおりです。
「コンポーネント・パレット」から、デザイナにflowアクティビティをドラッグします。
+記号をクリックし、次の図のようにflowアクティビティを開きます。
flowアクティビティには、2つのブランチがあり、各ブランチには機能要素用のボックスがあります。これらのボックスにデータを移入するには、scopeアクティビティの場合のように、機能を作成するか、複数のアクティビティをボックスにドラッグします。
複数のサービスを同時に起動するには、追加するアクティビティをflowの両側にドラッグして定義します。
完了すると、flowアクティビティの設計は次のようになります。この例は、WebLogicFusionOrderDemoアプリケーションの「Retrieve_QuotesFromSuppliers」flowアクティビティを示しています。入札を受け取るために、「InternalWarehouseService」および「PartnerSupplierMediator」の2つのブランチが定義されています。
通常、flowアクティビティには多数のsequenceアクティビティが含まれています。各sequenceはパラレルに実行されます。例9-1は、設計完了後のOrderProcessor.bpel
ファイルのRetrieve_QuotesFromSuppliers
flowアクティビティに対してsequenceが2つある構文を示しています。ただし、flowアクティビティには多数のsequenceを指定できます。flowアクティビティには、他のアクティビティを含めることもできます。例9-1では、flowの各sequenceにassign、invokeおよびreceiveアクティビティが含まれています。
図9-1 flowアクティビティ
<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>
flowアクティビティでは、BPELコードによってパラレル・ブランチの数が決定されます。ただし、必要なブランチの数は、多くの場合、使用可能な情報に応じて異なります。flowNアクティビティは、N
の値に等しい複数のフローを作成します。この値は、使用可能なデータおよびプロセス内のロジックに基づいて実行時に定義されます。索引変数は、N
の値に到達するまで、新しいブランチが作成されるたびに増分されます。
flowNアクティビティは、任意の数のデータ要素に対してアクティビティを実行します。BPELプロセス・サービス・コンポーネントは、要素の数の変化に応じて適切に調整を実行します。
flowNで作成される各ブランチは、同じアクティビティを実行しますが、異なるデータを使用します。各ブランチは、索引変数を使用して入力変数を参照します。索引変数をXPath式で使用すると、そのブランチに固有のデータを取得できます。
たとえば、データの配列があるとします。BPELプロセス・サービス・コンポーネントは、count
関数を使用して配列内の要素の数を判断します。次に、N
が要素の数に設定されます。索引変数は、事前に設定された値(デフォルトは0(ゼロ))で始まります。flowNは、複数のブランチを作成して配列の各要素を取得し、その要素に含まれるデータを使用してアクティビティを実行します。これらのブランチは、初期索引値とN
の間のすべての値を使用して、パラレルに生成および実行されます。flowNは、索引変数がN
の値に到達すると終了します。たとえば、配列に3
つの要素が含まれている場合、N
は3
に設定されます。索引変数が1で始まるとすると、flowNアクティビティは索引1、2および3を使用して3つのパラレル・ブランチを作成します。
flowNアクティビティでは、Webサービスから取得したデータなど、他のソースのデータも使用できます。
図9-5は、3つのホテルを参照するOracle Enterprise Manager Fusion Middleware ControlコンソールのflowNアクティビティの実行時フローを示しています。この図は、BPELプロセス・サービス・コンポーネントではなく、プロセスを実際に実行する方法を示しているため、ビューそのものではありません。この例では、3つのホテルがありますが、ブランチの数は使用可能なホテルの数に応じて異なります。
図9-5 flowNアクティビティの実行を示すOracle Enterprise Manager Fusion Middleware Controlコンソール・ビュー
次のコードは、flowNアクティビティを使用して任意の数のホテルの情報を参照する.bpel
ファイルを示しています。次のアクションを実行します。
例9-2にsequence名を示します。
例9-2 sequence名
<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" -->
receive
アクティビティは、クライアント・パートナ・リンクをコールし、flowN
アクティビティがN
の数を定義してホテル情報を参照するために必要な情報を取得します。例9-3に例を示します。
例9-3 receiveアクティビティ
<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
アクティビティが開始されます。flowN
のアクティビティに名前を定義すると、N
がinputVariable
(ホテル・エントリの数)の値として定義されます。また、このアクティビティは、索引変数としてindex
を割り当てます。例9-4に例を示します。
図9-4 flowNアクティビティ
<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. -->
例9-5に示すコピー・ルールで索引変数を使用し、複数のホテル・エントリを1つのリストに連結します。
例9-5 assignアクティビティ
<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>
invoke
アクティビティは、このホテル情報を使用して、Webサービスから各ホテルの詳細情報を参照します。例9-6に例を示します。
例9-6 invokeアクティビティ
<!-- 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>
最後に、このBPELプロセスは、各ホテルの詳細情報をクライアント・パートナ・リンクに送信します。例9-7に例を示します。