11 BPELプロセスでの条件分岐の使用

この章では、BPELプロセス・サービス・コンポーネントでの条件分岐の使用方法について説明します。条件分岐により、BPELプロセス・サービス・コンポーネントの実行フローを制御するための判断ができるようになります。この章では、switch、if、while、repeatUntilの各アクティビティを使用して条件分岐を定義する方法、およびアクティビティの実行をバイパスできるXPath式を指定する方法についても説明します。

この章の内容は次のとおりです。

11.1 条件分岐の概要

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によるビジネス・ルールの設計』を参照してください。

11.2 ifまたはswitchアクティビティによる条件分岐の定義

この項では、次のアクティビティを使用して条件分岐を定義する方法について説明します。

  • BPELバージョン2.0プロジェクトのifアクティビティ

  • BPELバージョン1.1プロジェクトのswitchアクティビティ

11.2.1 BPEL 2.0のifアクティビティの作成による条件分岐の定義

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>
11.2.1.1 ifアクティビティの作成方法

ifアクティビティを作成するには:

  1. 「コンポーネント」ウィンドウで、「BPELコンストラクト」を展開します。
  2. ifアクティビティをデザイナにドラッグします。

    図11-1に示すように、if条件とelse条件が表示されます。

    図11-1 ifアクティビティ

    図11-1の説明が続きます
    「図11-1 ifアクティビティ」の説明
  3. ifブランチをクリックします。
  4. 図11-2に示すように、「条件」フィールドに条件を入力します。「XPath式ビルダー」アイコンをクリックして、「式ビルダー」ダイアログを起動することもできます。

    図11-2 ifアクティビティのifブランチ

    図11-2の説明が続きます
    「図11-2 ifアクティビティのifブランチ」の説明
  5. 「OK」をクリックします。
  6. 必要に応じて、追加のアクティビティをif条件にドラッグして定義します。これらのアクティビティは、if条件がtrueと評価された場合に実行されます。
  7. elseifブランチをクリックします(このブランチを追加した場合)。
  8. 図11-3に示すように、「条件」フィールドに条件を入力します。

    図11-3 ifアクティビティのelseifブランチ

    図11-3の説明が続きます
    「図11-3 ifアクティビティのelseifブランチ」の説明
  9. 「OK」をクリックします。
  10. elseif条件を追加する場合は、ifアクティビティを強調表示し、「追加」アイコンを選択してメニューを起動します。
  11. 必要に応じて、追加のアクティビティをelseif条件にドラッグして定義します。これらのアクティビティは、ifブランチがtrueと評価されず、このelseifブランチがtrueと評価された場合に実行されます。
  12. elseラベルをクリックします。
  13. 必要に応じて、条件を入力するか、追加のアクティビティをelse条件にドラッグして定義します。これらのアクティビティは、ifおよびその他のelseifブランチがtrueと評価されず、このelseブランチがtrueと評価された場合に実行されます。

    図11-4に、完了したifアクティビティを示します。各ブランチには、含まれているアクティビティが表示されています。

    図11-4 完了したifアクティビティ

    図11-4の説明が続きます
    「図11-4 完了したifアクティビティ」の説明
11.2.1.2 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') &lt; 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>

11.2.2 BPEL 1.1のswitchアクティビティの作成による条件分岐の定義

2社からの融資提案が同時に収集されるBPELプロセス・サービス・コンポーネントのflowアクティビティを設計し、ここではいずれの条件も比較されていないと仮定します。各条件は、それぞれのグローバル変数に格納されています。2つの提案を比較し、その比較に基づいて決定するには、switchアクティビティを使用できます。

図11-5に、switchアクティビティに定義されたBPEL条件分岐プロセスの概要を示します。

11.2.2.1 switchアクティビティの作成方法

