Skip to main content

This is documentation for Caché & Ensemble. See the InterSystems IRIS version of this content.Opens in a new tab

For information on migrating to InterSystems IRISOpens in a new tab, see Why Migrate to InterSystems IRIS?

BPL のエラー処理

ここでは、BPL ビジネス・プロセスでのエラー処理について説明します。BPL は、ビジネス・プロセスがエラーをスロー/キャッチできるようにするためのエラー・ハンドラ、およびエラーの発生原因となったアクションを元に戻すことによって、エラーから復帰する方法を指定するための補償ハンドラを備えています。

エラー処理で呼び出される BPL 要素は、<scope>、<throw>、<catch>、<catchall>、<compensate>、<compensationhandlers>、<compensationhandler>、および <faulthandlers> です。このトピックでは、これらの要素の役割、およびこれらの要素が連携して、以下のシナリオのようなエラーを処理するしくみについて説明します。

システム・エラー - エラー処理なし

以下は、エラー状態を生成し、エラー処理を行わない BPL ビジネス・プロセスの例です。

generated description: errorbpl 1

この BPL ビジネス・プロセスは以下の処理を実行します。

  1. 最初の <trace> 要素がメッセージの before assign を生成します。

  2. <assign> 要素が SomeProperty を式 1/0 と同じに設定しようとします。この試みによって 0 による除算システム・エラーが発生します。

  3. ビジネス・プロセスが終了し、メッセージがイベント・ログに送信されます。

    2 つ目の <trace> 要素が使用されることはありません。

イベント・ログ・エントリ

この場合、Ensemble イベント・ログのエントリは以下のようになります。

generated description: error 1

基礎的な情報は、"Ensemble プロダクションの管理" の “イベント・ログ” の章を参照してください。

この BPL 用の XData

この BPL は以下の XData ブロックによって定義されます。

XData BPL
{
<process language='objectscript'
         request='Test.Scope.Request'
         response='Test.Scope.Response' >
  <sequence>
    <trace value='"before assign"'/>
    <assign property="SomeProperty" value="1/0"/>
    <trace value='"after assign"'/>
  </sequence>
</process>
}

システム・エラー - Catchall で対応

エラー処理に対応するため、BPL には <scope> と呼ばれる要素があります。スコープは一連のアクティビティのラッパです。このスコープには、1 つ以上のアクティビティ、1 つ以上のフォールト・ハンドラ、ゼロ個以上の補償ハンドラを含めることができます。フォールト・ハンドラの目的は、<scope> 内のアクティビティによって生成されるすべてのエラーをキャッチすることです。また、補償ハンドラを呼び出して、発生したエラーに対処することもできます。

下の例では、<scope> 内に <faulthandlers> ブロックを配置し、さらに <catchall> を追加しています。<scope> に <faulthandlers> 要素が含まれているため、長方形の中央を横切る水平点線が追加されます。この線の下側の領域に、<faulthandlers> の内容が表示されます。

generated description: errorbpl 2

この BPL ビジネス・プロセスは以下の処理を実行します。

  1. 最初の <trace> 要素がメッセージの before scope を生成します。

  2. <scope> 要素はスコープの始まりです。

  3. 2 つ目の <trace> 要素がメッセージの before assign を生成します。

  4. <assign> 要素が式 1/0 を評価しようとします。この試みによって 0 による除算システム・エラーが発生します。

  5. これで、制御が <scope> 内で定義された <faulthandlers> に移ります。<scope> 長方形に、中央を横切る水平点線が追加されます。この点線の下側の領域に <faulthandlers> 要素の内容が表示されます。この場合は、<catch> が存在しませんが、<catchall> 要素が存在するため、ここに制御が移ります。

    Ensemble は、<assign> 要素の直後の <trace> 要素メッセージを無視することに注意してください。

    <catchall> を掘り下げる場合は、以下を参照してください。

    generated description: errorbpl 2 drilldown

  6. <catchall> 内部で、<trace> 要素がメッセージの in catchall faulthandler を生成します。

  7. <catchall> 内部で、別の <trace> 要素が $System.Status メソッドと特殊変数の %Context%LastError を使用してエラーの特性を調査するメッセージを生成します。詳細は、“イベント・ログ・エントリ” を参照してください。

  8. <scope> が終わります。

  9. 最後の <trace> 要素がメッセージの after scope を生成します。

