エラー処理のための ESQL のコーディング

概要

メッセージ・フロー内のメッセージを処理する際のエラーの原因として、次のものが考えられます。
  1. 外部的な原因。 例えば、着信メッセージが構文的に無効である、フローによって使用されるデータベースがシャットダウンされている、またはブローカーが実行されているマシンへの電源機構で障害が発生している、などです。
  2. 内部エラー。 例えば、制約チェックのため行をデータベース表に挿入しようとする試みが失敗する、またはデータベースから読み取られる文字ストリングに英字が含まれるため数値に変換できない、などです。

    内部エラーは、データベースに無効なデータを保管しているプログラム、またはフローのロジックの不備によって生じる可能性があります。

メッセージ・フローの設計者は、エラーを真剣に考慮し、その処理方法を決めておく必要があります。

デフォルトのエラー処理の使用

ESQL エラーの処理に関する最も単純な方針は、何もしないでブローカーのデフォルトの動作を使用することです。 デフォルトでは、失敗したメッセージの処理を切り上げて、次のメッセージに進みます。 入出力ノードは、処理を切り上げたときの動作を正確に制御するオプションを提供します。

入出力ノードがトランザクションのモードに設定される場合、ブローカーはメッセージが処理される前に状態を復元します。
  1. 入力キューから取られたと思われる入力メッセージは書き戻される。
  2. フローが出力キューに書き込んだと思われる出力メッセージはすべて廃棄される。
入出力ノードがトランザクションのモードに設定されていない場合は、次のようになります。
  1. 入力キューから取られた入力メッセージは書き戻されない。
  2. フローが出力キューに書き込んだ出力メッセージはすべてそこに留まる。

これらの方針にはそれぞれに利点があります。 トランザクションのモデルがデータの整合性を保持する一方、非トランザクションのモデルではメッセージ処理の継続性が最大になります。 なお、トランザクションのモデルでは、失敗する入力メッセージは入力キューに書き戻され、ブローカーは処理を再試行します。 この結果として、ほとんどの場合、メッセージは再試行の限界に達するまで失敗し続けます。 その限界に達すると、メッセージはデッド・レター・キューに置かれます。 メッセージ処理失敗の理由は、システム・イベント・ログ (Windows) または SYSLOG (UNIX) に記録されます。 こうして、失敗メッセージは後続の良好なメッセージの処理を少しの間保留し、その後ブローカーによって未処理のままとされます。

ほとんどのデータベースはトランザクションとして動作し、メッセージの処理が成功した場合にはデータベース表に対する変更がすべてコミットされ、失敗した場合にはロールバックされるようにします。こうしてデータの整合性を維持します。 この例外は、ブローカー自体またはデータベースが失敗するような場合です (例えば、それらが実行されているマシンへの電力の供給が中断される、など)。 このような場合、特定のデータベースの変更はコミットして、他のデータベースの変更はコミットしない可能性があります。 あるいは、データベースの変更はコミットし、入出力メッセージはコミットしない可能性もあります。 これらの可能性が気にかかる場合は、フローを調整し、関係するデータベースをこの機能の仕方に合わせて構成する必要があります。

カスタマイズされたエラー処理の使用

以下に、カスタマイズされたエラー・ハンドラーの作成に関する一般的なヒントをいくつか示します。
  1. デフォルトのエラー処理よりも優れたものが必要な場合には、まずハンドラーを使用します (DECLARE HANDLER ステートメントを参照)。考えられるすべての例外 (あるいは予測できる限りの例外) を代行受信するためのハンドラーを 1 つのノードにつき 1 つ作成します。
  2. エラーを代行受信したら、エラー・ハンドラーはその処理に適したロジックなら何でも使用できます。 あるいは、THROW ステートメントまたはノードを使って例外を作成することもできます。 この例外はフロー・ロジックの高位で処理されるか、または入力ノードに達する場合もあり、トランザクションのロールバックを引き起こします。 例外のスローを参照してください。
  3. ハンドラーによってキャッチされない例外をノードがスローする場合、フローは failure ターミナルに方向転換されるか (接続されている場合)、またはデフォルトのエラー処理によって処理されます (接続されていない場合)。

    未処理エラーをキャッチするために failure ターミナルを使用してください。 単純なロジック・フローを failure ターミナルに接続してください。 このロジック・フローは、ログ・レコードをデータベース (おそらくメッセージのビット・ストリームを含む) あるいはレコードをイベント・ログに書き込む Database ノードまたは Compute ノードで構成できます。 さらに、特別なキューにメッセージを書き込む出力ノードを含めることもできます。

    完全な例外ツリーが、failure ターミナルに接続されているどのノードにも渡されます (例外ツリーについては、ExceptionList ツリー構造で説明されています)。

  4. エラー・ハンドラーは、各エラーを適切な場所 (システム・イベント・ログなど) に記録する責任があります。

