[SOA/BPM] Fault Management Framework by Example

概要
Fault Management Frameworkは、エラーハンドリングを外出しして、SOA/BPELの設計時、実行時に影響しないようにするためですことを目的としています。このフレームワークはXMLでポリシーを設定できます。ポリシーはコンポジット、コンポーネント間で流用可能で、ランタイムフォルト、ビジネスフォルトとも捕捉できます。フォルトを捕捉すると、ポリシーの定義に基づいてアクションを実施します。例えば、リトライ、人の介入、スコープの再生、やフォルトの再送、停止、カスタムのJavaコードの実行などです。人間による介入の場合、フォルトが発生したインスタンスを管理するためのUIをEnterprise Managerが提供しています。

ポリシーを定義し、コンポジットやコンポーネントに強制した場合、フレームワークは標準のフォルトハンドラが動作する前にフォルトを捕捉します。例えば、BPELプロセスが標準のフォルトハンドリングを持ち、フォルトポリシーが当該BPELプロセスに適用されている場合、フォルトが発生するとフレームワークはフォルトを捕捉し、インスタンスに適用されたアクションを実行させることができます。
フォルトポリシーファイルはサーバー起動と同時にロードされますので、ポリシーファイルへの変更を反映させるためにはサーバーの再起動が必要です。フォルトポリシーファイルの在処は、composite.xmlと同じ場所か、もしくはcomposite.xmlのプロパティ内で定義されている場所です。
<property name="oracle.composite.faultPolicyFile">
   oramds://apps/faultpolicyfiles/fault-policies.xml
</property>

<property name="oracle.composite.faultBindingFile">
   oramds://apps/faultpolicyfiles/fault-bindings.xml
</property>
composite.xmlでプロパティを使う場合、デフォルトと異なるファイル名を指定する必要があります。

Fault Policies (fault-policies.xml / fault-policies.xsd)
SOA SuiteのFault Management Frameworkのセットアップに必要な2個のXMLポリシーファイルがあります。まずfault-policies.xml、これにはフォルトポリシー定義、フォルト定義(条件も含めることができます)、アクションが記載されています。

注意: ポリシーファイル中の要素の大文字・小文字には注意して下さい。スキーマを強制するエディタをお持ちでない場合、<Action>のかわりに<action>のような要素を定義してしまいがちです。

<faultPolicy> Element
エンタープライズデプロイメントに含まれる、可能性のある全てのフォルトをもっと簡単に管理するため、複数のフォルトポリシーを使ってフォルトを論理的にグループ分けすることができます。各ポリシーは<faultPolicy> 要素で定義され、各ポリシー定義には固有のポリシーIDを持ちます。
<faultPolicy version="0.0.1" id="FusionMidFaults"
     xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
     xmlns:xs="http://www.w3.org/2001/XMLSchema"
     xmlns="http://schemas.oracle.com/bpel/faultpolicy"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<faultName> Element
<faultPolicy> 要素内に、<Conditions>要素で囲んだポリシーと関連づけられるあらゆるフォルトを定義します。各ポリシー名の定義はQName(例えばbpelx:remoteFault)によって識別されるフォルトと、関係づけられているアクションの”参照”が含まれている必要があります。さらに値を検査するためにXPath式を使用して障害を絞り込むことができます。(例:$fault.code="3220"):
<Conditions>
   <faultName
      xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
      name="bpelx:remoteFault”>
      <condition>
         <test>$fault.code="3220"</test>
         <action ref="ora-retry"/>
      </condition>
   </faultName>
...
</Conditions>
<Action> Element
</Conditions> 要素に続いて、<Actions>要素で囲んだポリシーに関係づけられている個別のアクションを定義します。各アクション定義は一意のAction Idと仕様を定義する必要があります。
...

   <Actions>

      <Action id="ora-retry">
         <retry>
            <retryCount>3</retryCount>
            <retryInterval>5</retryInterval>
            <exponentialBackoff/>
            <retryFailureAction ref="ora-terminate"/>
         </retry>
      </Action>

      <Action id="ora-terminate">
         <abort/>
      </Action>

   </Actions>

</faultPolicy>
製品のマニュアルをご覧になると、アクションIDが、すべて"ORA-"で始まる特定の用語を使用していることに気付くと思います。このせいで、IDが予約されていると誤解されることがありますが、実際には、任意の名前を使用することができます。それは、アクション定義が何を行うかを定義し、IDが「参照」として使用されているという、アクション仕様の要素です。 例えば、上記のコードスニペットには、ora-retryがretryFailureActionを含んでおり、これはora-terminateという別のアクション定義を参照しています。

Fault Bindings (fault-bindings.xml / fault-bindings.xsd)
Fault Management Frameworkで使われる2個目のポリシーファイルは、fault-bindings.xmlです。このファイルはfault-policies.xmlに定義されているポリシーをコンポジット内のレベルとバインドします。レベルには以下のものが含まれます。
  • コンポジットアプリケーション
  • コンポーネント
    • 参照(Reference)
    • BPELプロセス
    • Mediator
