この章では、BPELプロセス・サービス・コンポーネントでの条件分岐の使用方法について説明します。条件分岐により、BPELプロセス・サービス・コンポーネントの実行フローを制御するための判断ができるようになります。
項目は次のとおりです。
SOAコンポジット・アプリケーションでの条件分岐の作成方法の詳細は、Fusion Order Demoアプリケーションを参照してください。
BPELは、条件分岐によって選択するロジックを利用します。次のアクティビティを使用すると、条件分岐に基づいて異なるアクションを選択するコードを設計できます。
switchアクティビティ(BPELバージョン1.1プロジェクト)
2つ以上のブランチを設定できます。各ブランチにはXPath式の形式を使用します。式がtrueの場合、そのブランチが実行されます。式がfalseの場合、BPELプロセス・サービス・コンポーネントは有効なブランチ条件が見つかるか、otherwiseブランチに達するか、ブランチがなくなるまで次のブランチ条件に進みます。複数のブランチ条件がtrueの場合は、最初にtrueと判断されたブランチがBPELにより実行されます。switchアクティビティの作成方法については、第10.2.1項「BPEL 1.1のswitchアクティビティの作成による条件分岐の定義」を参照してください。
ifアクティビティ(BPELバージョン2.0プロジェクト)
2つ以上のブランチのいずれかに決めるために特定のアクティビティに条件動作が必要な場合、ifアクティビティを使用できます。ifアクティビティは、BPEL 1.1プロセスに見られたswitchアクティビティにかわるものです。ifアクティビティの作成方法の詳細は、第10.2.2項「BPEL 2.0のifアクティビティの作成による条件分岐の定義」を参照してください。
whileアクティビティ
2つのアクション間で選択を実行するwhileループを作成できます。whileアクティビティの作成方法については、第10.3項「whileアクティビティの作成による条件分岐の定義」で説明します。
多数のブランチが設定され、各ブランチにはXPath式形式の条件が指定されます。
条件分岐には、タイムアウトを設定できます。つまり、指定の期間内にレスポンスを生成できない場合、BPELフローは待機を中止し、そのアクティビティを再開できます。この機能の詳細は、第14章「BPELプロセスでのイベントおよびタイムアウトの使用」で説明します。
|
注意: 条件分岐ロジックはビジネス・ルールを使用して定義することもできます。詳細は、『Oracle Fusion Middleware Oracle Business Rulesユーザーズ・ガイド』およびWebLogic Fusion Order Demoアプリケーションを参照してください。 |
この項では、次のアクティビティを使用して条件分岐を定義する方法について説明します。
BPELバージョン1.1プロジェクトのswitchアクティビティ
BPELバージョン2.0プロジェクトのifアクティビティ
2社からの融資提案が同時に収集されるBPELプロセス・サービス・コンポーネントのflowアクティビティを設計し、ここではいずれの条件も比較されていないと仮定します。各条件は、それぞれのグローバル変数に格納されています。2つの提案を比較し、その比較に基づいて決定するには、switchアクティビティを使用できます。
図10-1に、switchアクティビティに定義されたBPEL条件分岐プロセスの概観を示します。
switchアクティビティを作成する手順は、次のとおりです。
「コンポーネント・パレット」で、「BPELコンストラクト」を展開します。
図10-2に示すように、switchアクティビティをデザイナにドラッグします。
switchアクティビティにはデフォルトで2つのswitch caseブランチがあり、各ブランチには機能要素を挿入するためのボックスがあります。ブランチを追加するには、switchアクティビティ全体を選択して右クリックし、メニューから「Switch Caseの追加」を選択します。
最初のブランチで、「Condition」ボックスをダブルクリックします。
図10-3に示すように、条件を入力するためのダイアログが表示されます。
「ラベル」フィールドに、条件分岐の名前を入力します。完了すると、Oracle BPELデザイナにこの名前が表示されます。
「説明」フィールドに、この条件分岐の機能に関する説明を入力します。
「条件」フィールドで、「式ビルダー」アイコンをクリックして「式ビルダー」ダイアログにアクセスします。
式を作成します。
bpws:getVariableDate('loanOffer1','payload','/loanOffer/APR') >
bpws:getVariableData('loanOffer2','payload','/loanOffer/APR')
この例では、融資企業からの完成した2つの融資提案は、グローバル変数loanOffer1およびloanOffer2に格納されます。それぞれの融資提案変数には、融資提案のAPRが格納されます。BPELフローは、APRが最も低い融資を選択する必要があります。次のいずれかのswitchアクティビティを実行します。
「OK」をクリックします。
式が表示されます。ダイアログの「ラベル」フィールドに入力した値は、条件分岐の名前になります。図10-4に詳細を示します。
「OK」をクリックします。
必要に応じて、その他のアクティビティを追加および構成します。図10-5に詳細を示します。
flowアクティビティと同様に、switchアクティビティには複数のブランチがあります。例10-1では、2つのブランチのみが設計完了後の.bpelファイルに表示されています。最初のブランチは、United Loanという企業からの融資提案を選択するブランチであり、XPathブール式を含むcase条件が適合した場合に実行されます。適合しなかった場合は、Star Loanという企業からの融資提案を選択する2番目のブランチが実行されます。デフォルトでは、switchアクティビティに含まれるswitch caseは2つですが、必要に応じて追加できます。
例10-1 switchアクティビティ
<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>
2つ以上のブランチのいずれかに決めるために特定のアクティビティに条件動作が必要な場合、ifアクティビティを使用できます。ブランチのセットから実行するアクティビティを1つのみ選択します。ifアクティビティは、次の順序で実行対象とみなされる1つ以上の条件分岐のリストで構成されます。
ifブランチ
オプションのelseifブランチ
オプションのelseブランチ
条件がtrueに評価される最初のブランチが採用され、そこに含まれているアクティビティが実行されます。条件付きブランチが採用されない場合は、elseブランチが採用されます(存在する場合)。ifアクティビティは、選択されたブランチに含まれるアクティビティが完了した時点で、またはtrueに評価される条件がなまelseブランチが指定されていない場合にはただちに終了します。
ifアクティビティは、BPELバージョン1.1に含まれていたswitchアクティビティにかわる、BPELバージョン2.0の機能です。
例10-2にifアクティビティの構文を示します。
例10-2 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>
ifアクティビティを作成する手順は、次のとおりです。
「コンポーネント・パレット」で、「BPELコンストラクト」を展開します。
ifアクティビティをデザイナにドラッグします。
図10-6に示すように、if条件とelse条件が表示されます。
elseif条件を追加する場合は、ifアクティビティを強調表示し、「追加」アイコンを選択してメニューを起動します。
ifブランチをクリックします。
図10-7に示すように、「条件」フィールドに条件を入力します。「XPath式ビルダー」アイコンをクリックして、「式ビルダー」ダイアログを起動することもできます。
「OK」をクリックします。
必要に応じて、追加のアクティビティをif条件にドラッグして定義します。これらのアクティビティは、if条件がtrueと評価された場合に実行されます。
elseifブランチをクリックします(このブランチを追加した場合)。
図10-8に示すように、「条件」フィールドに条件を入力します。
「OK」をクリックします。
必要に応じて、追加のアクティビティをelseif条件にドラッグして定義します。これらのアクティビティは、ifブランチがtrueと評価されず、このelseifブランチがtrueと評価された場合に実行されます。
elseラベルをクリックします。
必要に応じて、条件を入力するか、追加のアクティビティをelse条件にドラッグして定義します。これらのアクティビティは、ifおよびその他のelseifブランチがtrueと評価されず、このelseブランチがtrueと評価された場合に実行されます。
図10-9に、完了したifアクティビティを示します。各ブランチには、含まれているアクティビティが表示されています。
例10-3に、設計完了後の.bpelファイルの例を示します。ifアクティビティでは、if、elseifおよびelseの各ブランチが定義されています。trueと評価された最初のブランチが実行されます。
例10-3 ifアクティビティ
<sequence>
<!-- receive input from requestor -->
<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 requestor -->
<reply name="replyOutput" partnerLink="client"
portType="tns:Test" operation="process" variable="output"/>
</sequence>
複数のアクション間で選択を行うようにBPELコードを設計する別の方法としては、whileアクティビティを使用したwhileループの作成があります。whileループは、指定の条件が適合するまで、アクティビティを繰り返します。たとえば、重要なWebサービスでリクエストに対してサービス・ビジー・メッセージを返している場合、そのサービスが使用可能になるまで、whileアクティビティを使用してポーリングし続けることができます。このときのwhileアクティビティの条件はサービスから受け取った最新のメッセージがビジーであることで、whileアクティビティ内の操作はサービスを再チェックすることです。Webサービスからサービス・ビジー以外のメッセージが戻ると、whileアクティビティは終了し、理想的にはWebサービスからの有効なレスポンスを使用して、BPELプロセス・サービス・コンポーンネントが続行されます。
whileアクティビティを作成する手順は、次のとおりです。
「コンポーネント・パレット」で、「BPELコンストラクト」を展開します。
whileアクティビティをデザイナにドラッグします。
+記号をクリックしてwhileアクティビティを開きます。
whileアクティビティには、条件式を作成するアイコンとwhile定義を検証するアイコンがあります。また、アクティビティをドラッグしてwhileループを定義する領域も用意されています。
while条件を使用するための追加のアクティビティ(scopeアクティビティなど)をwhileアクティビティの「アクティビティをここにドロップ」領域にドラッグして定義します。
このアクティビティとして、既存のアクティビティや新しいアクティビティを使用できます。
[Ctrl]キーを押しながら[Space]キーを押してXPathビルディング・アシスタントを起動するか、「XPath式ビルダー」アイコンをクリックして「式ビルダー」ダイアログを開きます。
図10-10に示すように、繰り返し実行する式を入力します。このアクションは、指定したwhile条件のブール値がtrueでなくなるまで実行されます。この例のアクティビティは、5未満の場合に繰り返しループするように設定されています。
完了後に「OK」をクリックします。
例10-4に、設計完了後の.bpelファイルの例を示します。whileアクティビティ内にscopeアクティビティがあります。scopeアクティビティ内にはinvoke、assignおよびwaitアクティビティがあります。データベース例外処理タスクは、ローカル変数を作成してscopeアクティビティ内にinvokeアクティビティを配置することで実行されます。ローカル変数はfalseに設定されます(0で表されます)。ローカル変数の条件が満たされる(1に設定される)まで、whileループ・アクティビティで外部パートナ・サービスのコールを試行します。whileアクティビティは、最大5回ループするように設定されています。例外の場合は、フラグをfalse(0)にリセットします。
例10-4 whileアクティビティ
<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>
アクティビティの本文を少なくとも1回実行する必要がある場合は、whileアクティビティではなくrepeatUntilアクティビティを使用します。repeatUntilアクティビティのXPath式の条件は、アクティビティの本文が完了した後に評価されます。条件は、指定したブール条件がtrueになるまで繰返し評価されます(アクティビティの本文も処理されます)。
|
注意: このアクティビティは、BPELバージョン2.0プロジェクトでサポートされています。 |
repeatUntilアクティビティを作成する手順は、次のとおりです。
「コンポーネント・パレット」で、「BPELコンストラクト」を展開します。
repeat untilアクティビティをデザイナにドラッグします。
repeat untilアクティビティをダブルクリックします。
名前を入力するか、デフォルト値をそのまま使用します。
「条件」フィールドで、「XPath式ビルダー」アイコンをクリックしてXPath式条件を入力します。
「式ビルダー」ダイアログが表示されます。
XPathブール式の条件を入力し、「OK」をクリックします。
図10-11に示すように、入力した条件が「繰返し期限」ダイアログに表示されます。
「適用」→「OK」の順にクリックします。
図10-12に示すように、repeat untilアクティビティを開きます。
「コンポーネント・パレット」からアクティビティをドラッグし、プロパティ値を定義することで、アクティビティの本文を設計します。これらのアクティビティは、XPath式の条件がtrueと評価されるまで評価されます。
例10-5に、設計完了後の.bpelファイルの例を示します。このシナリオでは、注文書の検証を少なくとも1回実行し、その後はステータスが5に更新されるまで、完了ステータスの評価に基づいて検証を繰り返します。
例10-5 repeatUntilアクティビティ
<repeatUntil>
<sequence>
<invoke name="PurchaseOrderValidation" ... />
<receive name="receiveValidation"
partnerLink="PurchaseOrderValidation"
operation="returnPurchaseOrderValidation"
variable="PurchaseOrderStatusResponse" />
</sequence>
<condition>
bpel:getVariableProperty(
"PurchaseOrderStatusResponse","tst:completionStatus") < 5
</condition>
</repeatUntil>
アクティビティにXPath式を指定して、trueと評価された場合に、そのアクティビティがスキップされるようにできます。この機能は、アクティビティを条件付きで実行するために使用するswitchアクティビティの代替手段として提供されています。アクティビティのスキップ条件は、次のように指定します。
<activity bpelx:skipCondition="boolean-expr"/>
bpelx:skipCondition属性により、アクティビティ・インスタンスが作成されるとすぐに、XPath式が評価されます。スキップ式でfalseのブール値が返された場合は、アクティビティが実行されます。スキップ式でtrueのブール値が返された場合、アクティビティは即時に完了となり、そのアクティビティの直後のアクティビティに実行が移動します。
このコンストラクトは、スキップ条件とは反対の条件が指定された単一のcase要素が含まれるswitch/case構造化アクティビティに相当します。
例10-6に、bpelx:skipCondition属性の使用例を示します。myvalueが0の場合、式はtrueと評価され、assignアクティビティがスキップされます。myvalueが10の場合、式はfalseと評価され、assignアクティビティのコピー操作が実行されます。
例10-6 bpelx:skipCondition属性の使用
<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>
例10-7に、switchアクティビティを使用した同等の機能を示します。
例10-7 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>
スキップ条件式には、組込みおよびカスタムのXPath関数と$variable参照も使用できます。例10-8に、いくつかの例を示します。
例10-8 組込みおよびカスタムのXPath関数と$variable参照
<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条件がブール値に評価されない場合にスローされるフォルトと同じです。このフォルトも、デバッグのために監査証跡に記録されます。
アクティビティの実行をバイパスするためのXPath式を指定する手順は、次のとおりです。
「コンポーネント・パレット」で、「BPELコンストラクト」を展開します。
スキップ条件を作成するアクティビティをデザイナにドラッグします。
「スキップ条件」タブをクリックします。
trueと評価された場合にアクティビティをスキップさせるXPath式を指定します。図10-13に詳細を示します。
「適用」→「OK」の順にクリックします。
.bpelファイルのコード・セグメントは、特定の操作に対する設計完了後の定義を示しています。
たとえば、例10-9に記載されているXPath式は、trueと評価された場合に(たとえば、inputが20)、assignアクティビティをスキップさせます。
例10-9 アクティビティの実行をバイパスするためのskipCondition属性
<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>