switchアクティビティを作成するには:

  1. 「コンポーネント」ウィンドウで、「BPELコンストラクト」を展開します。
  2. 図11-6に示すように、switchアクティビティをデザイナにドラッグします。

    switchアクティビティにはデフォルトで2つのswitch caseブランチがあり、各ブランチには機能要素を挿入するためのボックスがあります。ブランチを追加するには、switchアクティビティ全体を選択して右クリックし、メニューから「Switch Caseの追加」を選択します。

    図11-6 switchアクティビティ

    図11-6の説明が続きます
    「図11-6 switchアクティビティ」の説明
  3. 最初のブランチで、「条件」ボックスをダブルクリックします。

    図11-7に示すように、条件を入力するためのダイアログが表示されます。

    図11-7 「条件」ダイアログ

    図11-7の説明が続きます
    「図11-7 「条件」ダイアログ」の説明
  4. 「ラベル」フィールドに、条件分岐の名前を入力します。完了すると、Oracle BPELデザイナにこの名前が表示されます。
  5. 「条件」フィールドで、「式ビルダー」アイコンをクリックして「式ビルダー」ダイアログにアクセスします。
  6. 式を作成します。
    bpws:getVariableDate('loanOffer1','payload','/loanOffer/APR') >
    bpws:getVariableData('loanOffer2','payload','/loanOffer/APR')
    

    この例では、融資企業からの完成した2つの融資提案は、グローバル変数loanOffer1およびloanOffer2に格納されます。それぞれの融資提案変数には、融資提案のAPRが格納されます。BPELフローは、APRが最も低い融資を選択する必要があります。次のいずれかのswitchアクティビティを実行します。

    • loanOffer1のAPRの方が高い場合、最初のブランチはloanOffer2のペイロードをselectedLoanOfferのペイロードに割り当てることで、loanOffer2を選択します。

    • loanOffer1loanOffer2より小さいAPRがない場合、otherwise caseはloanOffer1ペイロードをselectedLoanOfferペイロードに割り当てます。

  7. 「OK」をクリックします。

    式が表示されます。ダイアログの「ラベル」フィールドに入力した値は、条件分岐の名前になります。

  8. 「OK」をクリックします。
  9. 必要に応じて、その他のアクティビティを追加および構成します。図11-8に詳細を示します。

    図11-8 switchアクティビティの設計

    図11-8の説明が続きます
    「図11-8 switchアクティビティの設計」の説明
11.2.2.2 switchアクティビティ作成時の処理内容

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>

11.3 whileアクティビティによる条件分岐の定義

複数のアクション間で選択を行うようにBPELコードを設計する別の方法としては、whileアクティビティを使用したwhileループの作成があります。whileループは、指定の条件が適合するまで、アクティビティを繰り返します。たとえば、重要なWebサービスでリクエストに対してサービス・ビジー・メッセージを返している場合、そのサービスが使用可能になるまで、whileアクティビティを使用してポーリングし続けることができます。このときのwhileアクティビティの条件はサービスから受け取った最新のメッセージがビジーであることで、whileアクティビティ内の操作はサービスを再チェックすることです。Webサービスからサービス・ビジー以外のメッセージが戻ると、whileアクティビティは終了し、理想的にはWebサービスからの有効なレスポンスを使用して、BPELプロセス・サービス・コンポーネントが続行されます。

11.3.1 whileアクティビティの作成方法

whileアクティビティを作成するには:

  1. 「コンポーネント」ウィンドウで、「BPELコンストラクト」を展開します。
  2. whileアクティビティをデザイナにドラッグします。
  3. +記号をクリックしてwhileアクティビティを開きます。

    whileアクティビティには、条件式を作成するアイコンとwhile定義を検証するアイコンがあります。また、アクティビティをドラッグしてwhileループを定義する領域も用意されています。

  4. while条件を使用するための追加のアクティビティ(scopeアクティビティなど)をwhileアクティビティの「アクティビティをここにドロップ」領域にドラッグして定義します。

    このアクティビティとして、既存のアクティビティや新しいアクティビティを使用できます。

  5. 「XPath式ビルダー」アイコンをクリックして、「式ビルダー」ダイアログを開きます。
  6. 図11-9に示すように、繰り返し実行する式を入力します。このアクションは、指定したwhile条件のブール値がtrueでなくなるまで実行されます。この例のアクティビティは、5未満の場合に繰り返しループするように設定されています。

    図11-9 式が設定されているwhileアクティビティ

    図11-9の説明が続きます
    「図11-9 式が設定されているwhileアクティビティ」の説明
  7. 完了後に「OK」をクリックします。

11.3.2 whileアクティビティ作成時の処理内容

次のコードは、設計完了後の.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>

11.4 repeatUntilアクティビティによる条件分岐の定義