イベント・ログ・エントリ

この場合、Ensemble イベント・ログのエントリは以下のようになります。

generated description: error 2

予期しないシステム・エラーが発生した場合、<scope> 内に <faulthandlers> ブロックがあるときは、“システム・エラー - エラー処理なし” の例とは異なり、イベント・ログにエントリが自動的には出力されません。ビジネス・プロセスが何を実行するかは、<faulthandlers> ブロックによって決定されます。この例では、エラーに関する情報を含む <trace> メッセージを出力します。上記のイベント・ログ・エントリ 4 は、<catchall> ブロック内の以下の文によって生成されます。

<trace value=
  '"%LastError "_
  $System.Status.GetErrorCodes(..%Context.%LastError)_
  " : "_
  $System.Status.GetOneStatusText(..%Context.%LastError)'
  />

BPL コンテキスト変数 %LastError には、常に %StatusOpens in a new tab 値が含まれます。<UNDEF> などの予期せぬシステム・エラーが発生した場合は、この %StatusOpens in a new tab 値がエラー “CacheError” (コード 5002) および特殊変数 $ZERROR のテキストから作成されます。%LastError から対応するエラー・コードとテキストを取得するには、上に示すように、$System.StatusGetErrorCodes メソッドと GetOneStatusText メソッドを使用して、それらを <trace> 文字列に連結します。

この BPL 用の XData

この BPL は以下の XData ブロックによって定義されます。

XData BPL
{
<process language='objectscript'
         request='Test.Scope.Request'
         response='Test.Scope.Response' >
  <sequence>
    <trace value='"before scope"'/>
    <scope>
      <trace value='"before assign"'/>
      <assign property="SomeProperty" value="1/0"/>
      <trace value='"after assign"'/>
      <faulthandlers>
        <catchall>
          <trace value='"in catchall faulthandler"'/>
          <trace value=
            '"%LastError "_
            $System.Status.GetErrorCodes(..%Context.%LastError)_
            " : "_
            $System.Status.GetOneStatusText(..%Context.%LastError)'
            />
        </catchall>
      </faulthandlers>
    </scope>
    <trace value='"after scope"'/>
  </sequence>
</process>
}

フォールトをスロー - Catchall で対応

<throw> 文を実行するとき、その fault 値は結果が文字列となる式です。Java のような他のオブジェクト指向言語と異なり、フォールトはオブジェクトではなく、文字列値です。フォールト文字列を指定するときは、以下のように、1 組の引用符を余分に追加する必要があります

<throw fault='"thrown"'/>

<throw> 文が実行されると、即座に、同じ <scope> 内の <faulthandlers> ブロックに制御が移り、<throw> 以降の途中の文はすべて省略されます。次にプログラムは、<faulthandlers> ブロック内で、<throw> 文の fault 文字列式と value 属性が同じである <catch> ブロックを探します。この比較では大文字と小文字が区別されます。

フォールトと一致する <catch> ブロックが見つかった場合は、その <catch> ブロック内のコードを実行して、<scope> から抜けます。終わりの </scope> 要素の次の文から実行を再開します。

フォールトがスローされ、フォールト文字列と一致する <catch> ブロックが <faulthandlers> ブロック内に存在しない場合は、制御が <throw> 文から <faulthandlers> 内の <catchall> ブロックに移ります。<catchall> ブロック内のコードを実行した後で、<scope> から抜けます。終わりの </scope> 要素の次の文から実行を再開します。予期しないエラーを確実にキャッチするため、すべての <faulthandlers> ブロック内に <catchall> ブロックを配置することをお勧めします。

以下の BPL があるとします。スペースの関係で、<start> 要素と <end> 要素が表示されていません。

