Skip to main content

This documentation is for an older version of this product. See the latest version of this content.Opens in a new tab

BPL のエラー処理

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

Important:

このエラー処理システムを、他のビジネス・ホストと通信する <call> 文と共に使用するときは、エラーの場合にターゲット・ビジネス・ホストがエラー・ステータスを返すことを確認します。エラーの場合でもターゲット・コンポーネントが成功を返すと、BPL プロセスは <catchhall> ロジックをトリガしません。

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

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

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

BPL diagram with the following shapes in order: start, empty trace, assign, empty trace, end

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

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

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

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

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

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

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

Two error messages stacked on top of each other

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

この 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> の内容が表示されます。

BPL diagram showing a rectangle with a dotted line across the middle surrounding several elements

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

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

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

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

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

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

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

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

    BPL diagram with the following elements in order: start, trace, trace, end

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

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

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

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

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

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

Error message stacked above a log entry for in catchall faulthandler

予期しないシステム・エラーが発生した場合、<scope> 内に <faulthandlers> ブロックがあるときは、“システム・エラー - エラー処理なし” の例とは異なり、イベント・ログにエントリが自動的には出力されません。ビジネス・プロセスが何を実行するかは、<faulthandlers> ブロックによって決定されます。この例では、エラーに関する情報を含む <trace> メッセージを出力します。実際のエラーを示すイベント・ログ・エントリは、<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 値がエラー “ObjectScript エラー” (コード 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> 要素が表示されていません。

BPL diagram with several shapes surrounded by a rectangle with a dashed line in the middle

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

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

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

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

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

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

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

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

    BPL diagram with the following elements in order: start, trace, trace, trace, end

  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 を生成します。

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

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

Error message stacked above in catchall faulthandler

この 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 があるとします。

BPL diagram with several shapes surrounded by a rectangle that has a dashed line in the middle

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

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

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

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

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

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

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

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

    BPL diagram with the following shapes in order: start, trace, end

    Note:

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

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

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

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

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

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

Event log with entries for before scope, before throw, in catchall faulthandler, and after scope

この 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> 要素が省略されています)。

Complex BPL diagram with nested scope shapes, resulting in nested rectangles

この 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> が存在するため、ここに制御が移ります。

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

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

    BPL diagram with the following shapes in order: start, trace, end

  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 を生成します。

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

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

Event log showing that nested scopes are identified with the terms inner scope and outer scope

この 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 があるとします (部分的に表示されています)。

Partial BPL diagram with nested scope elements

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

Partial BPL diagram with five shapes: trace, catchall, join, trace, end

この 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> がありません。

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

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

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

    BPL diagram with the following shapes in order: start, trace, end

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

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

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

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

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

Event log with entries for inner and outer scope elements

この 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 があるとします (部分的に表示されています)。

BPL diagram with nested scopes

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

Partial BPL diagram with the following elements in order: trace, catch, join, trace, end

この 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 が即座に停止して、メッセージがイベント・ログに送信されます。

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

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

Event log with error after inner scope and before assign elements

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

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

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

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

ERROR #5002: ObjectScript 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 があるとします (部分的に表示されています)。

Partial BPL diagram with nested scopes

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

Partial BPL diagram with the following elements in order: trace, catch, catchall, join, trace, and end

この 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 を生成します。

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

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

Event log with entries for inner and outer scope elements

この 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 があるとします。

Complex BPL diagram with compensationhandler element in scope element

この 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> 要素を掘り下げる場合は、以下を参照してください。

    BPL diagram with the following shapes in order: start, trace, trace, compensate, trace, end

  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 の現在値が続きます。

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

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

Event log with several entries

この 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