アクティビティの本文を少なくとも1回実行する必要がある場合は、whileアクティビティではなくrepeatUntilアクティビティを使用します。repeatUntilアクティビティのXPath式の条件は、アクティビティの本文が完了した後に評価されます。条件は、指定したブール条件がtrueになるまで繰返し評価されます(アクティビティの本体も処理されます)。

ノート:

このアクティビティは、BPELバージョン2.0プロジェクトでサポートされています。

11.4.1 repeatUntilアクティビティの作成方法

repeatUntilアクティビティを作成するには:

  1. 「コンポーネント」ウィンドウで、「BPELコンストラクト」を展開します。
  2. 「繰返し期限」アクティビティをデザイナにドラッグします。
  3. 「繰返し期限」アクティビティをクリックして、そのプロパティ・フィールドをプロパティ・インスペクタで表示するか、「繰返し期限」アクティビティをダブルクリックします。

    アクティビティをプロパティ・インスペクタで編集する方法の詳細は、「BPELアクティビティをプロパティ・インスペクタで編集する方法」を参照してください。

  4. 名前を入力するか、デフォルト値をそのまま使用します。
  5. 「条件」フィールドで、「XPath式ビルダー」アイコンをクリックしてXPath式条件を入力します。

    「式ビルダー」ダイアログが表示されます。

  6. XPathブール式の条件を入力し、「OK」をクリックします。

    図11-10に示すように、入力した条件が「繰返し期限」ダイアログに表示されます。

    図11-10 入力が完了した「繰返し期限」ダイアログ

    図11-10の説明が続きます
    「図11-10 入力が完了した「繰返し期限」ダイアログ」の説明
  7. 「適用」をクリックし、「OK」をクリックします。
  8. 図11-11に示すように、「繰返し期限」アクティビティを展開します。

    図11-11 展開した状態のrepeatUntilアクティビティ

    図11-11の説明が続きます
    「図11-11 展開した状態のrepeatUntilアクティビティ」の説明
  9. 「コンポーネント」ウィンドウからアクティビティをドラッグし、プロパティ値を定義することで、アクティビティの本文を設計します。これらのアクティビティは、XPath式の条件がtrueと評価されるまで評価されます。

11.4.2 repeatUntilアクティビティ作成時の処理内容

次に、設計完了後の.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>

11.5 アクティビティの実行をバイパスするためのXPath式の指定

Oracleの拡張機能を使用すると、BPELバージョン1.1および2.0のアクティビティにXPath式を指定して、trueと評価された場合に、そのアクティビティがスキップされるようにできます。この機能は、アクティビティを条件付きで実行するために使用するswitchアクティビティの代替手段として提供されています。アクティビティのスキップ条件は、次のように指定します。

<activity bpelx:skipCondition="boolean-expr"/>

bpelx:skipCondition属性により、アクティビティ・インスタンスが作成されるとすぐに、XPath式が評価されます。スキップ式でfalseのブール値が返された場合は、アクティビティが実行されます。スキップ式でtrueのブール値が返された場合、アクティビティは即時に完了となり、そのアクティビティの直後のアクティビティに実行が移動します。

11.5.1 アクティビティの実行をバイパスするためのXPath式の指定方法

アクティビティの実行をバイパスするためのXPath式を指定するには:

  1. 「コンポーネント」ウィンドウで、「BPELコンストラクト」を展開します。
  2. スキップ条件を作成するアクティビティをデザイナにドラッグします。
  3. 「スキップ条件」タブをクリックします。
  4. trueと評価された場合にアクティビティをスキップさせるXPath式を指定します。図11-12に詳細を示します。

    図11-12 スキップ条件XPath式

    図11-12の説明が続きます
    「図11-12 スキップ条件XPath式」の説明
  5. 「適用」をクリックし、「OK」をクリックします。

11.5.2 アクティビティの実行をバイパスするためのXPath式指定時の処理内容

.bpelファイルのコード・セグメントは、特定の操作に対する設計完了後の定義を示しています。

たとえば、次のコードに示されているXPath式は、trueと評価された場合に(たとえば、input20)、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属性を示しています。myvalue0の場合、式はtrueと評価され、assignアクティビティがスキップされます。myvalue10の場合、式は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条件がブール値に評価されない場合にスローされるフォルトと同じです。このフォルトも、デバッグのために監査証跡に記録されます。