generated description: errorbpl 3

この BPL ビジネス・プロセスは以下の処理を実行します。

  1. 最初の <trace> 要素がメッセージの before scope を生成します。

  2. <scope> 要素はスコープの始まりです。

  3. 2 つ目の <trace> 要素がメッセージの before assign を生成します。

  4. <throw> 要素が特定の名前付きフォールト ("MyFault") をスローします。

  5. これで、制御が <scope> 内で定義された <faulthandlers> に移ります。<scope> 長方形に、中央を横切る水平点線が追加されます。この点線の下側の領域に <faulthandlers> 要素の内容が表示されます。この場合は、<catch> が存在しませんが、<catchall> 要素が存在するため、ここに制御が移ります。

    Ensemble は 3 つ目の <trace> 要素を無視することに注意してください。

    <catchall> を掘り下げる場合は、以下を参照してください。

    generated description: errorbpl 3 drilldown

  6. <catchall> 内部で、最初の <trace> 要素がメッセージの in catchall faulthandler を生成します。

  7. <catchall> 内部で、2 つ目の <trace> 要素が $System.Status メソッドと特殊変数の %Context%LastError を使用してフォールトに関する情報を提供するメッセージを生成します。フォールトがスローされた結果としての %LastError は、システム・エラーの結果としての値と異なります。

    • GetErrorCodes<Ens>ErrBPLThrownFault を返します。

    • GetOneStatusText は、<throw> 文の fault 式から得られたテキストを返します。

  8. <catchall> 内部で、3 つ目の <trace> 要素が BPL コンテキスト変数の %LastFault を使用してフォールトに関する情報を提供するメッセージを生成します。このメッセージには、<throw> 文の fault 式から得られたテキストが含まれます。

  9. <scope> が終わります。

  10. 最後の <trace> 要素がメッセージの after scope を生成します。

イベント・ログ・エントリ

この場合、Ensemble イベント・ログのエントリは以下のようになります。

generated description: error 3

この BPL 用の XData

この BPL は以下の XData ブロックによって定義されます。

XData BPL
{
<process language='objectscript'
         request='Test.Scope.Request'
         response='Test.Scope.Response' >
  <sequence>
    <trace value='"before scope"'/>
    <scope>
      <trace value='"before assign"'/>
      <throw fault='"MyFault"'/>
      <trace value='"after assign"'/>
      <faulthandlers>
        <catchall>
          <trace value='"in catchall faulthandler"'/>
          <trace value=
            '"%LastError "_
            $System.Status.GetErrorCodes(..%Context.%LastError)_
            " : "_
            $System.Status.GetOneStatusText(..%Context.%LastError)'
            />
          <trace value='"%LastFault "_..%Context.%LastFault'/>
        </catchall>
      </faulthandlers>
    </scope>
    <trace value='"after scope"'/>
  </sequence>
</process>
}

フォールトをスロー - Catch で対応

前述の例のように、スローされたフォールトを <catchall> で処理する以外に、特定の <catch> を使用することもできます。

以下の BPL があるとします。

generated description: errorbpl 4

この BPL ビジネス・プロセスは以下の処理を実行します。

  1. 最初の <trace> 要素がメッセージの before scope を生成します。

  2. <scope> 要素はスコープの始まりです。

  3. 2 つ目の <trace> 要素がメッセージの before throw を生成します。

  4. <throw> 要素が特定の名前付きフォールト ("MyFault") をスローします。

  5. これで、制御が <scope> 内で定義された <faulthandlers> に移ります。<scope> 長方形に、中央を横切る水平点線が追加されます。この点線の下側の領域に <faulthandlers> 要素の内容が表示されます。この場合は、fault 値が "MyFault" の <catch> 要素が存在するため、ここに制御が移ります。<catchall> 要素は無視されます。

    Ensemble は、<throw> 要素以降の <trace> 要素メッセージを無視することに注意してください。

    <catch> を掘り下げる場合は、以下を参照してください。

    generated description: errorbpl 4 drilldown

    Note:

    <catchall> を設ける場合は、それを <faulthandlers> ブロックの最後の文にする必要があります。必ず、<catchall> の前にすべての <catch> ブロックを配置します。

  6. <catch> 内部で、<trace> 要素がメッセージの in catch faulthandler for ‘MyFault’ を生成します。

  7. <scope> が終わります。

  8. 最後の <trace> 要素がメッセージの after scope を生成します。

