この章の内容は次のとおりです。
BPELは、条件分岐によって選択するロジックを利用します。次のアクティビティを使用すると、条件分岐に基づいて異なるアクションを選択するコードを設計できます。
ifアクティビティ(BPELバージョン2.0プロジェクト)
2つ以上のブランチのいずれかに決めるために特定のアクティビティに条件動作が必要な場合、ifアクティビティを使用できます。ifアクティビティは、BPEL 1.1プロセスに見られたswitchアクティビティにかわるものです。ifアクティビティの作成方法の詳細は、「BPEL 2.0のifアクティビティの作成による条件分岐の定義」を参照してください。
switchアクティビティ(BPELバージョン1.1プロジェクト)
2つ以上のブランチを設定できます。各ブランチにはXPath式の形式を使用します。式がtrueの場合、そのブランチが実行されます。式がfalseの場合、BPELプロセス・サービス・コンポーネントは有効なブランチ条件が見つかるか、otherwiseブランチに達するか、ブランチがなくなるまで次のブランチ条件に進みます。複数のブランチ条件がtrueの場合は、最初にtrueと判断されたブランチがBPELにより実行されます。switchアクティビティの作成方法の詳細は、「BPEL 1.1のswitchアクティビティの作成による条件分岐の定義」を参照してください。
whileアクティビティ
2つのアクション間で選択を実行するwhileループを作成できます。whileアクティビティの説明は、「whileアクティビティによる条件分岐の定義」にあります。
多数のブランチが設定され、各ブランチにはXPath式形式の条件が指定されます。
条件分岐には、タイムアウトを設定できます。つまり、指定の期間内にレスポンスを生成できない場合、BPELフローは待機を中止し、そのアクティビティを再開できます。この機能の詳細は、「BPELプロセスでのイベントおよびタイムアウトの使用」で説明します。
注意:
条件分岐ロジックはビジネス・ルールを使用して定義することもできます。『Oracle Business Process Managementによるビジネス・ルールの設計』を参照してください。
この項では、次のアクティビティを使用して条件分岐を定義する方法について説明します。
BPELバージョン2.0プロジェクトのifアクティビティ
BPELバージョン1.1プロジェクトのswitchアクティビティ
2つ以上のブランチのいずれかに決めるために特定のアクティビティに条件動作が必要な場合、ifアクティビティを使用できます。ブランチのセットから、実行するアクティビティが1つだけ選択されます。ifアクティビティは、次の順序で実行対象とみなされる1つ以上の条件分岐のリストで構成されます。
ifブランチ
オプションのelseifブランチ
オプションのelseブランチ
条件がtrueに評価される最初のブランチが採用され、そこに含まれているアクティビティが実行されます。条件付きブランチが採用されない場合は、elseブランチが採用されます(存在する場合)。ifアクティビティは、選択されたブランチに含まれるアクティビティが完了した時点で、またはtrueに評価される条件がなまelseブランチが指定されていない場合にはただちに終了します。
ifアクティビティは、BPELバージョン1.1に含まれていたswitchアクティビティにかわる、BPELバージョン2.0の機能です。
次の例にifアクティビティの構文を示します。
<if standard-attributes> standard-elements <condition>some conditon expression</condition> activity <elseif>* <condition>some condition expression</condition> some activity </elseif> <else>? some activity </else> </if>
次のコードは、設計完了後の.bpel
ファイルの例を示しています。ifアクティビティでは、if、elseifおよびelseの各ブランチが定義されています。trueと評価された最初のブランチが実行されます。
<sequence> <!-- receive input from requester --> <receive name="receiveInput" partnerLink="client" portType="tns:Test" operation="process" variable="input" createInstance="yes"/> <!-- assign default value --> <assign> <copy> <from>'Value is greater than zero'</from> <to>$output.payload</to> </copy> <assign> <copy> <from>'Value is greater than zero'</from> <to>$output.payload</to> </copy> </assign> <!-- switch depends on the input value field --> <if> <condition>$input.payload > 0</condition> <extensionActivity> <bpelx:exec name="Java_Embedding" version="1.5" language="java"> System.out.println("if condition is true.\n"); </bpelx:exec> </extensionActivity> <elseif> <condition>bpws:getVariableData('input', 'payload') < 0</condition> <assign> <copy> <from>'Value is less than zero'</from> <to>$output.payload</to> </copy> </assign> </elseif> <else> <assign> <copy> <from>'Value is equal to zero'</from> <to>$output.payload</to> </copy> </assign> </else> </if> <!-- respond output to requester --> <reply name="replyOutput" partnerLink="client" portType="tns:Test" operation="process" variable="output"/> </sequence>
2社からの融資提案が同時に収集されるBPELプロセス・サービス・コンポーネントのflowアクティビティを設計し、ここではいずれの条件も比較されていないと仮定します。各条件は、それぞれのグローバル変数に格納されています。2つの提案を比較し、その比較に基づいて決定するには、switchアクティビティを使用できます。
図11-5に、switchアクティビティに定義されたBPEL条件分岐プロセスの概要を示します。
flowアクティビティなどのswitchアクティビティには複数のブランチがあります。次の例では、2つのブランチのみが設計完了後の.bpel
ファイルに表示されています。最初のブランチは、United Loanという企業からの融資提案を選択するブランチであり、XPathブール式を含むcase条件が適合した場合に実行されます。そうでない場合、Star Loanという企業からの融資提案を選択する2番目のブランチが実行されます。デフォルトでは、switchアクティビティには2つのswitch caseが含まれていますが、必要に応じて追加できます。
<switch name="switch-1"> <case condition="bpws:getVariableData('loanOffer1','payload', '/autoloan:loanOffer/autoloan:APR') > bpws:getVariableData('loanOffer2','payload','/autoloan:loanOffer/autoloan:APR ')"> " name="Choose_the_Loan_with_the_Lower_APR"> <bpelx:annotation> <bpelx:general> <bpelx:property name="userLabel">Choose the Loan with the Lower APR</bpelx:property> </bpelx:general> </bpelx:annotation> <assign name="selectUnitedLoan"> <copy> <from variable="loanOffer1" part="payload"> </from> <to variable="selectedLoanOffer" part="payload"/> </copy> </assign> </case> <otherwise> <assign name="selectStarLoan"> <copy> <from variable="loanOffer2" part="payload"> </from> <to variable="selectedLoanOffer" part="payload"/> </copy> </assign> </otherwise> </switch>
複数のアクション間で選択を行うようにBPELコードを設計する別の方法としては、whileアクティビティを使用したwhileループの作成があります。whileループは、指定の条件が適合するまで、アクティビティを繰り返します。たとえば、重要なWebサービスでリクエストに対してサービス・ビジー・メッセージを返している場合、そのサービスが使用可能になるまで、whileアクティビティを使用してポーリングし続けることができます。このときのwhileアクティビティの条件はサービスから受け取った最新のメッセージがビジーであることで、whileアクティビティ内の操作はサービスを再チェックすることです。Webサービスからサービス・ビジー以外のメッセージが戻ると、whileアクティビティは終了し、理想的にはWebサービスからの有効なレスポンスを使用して、BPELプロセス・サービス・コンポーネントが続行されます。
次のコードは、設計完了後の.bpel
ファイルの例を示しています。whileアクティビティ内にscopeアクティビティがあります。scopeアクティビティには、シーケンスおよびフォルト・ハンドラが最上位レベルに含まれています。シーケンスにはinvokeアクティビティ、assignアクティビティ、およびシーケンスにラップされたassignアクティビティとwaitアクティビティを含むcatchAll
を定義するフォルト・ハンドラが含まれています。
次のコードにより、外部サービスがコールされます。外部サービスがフォルトをスローすると、フォルト・ハンドラによってフォルトが捕捉され、dbStatus
変数値が増分されます。
したがって、whileループの終了条件は次のいずれかとなります。
例外がないこと(dbStatus
値が値10
に設定されており、これにより、while条件はfalseと評価されます)
フォルトが5回スローされた後であること(dbStatus
値が5
に設定されており、while条件はfalseを返します)
<while name="While_1" condition="bpws:getVariableData('dbStatus') > 5"> <scope name="Scope_1"> <faultHandlers> <catchAll> <sequence name="Sequence_2"> <assign name="assign_DB_retry"> <copy> <from expression="bpws:getVariableData('dbStatus') + 1"/> <to variable="dbStatus"/> </copy> </assign> <wait name="Wait_30_sec" for="'PT31S'"/> </sequence> </catchAll> </faultHandlers> <sequence name="Sequence_1"> <invoke name="Write_DBWrite" partnerLink="WriteDBRecord" portType="ns2:WriteDBRecord_ptt" operation="insert" inputVariable="Invoke_DBWrite_merge_InputVariable"/> <assign name="Assign_dbComplete"> <copy> <from expression="'10'"/> <to variable="dbStatus"/> </copy> </assign> </sequence> </scope> </while>
注意:
前の例のwhileアクティビティのコード・フラグメントでは、BPEL 1.1コンストラクトbpws:getVariableData('dbStatus')
が使用されています。BPEL 2.0の場合、変数は$
記号およびドット(.
)表記法を使用して、直接参照されます。次に例を示します。
<while name="While1"> <condition>$inputVariable.payload/client:counter > 0 </condition>
アクティビティの本文を少なくとも1回実行する必要がある場合は、whileアクティビティではなくrepeatUntilアクティビティを使用します。repeatUntilアクティビティのXPath式の条件は、アクティビティの本文が完了した後に評価されます。条件は、指定したブール条件がtrueになるまで繰返し評価されます(アクティビティの本体も処理されます)。
注意:
このアクティビティは、BPELバージョン2.0プロジェクトでサポートされています。
次に、設計完了後の.bpel
ファイルの例を示します。このシナリオでは、注文書の検証を少なくとも1回実行し、その後はステータスが5
に更新されるまで、完了ステータスの評価に基づいて検証を繰り返します。
<repeatUntil> <sequence> <invoke name="PurchaseOrderValidation" ... /> <receive name="receiveValidation" partnerLink="PurchaseOrderValidation" operation="returnPurchaseOrderValidation" variable="PurchaseOrderStatusResponse" /> </sequence> <condition> bpel:getVariableProperty( "PurchaseOrderStatusResponse","tst:completionStatus") < 5 </condition> </repeatUntil>
Oracleの拡張機能を使用すると、BPELバージョン1.1および2.0のアクティビティにXPath式を指定して、trueと評価された場合に、そのアクティビティがスキップされるようにできます。この機能は、アクティビティを条件付きで実行するために使用するswitchアクティビティの代替手段として提供されています。アクティビティのスキップ条件は、次のように指定します。
<activity bpelx:skipCondition="boolean-expr"/>
bpelx:skipCondition
属性により、アクティビティ・インスタンスが作成されるとすぐに、XPath式が評価されます。スキップ式でfalseのブール値が返された場合は、アクティビティが実行されます。スキップ式でtrueのブール値が返された場合、アクティビティは即時に完了となり、そのアクティビティの直後のアクティビティに実行が移動します。
.bpel
ファイルのコード・セグメントは、特定の操作に対する設計完了後の定義を示しています。
たとえば、次のコードに示されているXPath式は、trueと評価された場合に(たとえば、input
が20
)、assignアクティビティをスキップさせます。
<sequence name="main"> . . . . . . <assign name="Assign_1" bpelx:skipCondition="number(bpws:getVariableData('inputVariable','payload','/client: process/client:input')) > 10"> <copy> <from expression="'Assign Block is not Skipped'"/> <to variable="inputVariable" part="payload" query="/client:process/client:input"/> </copy> </assign> . . . . . . </sequence>
bpelx:skipCondition
属性は、スキップ条件とは反対の条件が指定された単一のcase要素が含まれるswitch/case構造化アクティビティに相当します。
次の例は、BPEL 1.1におけるbpelx:skipCondition
属性を示しています。myvalue
が0
の場合、式はtrueと評価され、assignアクティビティがスキップされます。myvalue
が10
の場合、式はfalseと評価され、assignアクティビティのコピー操作が実行されます。
<assign bpelx:skipCondition="bpws:getVariableData('input', 'payload','/tns:inputMsg/tns:myvalue') <= 0"> <copy> <from expression="'Value is greater than zero'"/> <to variable="output" part="payload" query="/tns:resultMsg/tns:valueResult"/> </copy> </assign>
次の例は、switchアクティビティを使用した同等の機能を示しています。
<switch> <case condition="bpws:getVariableData('input', 'payload','/tns:inputMsg/tns:value') > 0"> <assign> <copy> <from expression="'Value is greater than zero'"/> <to variable="output" part="payload" query="/tns:resultMsg/tns:valueResult"/> </copy> </assign> </case> </switch>
BPEL 2.0では、bpelx:skipCondition
構文がアクティビティの子要素として表示されます。次のコードは、この規則を使用したassignアクティビティの例を示しています。
<assign name="Assign4"> <bpelx:skipCondition>ora:getNodeValue($inputVariable.payload/client:input) > 5 </bpelx:skipCondition><copy> <from>"dummy result"</from> <to>$outputVariable.payload/client:result</to> </copy></assign>
スキップ条件式には、組込みおよびカスタムのXPath関数も使用できます。次のコードは、いくつかの例を示しています。
<assign bpelx:skipCondition="bpws:getVariableData( 'crOutput', 'payload', '/tns:rating' ) > 0"> <assign bpelx:skipCondition="custom:validateRating()" ... /> <assign xmlns:fn='http://www.w3.org/2005/xpath-functions' bpelx:skipCondition="fn:false()" ... />
XPath式の評価でエラーがスローされると、そのエラーはBPELフォルトにラップされて、アクティビティからスローされます。
イベントは、trueと評価しているスキップ条件式によってバイパスされるアクティビティのBPELインスタンス監査証跡に追加されます。スキップ条件がfalseと評価された(アクティビティが実行されることを意味する)場合も、スキップ条件式が評価されたという事実が、デバッグのために監査証跡に記録されます。
XPathエンジンがブール値の評価に失敗した場合は、bpws:subLanguageFault
がスローされます。これは、switch/case条件がブール値に評価されない場合にスローされるフォルトと同じです。このフォルトも、デバッグのために監査証跡に記録されます。