Mule 4 の概要: エラーハンドラ

Java の例外処理プロセスでは何が起こったのかを理解するためにソースコードを確認したり、エラーを強制的に発生させたりする必要がありますが、Mule 4 ではこれ以外の方法も使用できるようになりました。Java の Throwable エラーや例外も引き続き使用できますが、Mule 4 では処理しやすいエラーの概念が正式に導入されています。スローされる可能性のあるエラーの種類を各コンポーネントで宣言して、設計の時点で潜在的なエラーを識別できるようになりました。

Mule エラー

実行に失敗すると、Mule に次のコンポーネントを含むエラーが示されます。

  • 問題の説明

  • 問題の特性を表す種類

  • 原因 (失敗を引き起こした根本的な Java Throwable)

  • エラーメッセージ (省略可能)。問題に関する Mule の適切なメッセージが記載されます。

たとえば、HTTP 要求に失敗して 401 状況コードが表示された場合、Mule エラーに次の情報が示されます。

Description: HTTP GET on resource ‘http://localhost:36682/testPath’ failed: unauthorized (401)
Type: HTTP:UNAUTHORIZED
Cause: a ResponseValidatorTypedException instance
Error Message:  { "message" : "Could not authorize the user." }

エラーの種類

上記の例で、エラーの種類が単なる UNAUTHORIZED ではなく、HTTP:UNAUTHORIZED になっています。エラーの種類が名前空間と識別子の両方で構成されるため、ドメインからその種類を判別することができます (HTTP:NOT_FOUND、FILE:NOT_FOUND など)。名前空間はそのコネクタによって定義されますが、コアランタイムエラーの名前空間は暗黙的なため、MULE:EXPRESSION と EXPRESSION は同一とみなされます。

エラーの種類のもう一つの重要な特徴は、親種別のある可能性があることです。たとえば、HTTP:UNAUTHORIZED には MULE:CLIENT_SECURITY という親があり、その親は MULE:SECURITY です。このため、エラーの種類がグローバルなエラーの細部であることがわかります。つまり、広範なセキュリティ問題の 1 つにクライアントセキュリティエラーがあり、その 1 つに HTTP 未承認エラーがあるということです。

こうした階層により、大まかなルーティングが可能になります。たとえば、MULE:SECURITY のハンドラが HTTP 未承認エラーと OAuth エラーの両方をキャッチします。以下は、コアランタイムがどのような階層になっているかを示しています。

エラー階層

どのエラーも一般的なエラーと「CRITICAL (重大)」エラーのどちらかに該当しますが、後者は極めて深刻なため処理することができません。一般的な階層の最上位が「ANY (すべて)」で、その下位の全種類がこれに該当します。

ここで重要な点は、失敗の明確な理由が見つからない場合に使用される「UNKNOWN (不明)」という種類に注意することです。このエラーは「ANY (すべて)」種類経由でしか処理できないため、今後既存のアプリケーションの動作を変更することなく、不明なエラーを特定できるようになります。

コネクタについては、各コネクタがそのコアランタイムエラーを考慮して各自のエラー種類階層を定義しますが、「CONNECTIVITY (接続性)」と RETRY_EXHAUSTED の 2 種類はすべてのコネクタに共通するため、常に存在します。

エラーハンドラ

Mule 4 では、error-handler コンポーネントを導入してエラー処理が再設計されています。このコンポーネントには任意の数の内部ハンドラを含めることができ、最初に一致したハンドラにエラーをルーティングできます。これらのハンドラに該当するのが on-error-continueon-error-propagate で、どちらも エラーの種類 (あるいは数種類のエラー) または式 (高度なユースケースの場合) との照合をサポートしています。こうしたハンドラは、Mule 3 の選択例外 (choice-exception-strategy)、キャッチ例外 (catch-exception-strategy)、ロールバック例外 (rollback-exception-strategy) 戦略によく似ていますが、はるかにシンプルで一貫しています。

Mule 4 でエラーが生じると、エラーハンドラが実行され、最初に一致したハンドラにエラーがルーティングされます。この時点でエラーが検査されるため、使用するコンポーネント (Flow または Try スコープなど) に応じたハンドラを実行して処理できます。

  • on-error-continue が実行されると、実行の結果をそのオーナーの結果として (実際にオーナーが実行を正常に完了したかのように) 使用します。また、この時点のすべてのトランザクションがコミットされます。

  • on-error-propagate はすべてのトランザクションをロールバックしてから実行され、その結果を使用して既存のエラーを再度スローさせます。つまり、そのオーナーが「失敗した」とみなされます。