イベント・ログ・エントリ

この場合、Ensemble イベント・ログのエントリは以下のようになります。

generated description: error 4

この BPL 用の XData

この BPL は以下の XData ブロックによって定義されます。

XData BPL
{
<process language='objectscript'
         request='Test.Scope.Request'
         response='Test.Scope.Response' >
  <sequence>
    <trace value='"before scope"'/>
    <scope>
      <trace value='"before throw"'/>
      <throw fault='"MyFault"'/>
      <trace value='"after throw"'/>
      <faulthandlers>
        <catch fault='"MyFault"'>
          <trace value='"In catch faulthandler for &apos;MyFault&apos;"'/>
        </catch>
        <catchall>
          <trace value='"in catchall faulthandler"'/>
          <trace value=
            '"%LastError "_
            $System.Status.GetErrorCodes(..%Context.%LastError)_
            " : "_
            $System.Status.GetOneStatusText(..%Context.%LastError)'
            />
          <trace value='"%LastFault "_..%Context.%LastFault'/>
        </catchall>
      </faulthandlers>
    </scope>
    <trace value='"after scope"'/>
  </sequence>
</process>
}

ネスト構造のスコープ - 内側のフォールト・ハンドラに Catchall を配置

<scope> 要素をネスト構造にできます。内側のスコープでエラーやフォールトが発生した場合、内側のスコープ内でキャッチする方法と、内側のスコープはそのエラーを無視し、外側スコープの <faulthandlers> ブロックでキャッチする方法があります。この後のトピックでは、複数のスコープがネストされているとき、内側のスコープで発生したエラーやフォールトを BPL がどのように処理するかを説明します。

以下の BPL があるとします (ここでは、<start> 要素と <end> 要素が省略されています)。

generated description: errorbpl 5

この BPL ビジネス・プロセスは以下の処理を実行します。

  1. 最初の <trace> 要素がメッセージの before outer scope を生成します。

  2. 最初の <scope> 要素は外側のスコープの始まりです。

  3. 2 つ目の <trace> 要素がメッセージの in outer scope, before inner scope を生成します。

  4. 2 つ目の <scope> 要素は内側のスコープの始まりです。

  5. 次の <trace> 要素がメッセージの in inner scope, before assign を生成します。

  6. <assign> 要素が式 1/0 を評価しようとします。この試みによって 0 による除算システム・エラーが発生します。

  7. これで、制御が内側の <scope> 内で定義された <faulthandlers> に移ります。この <scope> 長方形に、中央を横切る水平点線が追加されます。この点線の下側の領域に <faulthandlers> 要素の内容が表示されます。この場合は、<catch> が存在しませんが、<catchall> が存在するため、ここに制御が移ります。

    Ensemble は、<assign> 要素の直後の <trace> 要素を無視することに注意してください。

    この <catchall> を掘り下げる場合は、以下を参照してください。

    generated description: errorbpl 5 drilldown

  8. <catchall> 内部で、<trace> 要素がメッセージの in inner scope, catchall を生成します。

  9. 内側の <scope> が終わります。

  10. 次の <trace> 要素がメッセージの in outer scope, after inner scope を生成します。

  11. 外側の <scope> 長方形に、中央を横切る水平点線が追加されます。この点線の下側の領域に <catchall> を含む <faulthandlers> 要素の内容が表示されます。フォールトが存在しないため、この <catchall> は無視されます。

  12. 外側の <scope> が終わります。

  13. 最後の <trace> 要素がメッセージの after outer scope を生成します。

イベント・ログ・エントリ

この場合、Ensemble イベント・ログのエントリは以下のようになります。