メッセージ・フロー内でのエラーを処理するために使用できるオプションに関する詳細は、メッセージ・フローのエラー処理を参照してください。以下のトピックには、実行できる事柄の例が載せられています。

エラーを検出するためのコーディング

以下のセクションでは、エラーを検出するのがブローカーであることを前提としています。 しかし、フローのロジックがエラーを検出するということも十分ありえます。 例えば、フロー・ロジックをコーディングする際には以下のものを使用できます。
  • 特に、起きるべきでない状況を検出するために挿入される IF ステートメント
  • 不可能なコードを介した経路をトラップする CASE 式またはステートメントの ELSE 節
フロー・ロジックが検出するエラーの例として、メッセージのタイプを示す可能な整数値の範囲を持つフィールドを考えてみましょう。 そのような場合に、フィールドの値が既知のタイプのどのメッセージにも対応していない ところにメッセージが到着した場合に発生するイベントを、成り行きに任せるのは望ましくないでしょう。 1 つの可能性として、メッセージの追加のタイプをサポートするようシステムがアップグレードされたものの、システムの一部がアップグレードされていない場合に、このことが起こり得ます。

独自のロジックを使用して無効な入力メッセージを処理する

構文的に無効な入力メッセージ (および誤ったメッセージ形式情報のために無効であるように見える入力メッセージ) を扱うのは困難です。 ブローカーはそのメッセージに何が含まれているかを認識できないからです。おそらくそのようなメッセージを扱う最も良い方法は、構文解析が完全に行われ、メッセージを妥当性検査するように入力ノードを構成することです。

ただし、これは事前定義メッセージ (つまり、MRM または IDOC) のみに適用されることに注意してください。

この方法で入力ノードを構成してある場合、入力メッセージを正常に構文解析できない場合は以下のことが保障されます。
  • 入力メッセージがノードの通常の output ターミナルから現れることはない (failure ターミナルに送られる)。
  • 入力メッセージがメッセージ・フローの主要部分に入ることはない。
  • 入力メッセージがデータベース更新の原因となることはない。
  • メッセージが出力キューに書き込まれることはない。

失敗メッセージを扱うには、単純なロジック・フローを failure ターミナルに接続してください。

この方針の唯一の欠点は、通常フローが一部のメッセージのフィールドへのアクセスを必要としない場合に、メッセージの完全構文解析の強制によってパフォーマンスに影響が及ぶことです。

独自のロジックを使用してデータベース・エラーを処理する

データベース・エラーは次の 3 つのカテゴリーに分類されます。
  1. データベースがまったく作動しない (例えばオフラインになっている)。
  2. データベースは作動するが要求を拒否する (例えばロックの競合が発生する)。
  3. データベースは作動するが、ユーザーのそれに対する要求が不可能な要求である (例えば存在しない表からの読み取りなど)。

デフォルトのエラー処理よりも優れたものが必要な場合には、まずハンドラーを使用して (DECLARE HANDLER ステートメントを参照) 例外を代行受信します。ハンドラーは、データベースによって戻される SQL 状態から、失敗の性質を判別できます。

データベースが作動しない
データベースがまったく作動せず、そのデータベースがメッセージの処理に不可欠の場合、ユーザーが行えることはおそらくそう多くはないでしょう。 この場合、ハンドラーは原因を判別した後、以下のいずれかを行えるかもしれません。
  • RESIGNAL ステートメントを使用して元のエラーを再スローし、デフォルトのエラー・ハンドラーが引き継ぐようにする。
  • 別のデータベースを使用する。
  • 特別な出力キューにメッセージを書き込む。

    しかし、この種の方針には注意する必要があります。 ハンドラーは例外を吸収するため、別のデータベースに対する変更またはキューに対する書き込みはすべてコミットされます。