HTTP リスナが、HTTP 要求を実行する別のフローへのフロー参照をトリガする、次のアプリケーションについて考えてみます。メッセージの受信時にすべてうまくいけば (下図の 1)、参照がトリガされ (2)、要求が実行されて (3)、応答を正常に受信します (4)。

エラー処理の例 1

エラーハンドラのセットアップが inner-flow であるため HTTP 要求に失敗し、「見つかりません」というエラーが表示された場合 (上図の 3)、エラーが伝搬され (4)、フロー参照に失敗します (2)。ただし、on-error-continue により primary-flow がこの処理を続行するため、実行されて (5)、正常な応答が返されます (6)。

エラー処理の例 1

要求に失敗し、未承認エラーが表示された場合は (3)、on-error-continue により inner-flow が処理を行い、ファイルから静的コンテンツを取得します (4)。そして、フロー参照も正常に行われ (2)、正常な応答が返されます (5)。

エラー処理の例 3

では、HTTP 要求で別のエラーが生じた場合はどうでしょうか? このフローには NOT_FOUND エラーと UNAUTHORIZED エラーのハンドラしかありませんが、デフォルトで他のエラーも伝搬します。つまり、スローされたエラーに一致するハンドラがなければ、エラーが再びスローされます。たとえば、要求に失敗し、「メソッドが許可されていません」というエラーが表示された場合 (3)、このエラーが伝搬され、フロー参照に失敗し (2)、この伝搬により応答も失敗します (4)。

エラー処理の例 4

上記のシナリオを回避するためには、最後のハンドラを HTTP:UNAUTHORIZED ではなく、ANY と照合するようにします。以下は、HTTP 要求で生じる可能性のある全エラーがどのように提示されるかを示しています。

エラー処理の Any

式を使用してエラーを照合することもできます。たとえば、エラーの処理時に Mule エラーを使用できるため、このエラーを使用してすべてのエラーを HTTP 名前空間と照合することができます。

エラー処理の式

Try スコープ

Mule 3 では概してエラーをフローレレベルでしか処理できないため、エラーに対処するためにはフローにロジックを抽出する必要があります。Mule 4 では、フロー内で内部コンポーネントのエラーのみを処理する Try スコープが導入されました。このスコープは旧来の Transactional スコープの後継で、トランザクションもサポートします。

Try スコープ

このエラーハンドラは、上記の説明のとおりに動作します。上記の例で、何らかのデータベース接続エラーが伝搬されると、try に失敗し、フローのエラーハンドラが実行されます。そして、他のすべてのエラーが処理され、Try スコープが正常に機能したとみなされ、フローの次のプロセッサである HTTP 要求が処理を続行します。

エラーのマッピング

Mule 4 では、デフォルトのエラーをカスタムエラーにマップできるようになりました。Try スコープは便利ですが、同一のコンポーネントがいくつかあり、それぞれのエラーを区別したい場合、これらのエラーに Try を使用するとアプリケーションがわかりづらくなることがあります。この場合は代わりに、各コンポーネントにエラーマッピングを追加することが考えられます。つまり、コンポーネントからのすべてまたは一定のエラーストリーミングが任意の別のエラーにマップされるようにします。たとえば、それぞれ HTTP 要求コンポーネントを使用する 2 つの API の結果を集約する場合、デフォルトでは API 1 と API 2 のエラーが同じため、API ごとに区別したいことがあります。

最初の要求からのエラーをカスタムの API_1 エラーにマップし、2 つ目の要求のエラーを API_2 にマップすれば、これらのエラーを異なるハンドラにルーティングできます。次の例では、HTTP:INTERNAL_SERVER_ERROR がマップされるため、API がダウンしたときにそれぞれ異なる処理ポリシーが適用されます (1 つ目の API はエラーの伝搬、2 つ目の API はエラーの処理)。

エラー処理のマッピング

Was this article helpful?

💙 Thanks for your feedback!

Edit on GitHub