generated description: error 5

この BPL 用の XData

この BPL は以下の XData ブロックによって定義されます。

XData BPL
{
<process language='objectscript'
         request='Test.Scope.Request'
         response='Test.Scope.Response' >
  <sequence>
    <trace value='"before outer scope"'/>
    <scope>
      <trace value='"in outer scope, before inner scope"'/>
      <scope>
        <trace value='"in inner scope, before assign"'/>
        <assign property="SomeProperty" value="1/0"/>
        <trace value='"in inner scope, after assign"'/>
        <faulthandlers>
          <catchall>
            <trace value='"in inner scope, catchall"'/>
          </catchall>
        </faulthandlers>
      </scope>
      <trace value='"in outer scope, after inner scope"'/>
      <faulthandlers>
        <catchall>
          <trace value='"in outer scope, catchall"'/>
        </catchall>
      </faulthandlers>
    </scope>
    <trace value='"after outer scope"'/>
  </sequence>
</process>
}

ネスト構造のスコープ - 外側のフォールト・ハンドラに Catchall を配置

以下の BPL があるとします (部分的に表示されています)。

generated description: errorbpl 6 top

この BPL の残りを以下に示します。

generated description: errorbpl 6 bottom

この BPL ビジネス・プロセスは以下の処理を実行します。

  1. 最初の <trace> 要素がメッセージの before outer scope を生成します。

  2. 最初の <scope> 要素は外側のスコープの始まりです。

  3. 次の <trace> 要素がメッセージの in outer scope, before inner scope を生成します。

  4. 2 つ目の <scope> 要素は内側のスコープの始まりです。

  5. 次の <trace> 要素がメッセージの in inner scope, before assign を生成します。

  6. <assign> 要素が式 1/0 を評価しようとします。この試みによって 0 による除算システム・エラーが発生します。

  7. これで、制御が内側の <scope> 内で定義された <faulthandlers> に移ります。この <scope> 長方形に、中央を横切る水平点線が追加されます。この点線の下側の領域に <faulthandlers> 要素の内容が表示されます。この場合は、<catch> が存在しますが、その fault 値が、スローされたフォールトと一致しません。内側のスコープには <catchall> がありません。

    Ensemble は、<assign> の直後の <trace> 要素を無視することに注意してください。

  8. これで、制御が外側の <scope> 内の <faulthandlers> ブロックに移ります。どの <catch> もフォールトと一致しませんが、<catchall> ブロックがあります。制御がこの <catchall> に移ります。

    この <catchall> を掘り下げる場合は、以下を参照してください。

    generated description: errorbpl 6 drilldown

  9. <catchall> 内部で、<trace> 要素がメッセージの in inner scope, catchall を生成します。

  10. 外側の <scope> が終わります。

  11. 最後の <trace> 要素がメッセージの after outer scope を生成します。

イベント・ログ・エントリ

この場合、Ensemble イベント・ログのエントリは以下のようになります。

generated description: error 6

この BPL 用の XData

この BPL は以下の XData ブロックによって定義されます。

XData BPL
{
<process language='objectscript'
         request='Test.Scope.Request'
         response='Test.Scope.Response' >
  <sequence>
    <trace value='"before outer scope"'/>
    <scope>
      <trace value='"in outer scope, before inner scope"'/>
      <scope>
        <trace value='"in inner scope, before assign"'/>
        <assign property="SomeProperty" value="1/0"/>
        <trace value='"in inner scope, after assign"'/>
        <faulthandlers>
          <catch fault='"MismatchedFault"'>
            <trace value=
              '"In catch faulthandler for &apos;MismatchedFault&apos;"'/>
          </catch>
        </faulthandlers>
      </scope>
      <trace value='"in outer scope, after inner scope"'/>
      <faulthandlers>
        <catchall>
          <trace value='"in outer scope, catchall"'/>
        </catchall>
      </faulthandlers>
    </scope>
    <trace value='"after outer scope"'/>
  </sequence>
</process>
}

ネスト構造のスコープ - どのスコープでも一致しない場合