データベースが要求を拒否する
ロックの競合が発生するときの状況は、「データベースが作動しない」場合に似ています。 これはデータベースが、失敗する要求だけでなく、現行メッセージに関して行ったデータベース変更すべて をバックアウトするからです。 ですから、それが唯一の更新であったことが確実でない場合は、おそらくエラーのロギングまたはメッセージの特別なキューへの引き渡しを除き、デフォルトのエラー処理よりも優れた方針がある可能性は少ないと言えます。
不可能な要求
データベースは作動するもののユーザーのそれに対する要求が不可能であるというケースは、幅広い問題を包含します。
例にあるように、フローが予期する名前の表をデータベースがただ持っていないというような場合も、おそらくエラーのロギングまたはメッセージの特別なキューへの引き渡しを除き、 デフォルトのエラー処理よりも優れた方針がある可能性は少ないと言えます。
しかし、他の多くのエラーは正常に処理できます。 例えば、行を挿入しようとする場合、その種の行がすでに存在するため、新規行は重複することになり、その試行は失敗するかもしれません。 またはその種の行が存在しない (つまり更新によって行がまったく更新されなかった) ために行の更新試行が失敗することも考えられます。 このような場合、適合すると思われるロジックなら何でもハンドラーは取り込むことができます。 欠落行を挿入するかもしれませんし、既存の行を使用するかもしれません (おそらくその値が適切なものであることを確認するでしょう)。
注: ゼロ行の更新がエラーとして報告される場合には、ノード・プロパティー「警告をエラーとして扱う」を true に設定する必要があります。 これはデフォルトの設定ではありません。

独自のロジックを使用して出力ノードのエラーを処理する

変更の始まりMQ 出力ノードで発生するエラーは、SQL 状態のエラーの性質を報告し、SQL native error 変数に追加情報を提供します。 こうして、デフォルトのエラー処理よりも優れたものが必要な場合には、まずハンドラーを使用して (DECLARE HANDLER ステートメントを参照) 例外を代行受信します。そうしたハンドラーは通常、単一の PROPAGATE ステートメントのみを囲みます。変更の終わり

独自のロジックを使用してその他のエラーを処理する

上記で扱われているものの他にもさまざまなエラーが発生し得ます。 例えば、算術計算のオーバーフロー、データの不適切によるキャストの失敗、タイプの制約によるメッセージ・フィールドへのアクセスの失敗などです。 ブローカーはこれらを扱うための 2 つのプログラミング・ストラテジーを提供しています。
  1. 処理されるかまたはトランザクションをロールバックするために残される例外がエラーによって発生する。
  2. 後にテストされる特殊値として失敗が記録される。

タイプの制約がない場合に、存在しないメッセージ・フィールドにアクセスしようとすると値がヌルになります。 ヌル値は式を介して伝搬し、結果をヌルにします。 こうして、式 (複雑な式) がヌル値を戻さなければ、式がその結果を計算する必要があった値すべてがヌルでなかったことを知ります。

キャスト式にはデフォルトの文節がある場合があります。 デフォルトの文節がある場合、キャストはそれとは分かりにくい形で失敗します。 例外をスローする代わりに、ただデフォルト値を戻します。 デフォルト値には、無害な数値 (例えば整数の場合のゼロ)、またはコンテキストの中で明らかに無効な値 (例えば顧客番号の場合の -1) を使用できますが、 ヌルがとりわけ適しているかもしれません。 なぜならヌルは、他のすべてのものと異なり、エラー条件がマスクされる可能性がまったくなく式を介して伝搬する値だからです。

他のノードのエラー処理

他のノードで発生する例外 (つまり、PROPAGATE ステートメントのダウンストリーム) は、ハンドラーによって通常の方法でキャッチされます。ただし、このようなエラーをふさわしく処理しようとすると、特別な問題が生じます。つまり、元のエラーに別のノードが関係していたため、別のノード (例外の発信元であるとは限らない) がその処理に関係している可能性が非常に高いのです。

このような状態で役立つよう、database および compute ノードには、out1out2out3、および out4 という 4 つの新しいターミナルが用意されています。さらに、PROPAGATE ステートメントの構文が拡張されて、ターゲット式、メッセージ・ソースおよび制御の文節が組み込まれ、これらの追加のターミナルをより良く制御できるようになりました。

特記事項 | 商標 | ダウンロード | ライブラリー | サポート | フィードバック
Copyright IBM Corporation 1999, 2006 最終更新: 08/21/2006
ac17140_