コンポジットアプリケーションとのバインディング
コンポジットアプリケーションとバインドする場合、<composite>要素とfaultPolicyと呼ばれる属性を使います。faultPolicy属性の値はfault-policies.xmlに定義したポリシーIDに一致する必要があります。
<composite faultPolicy="FusionMidFaults"/>
参照とのバインディング
参照とバインドする場合、<reference>要素とfaultPolicyと呼ばれる属性を使います。 faultPolicy属性の値はfault-policies.xmlに定義したポリシーIDに一致する必要があります。また、<name>や<portType>といった要素を指定する必要があります。
  <reference faultPolicy="FusionMidFaults">
    <name>creditRatingService</name>
    <portType xmlns:credit="http://services.otn.com">credit:CreditRatingService</portType>
  </reference>

  <reference faultPolicy="FusionMidFaults">
    <name>CreditApprovalService</name>
  </reference> 
BPELプロセスとのバインディング
BPELプロセスとバインドする場合、<component>要素とfaultPolicyと呼ばれる属性を使います。 faultPolicy属性の値はfault-policies.xmlに定義したポリシーIDに一致する必要があります。BPELプロセスの名前を<element>要素に指定する必要があります。
  <component faultPolicy="FusionMidFaults">
    <name>HelloWorld</name>
    <name>ShippingComponent</name>
  </component>
Mediatorとのバインディング
Mediatorとバインドする場合、<component>要素とfaultPolicyと呼ばれる属性を使います。faultPolicy属性の値はfault-policies.xmlに定義したポリシーIDに一致する必要があります。mediatorの名前を<element>要素に指定する必要があります。
  <component faultPolicy="FusionMidFaults">
    <name>RouteToShippingMediator</name>
  </component>
例 (bpel-300-FaultHandlingFramework_rev1.0.jar)
実際に動くサンプルで、記述した内容を理解してもらいたいので、Fault Management Frameworkが標準で提供する全ての機能(Javaコードの呼び出しなど)を説明する例を用意しました。
sca_bpel-300-FaultHandlingFramework_rev1.0.zip をダウンロードして、jarファイルを抽出して下さい。JDeveloperで新しいSOAプロジェクトを作成するか、もしくは”SOAアーカイブをSOAプロジェクトにインポート”でjarファイルをインポートして下さい。
インポートすると、次のような画面が現れるはずです。
この時点で、fault-policies.xml とfault-binding.xml の両ファイルを開き、内容を確認しましょう。複数のポリシーが定義されていて、ポリシーがコンポジットアプリケーション中の様々なレベルに対して適用されていることがわかります。ポリシーを確認したら、コンポジットをSOAサーバーにデプロイし、Enterprise Manager Fusion Middleware Controlを開いてデプロイしたコンポジットのテストページへ移動します。faultActionという値を指定して呼び出すような画面が現れます。
様々なシナリオを確認するため、次の値をfaultActionに指定してみましょう。
  • ora-retry
  • ora-human-intervention
  • ora-terminate
  • ora-rethrow-fault
  • ora-replay-scope
  • ora-java
  • mediator
  • throw-vs-reply  (詳細は以下を参照)
  • reply-with-fault(詳細は以下を参照)
faultActionに上記の値を設定して「Webサービスのテスト」ボタンを押下して、「フロートレースの起動」を押し、インスタンスを確認します。トレースと鑑査証跡を調べると、Fault Management Frameworkがどんな振る舞いをしているかがわかります。どうなっているかがわかると、ポリシーを変更して、コンポジットを再デプロイし、サーバーを再起動してから再度テストして、挙動の違いを確認してみてください。

throw-vs-reply / reply-with-fault
throw-vs-replyとreply-with-faultというfaultActionには少々説明が必要です。「悪い設計上の決定」が原因で、Fault Management Frameworkに関する混乱した状況に出くわしました。 混乱が発生したシナリオは以下の通りです。
  • BPELプロセスが別の同期型BPELプロセスを実行する
  • 2番目のBPELプロセスには、Receiveアクティビティの後にJMSアダプタを起動する、非同期フローを含む
  • BPELプロセスが同期型として定義されていて、JMSアダプタからのレスポンスがほぼ即時であったとしても、JMSアダプタはデハイドレーションを引き起こし、新しいスレッドがJMSの応答を取り上げて、結果を配信しようとする
  • 新しいスレッドがフォルトを送出した場合、元のスレッドはデハイドレーションされて無くなってしまっているので、BPELエンジンはこのフォルトを処理しようとする(つまり、最初のスレッドとFault Management Frameworkの相関が無くなっている、ということ)。さらに、元のBPELプロセスの"Invoke"アクティビティはレスポンスがない、もしくはフォルトが届くために、タイムアウトになってしまう。
このシナリオにおいて、相関を取り戻す方法があります。例外を「投げる」のではなく、ペイロードに例外を付加して「応答」する、というものです。

この例では簡単のためにJMSアダプタのシナリオを実装しませんでしたが、そのかわりにFaultGeneratorBPELProcessにSleepアクティビティを入れ、強制的にでハイドレーションするようにして同じ振る舞いをするようにしています。「混乱するポイント」を確認するために、throw-vs-replyをfaultActionに指定し、タイムアウトの例外が発生することを確認しましょう。「解決法や想定される振る舞い」をみたい場合には、reply-with-faultをfaultActionに指定して下さい。FaultGeneratorBPELProcessのロジックをご覧になって、 throw-vs-reply とreply-with-faultでどんなことをしているか確認されることをお勧めします。

このエントリが、Fault Management Frameworkとその機能に関する貴重な見識を提供できていればとても幸甚に思います。


原文はこちら。
http://blogs.oracle.com/ateamsoab2b/entry/fault_management_framework_by_example

0 件のコメント:

コメントを投稿