以下の BPL があるとします (部分的に表示されています)。

generated description: errorbpl 7 top

この BPL の残りを以下に示します。

generated description: errorbpl 7 bottom

この BPL ビジネス・プロセスは以下の処理を実行します。

  1. 最初の <trace> 要素がメッセージの before outer scope を生成します。

  2. 最初の <scope> 要素は外側のスコープの始まりです。

  3. 次の <trace> 要素がメッセージの in outer scope, before inner scope を生成します。

  4. 2 つ目の <scope> 要素は内側のスコープの始まりです。

  5. 次の <trace> 要素がメッセージの in inner scope, before assign を生成します。

  6. <assign> 要素が式 1/0 を評価しようとします。この試みによって 0 による除算システム・エラーが発生します。

  7. これで、制御が内側の <scope> 内の <faulthandlers> ブロックに移ります。<scope> 長方形に、中央を横切る水平点線が追加されます。この点線の下側の領域に <faulthandlers> 要素の内容が表示されます。この場合は、<catch> が存在しますが、その fault 値が、スローされたフォールトと一致しません。内側のスコープには <catchall> がありません。

  8. これで、制御が外側の <scope> 内の <faulthandlers> ブロックに移ります。どの <catch> もフォールトと一致しません。また、<catchall> ブロックもありません。

  9. BPL が即座に停止して、メッセージがイベント・ログに送信されます。

イベント・ログ・エントリ

この場合、Ensemble イベント・ログのエントリは以下のようになります。

generated description: error 7

上記のイベント・ログと、“システム・エラー - エラー処理なし” で紹介したイベント・ログ例との間には重要な相違点があります。これら 2 つの例の共通点は、ゼロによる除算のエラーが発生した場合の適切なフォールト処理が設けられていないことです。

ただし、“システム・エラー - エラー処理なし” の例には <scope> がなく、<faulthandlers> ブロックもありません。このような状況では、最初の例で示したように、Ensemble は、自動的に、システム・エラーをイベント・ログに出力します。

一方、上記の例では、各 <scope> に <faulthandlers> ブロックが含まれています。このような場合は、“システム・エラー - エラー処理なし” の例と異なり、イベント・ログにシステム・エラーが自動的には出力されません。予期しないエラーが発生したとき <trace> メッセージをイベント・ログに出力するかどうかは、BPL ビジネス・プロセス開発者が決定します。この例には、フォールトをキャッチする <faulthandlers> ブロックがありません。ビジネス・プロセスの終了に関する自動メッセージには、システム・エラーのトレース情報のみが含まれます (上記の 4 番)。

ただし、システム・エラー・メッセージがターミナル・ウィンドウに表示されます。

ERROR #5002: Cache error: <DIVIDE>zS4+3^Test.Scope.BusinessProcess.Thread1.1

この BPL 用の XData

この BPL は以下の XData ブロックによって定義されます。

XData BPL
{
<process language='objectscript'
         request='Test.Scope.Request'
         response='Test.Scope.Response' >
  <sequence>
    <trace value='"before outer scope"'/>
    <scope>
      <trace value='"in outer scope, before inner scope"'/>
      <scope>
        <trace value='"in inner scope, before assign"'/>
        <assign property="SomeProperty" value="1/0"/>
        <trace value='"in inner scope,after assign"'/>
        <faulthandlers>
          <catch fault='"MismatchedFault"'>
            <trace value=
              '"In catch faulthandler for &apos;MismatchedFault&apos;"'/>
          </catch>
        </faulthandlers>
      </scope>
      <trace value='"in outer scope, after inner scope"'/>
      <faulthandlers>
        <catch fault='"MismatchedFault"'>
          <trace value=
            '"In catch faulthandler for &apos;MismatchedFault&apos;"'/>
        </catch>
      </faulthandlers>
    </scope>
    <trace value='"after outer scope"'/>
  </sequence>
</process>
}

ネスト構造のスコープ - 外側のフォールト・ハンドラに Catch を配置

以下の BPL があるとします (部分的に表示されています)。

generated description: errorbpl 8 top

この BPL の残りを以下に示します。

generated description: errorbpl 8 bottom

この BPL ビジネス・プロセスは以下の処理を実行します。

  1. 最初の <trace> 要素がメッセージの before outer scope を生成します。

  2. 最初の <scope> 要素は外側のスコープの始まりです。

  3. 次の <trace> 要素がメッセージの in outer scope, before inner scope を生成します。

  4. 2 つ目の <scope> 要素は内側のスコープの始まりです。

  5. 次の <trace> 要素がメッセージの in inner scope, before throw を生成します。

  6. <throw> 要素が特定の名前付きフォールト ("MyFault") をスローします。

  7. これで、制御が内側の <scope> 内で定義された <faulthandlers> に移ります。<catch> は存在しますが、その fault 値は "MismatchedFault" です。内側のスコープには <catchall> がありません。

  8. 制御が外側の <scope> 内の <faulthandlers> ブロックに移ります。このブロックには、fault 値が "MyFault" の <catch> が含まれます。

  9. 次の <trace> 要素がメッセージの in outer scope catch faulthandler for 'MyFault' を生成します。

  10. 2 つ目の <scope> が終わります。

  11. 最後の <trace> 要素がメッセージの after outer scope を生成します。

イベント・ログ・エントリ

この場合、Ensemble イベント・ログのエントリは以下のようになります。

generated description: error 8

この BPL 用の XData

この BPL は以下の XData ブロックによって定義されます。

XData BPL
{
<process language='objectscript'
         request='Test.Scope.Request'
         response='Test.Scope.Response' >
  <sequence>
    <trace value='"before outer scope"'/>
    <scope>
      <trace value='"in outer scope, before inner scope"'/>
      <scope>
        <trace value='"in inner scope, before throw"'/>
        <throw fault='"MyFault"'/>
        <trace value='"in inner scope, after throw"'/>
        <faulthandlers>
          <catch fault='"MismatchedFault"'>
            <trace value=
    '"In inner scope catch faulthandler for &apos;MismatchedFault&apos;"'/>
          </catch>
        </faulthandlers>
      </scope>
      <trace value='"in outer scope, after inner scope"'/>
      <faulthandlers>
        <catch fault='"MyFault"'>
          <trace value=
            '"In outer scope catch faulthandler for &apos;MyFault&apos;"'/>
        </catch>
      </faulthandlers>
    </scope>
    <trace value='"after outer scope"'/>
  </sequence>
</process>
}

フォールトをスロー - 補償ハンドラで対応

ビジネス・プロセス管理では、一部のロジック・セグメントを元に戻す必要が頻繁に生じます。この処理を “補償” といいます。原則として、ビジネス・プロセスが何かを実行する場合、その操作を取り消すことができる必要があります。つまり、エラーが発生した場合、ビジネス・プロセスは失敗した操作を元に戻すことによって、そのエラーを補償できる必要があります。障害発生時点以降のすべての操作を取り消し、問題が発生しなかった場合と同じ状態に戻す必要があります。BPL では、補償ハンドラと呼ばれるしくみによってこれを実現します。

BPL <compensationhandler> ブロックはサブルーチンに似ていますが、一般的なサブルーチン・メカニズムを備えていません。これらのブロックを “呼び出す” ことは可能ですが、必ず<faulthandler> ブロックから呼び出すこと、かつ、必ずその <compensationhandler> ブロックと同じ <scope> 内から呼び出すことが条件となります。<compensate> 要素から <compensationhandler> ブロックを呼び出すときは、ターゲットとしてその名前を指定します。この構文では、引用符を追加する必要がありません

<compensate target="general"/>

補償ハンドラが役に立つのは、既に実行されている処理を元に戻せる場合だけです。例えば、預金を間違った口座に振り替えた場合、元の口座に振り替え直すことは可能ですが、元どおりの状態にできない処理もあります。したがって、適切な補償ハンドラを計画し、どの程度後退するのかに応じて、それらの補償ハンドラを構成する必要があります。

以下の BPL があるとします。

generated description: errorbpl 9

この BPL ビジネス・プロセスは以下の処理を実行します。

  1. [コンテキスト] タブ (非表示) は、MyBalance という名前のプロパティを定義して、その値を 100 に設定します。

  2. 最初の <trace> 要素がメッセージの before scope balance is を生成し、その後に MyBalance の値が続きます。

  3. <scope> 要素はスコープの始まりです。

  4. 次の <trace> 要素がメッセージの before debit を生成します。

  5. <assign> 要素が MyBalance を 1 減らします。

  6. 次の <trace> 要素がメッセージの after debit を生成します。

  7. <throw> 要素が特定の名前付きフォールト ("BuyersRegret") をスローします。

  8. これで、制御が <faulthandlers> に移ります。fault 値が "BuyersRegret" の <catch> が存在するため、ここに制御が移ります。

    この <catch> 要素を掘り下げる場合は、以下を参照してください。

    generated description: errorbpl 9 drilldown

  9. この <catch> 内部で、<trace> 要素がメッセージの in catch faulthandler for 'BuyersRegret' を生成します。

  10. この <catch> 内部で、2 つ目の <trace> 要素がメッセージの before restore balance is を生成し、その後ろに MyBalance の現在値が続きます。

  11. <compensate> 要素が使用されます。この要素の場合は、target が、name が RestoreBalance の <compensationhandler> です。この <compensationhandler> ブロックで以下の処理を実行します。

    • <trace> 文により、メッセージ “Restoring Balance” を出力します。

    • <assign> 文を実行して、MyBalance を 1 増やします。

    Note:

    <compensationhandlers> と <faulthandlers> の順序を逆にすることはできません。これら両方のブロックを記述する場合は、最初に <compensationhandlers>、次に <faulthandlers> を配置する必要があります。

  12. 次の <trace> 要素がメッセージの after restore balance is を生成し、その後に MyBalance の現在値が続きます。

  13. <scope> が終わります。

  14. 最後の <trace> 要素がメッセージの after scope balance is を生成し、その後に MyBalance の現在値が続きます。

イベント・ログ・エントリ

この場合、Ensemble イベント・ログのエントリは以下のようになります。

generated description: error 9

この BPL 用の XData

この BPL は以下の XData ブロックによって定義されます。

XData BPL
{
<process language='objectscript'
         request='Test.Scope.Request'
         response='Test.Scope.Response' >
  <context>
    <property name="MyBalance" type="%Library.Integer" initialexpression='100'/>
  </context>
  <sequence>
    <trace value='"before scope balance is "_context.MyBalance'/>
    <scope>
      <trace value='"before debit"'/>
      <assign property='context.MyBalance' value='context.MyBalance-1'/>
      <trace value='"after debit"'/>
      <throw fault='"BuyersRegret"'/>
      <compensationhandlers>
        <compensationhandler name="RestoreBalance">
          <trace value='"Restoring Balance"'/>
          <assign property='context.MyBalance' value='context.MyBalance+1'/>
        </compensationhandler>
      </compensationhandlers>
      <faulthandlers>
        <catch fault='"BuyersRegret"'>
          <trace value='"In catch faulthandler for &apos;BuyersRegret&apos;"'/>
          <trace value='"before restore balance is "_context.MyBalance'/>
          <compensate target="RestoreBalance"/>
          <trace value='"after restore balance is "_context.MyBalance'/>
        </catch>
        <catchall>
          <trace value='"in catchall faulthandler"'/>
          <trace value=
            '"%LastError "_
            $System.Status.GetErrorCodes(..%Context.%LastError)_
            " : "_
            $System.Status.GetOneStatusText(..%Context.%LastError)'
            />
          <trace value='"%LastFault "_..%Context.%LastFault'/>
        </catchall>
      </faulthandlers>
    </scope>
    <trace value='"after scope balance is "_context.MyBalance'/>
  </sequence>
</process>
}
FeedbackOpens in a new tab