Muleの例外処理まとめ

# 概要
Muleの例外処理についてまとめてみました。とはいってもエラーレベルとOn Error Continue、On Error Propagateの組み合わせによる動きの違いについての簡単な説明のみになります。

## エラーレベル
* Muleディフォルトのディフォルトエラーハンドラー  
  Muleのディフォルトのエラーハンドラー。アプリケーションで処理されないエラーを処理します。カスタマイズ不可。

* アプリケーションレベル  
  アプリケーションの共通のエラーハンドラー。共通のMule設定ファイル(global.xml)に例外処理を指定することで、各フロー共通のエラーの指定が可能となります。

* フローレベル  
フロー単位の共通エラーハンドラー。

* プロセッサーレベル  
フローの処理内にTry-Catchの形で埋め込まれるエラーハンドラーです。

## On Error ContinueとOn Error Propagate
* On Error Continue  
payloadを返します。親フローには正常な結果として戻され、以降の処理が行われます。

* On Error Propagate  
Errorオブジェクトを返します。親フローには例外がスローされ、以降の処理は行われません。

# 動かしてみて確認
## 準備
検証用に簡単なMuleアプリケーションを作成します。こんな感じ。
![testapplication.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367531/c3a9be36-3cd5-25f8-5ec3-990c29dfafae.jpeg)

1. HTTP Listnerコネクターを配置
  * Connector Configurationはディフォルトのまま、新規作成
  * General→Pathは「/errorhandling/」と指定
2. Loggerを配置してください。
3. Validation is Numberを配置
  * General > Valueに「attributes.queryParams.value」と指定
  * Error option > Messageに「error message」
4. Set payloadを配置。Setting > Valueに「no error」と設定します。
5. 以下のURLにアクセスして動作確認。   
  http://localhost:8081/errorhandling?value=1  
  以下が返却されればOKです。
    * status：200 OK
    * body：no error

## 動作確認
### Muleディフォルトのディフォルト
1. パラメーター「Value」の値を「a」に変更してアクセス。  
  http://localhost:8081/errorhandling?value=a
2. 以下で応答が戻ってきます。
  * status：500 server error
  * body：error message

アプリケーションで何のエラー処理もしないと、Muleディフォルトのエラーハンドラーによって処理されます。

### アプリケーションレベル
1. アプリケーション共通のエラーハンドラーを追加します。  
![GlobalErrorPropagate.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367531/14934a8e-6e46-e58e-efe8-6ccf68083648.jpeg)
2. フロー以外のところにError Handlerを配置します。（通常は共通用の別XMLファイル（global.xml）に配置します。）
3. 配置したError HandlerをGlobal Elements > ConfigurationでDefault Error Handlerに指定します。
![GlobalCOnfiguration.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367531/c86bd3b0-c524-c73c-4aa4-f140518c6afd.jpeg)
4. 配置したError Handler内にOn Error Propagateを配置します。
5. On Error Propagate内にSet Payloadを配置します。Setting > Valueに「global error propagate」と指定します。
6. Set Payloadの横にLoggerを配置します。
7. 先ほどと同じURLでアクセス。以下が返却されます。
  * status：500 server error
  * body：error message  

    **先ほどと同じ結果となります。**が、これは作成したアプリケーションレベルのエラーハンドラーで処理した結果となります。（ブレークポイントを貼ってデバッグすれば確かにこの処理を行っています。）戻ってくる結果が変わらないのは、On Error Propagateの動作によるものです。詳しい理由はOn Error Continueの動作確認後に説明します。

続いてOn Error Continueエラーハンドラーの動作を確認します。  
![GlobalErrorContinue.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367531/99c26bbd-0c0f-8850-9dfe-e513675fb51b.jpeg)

1. On Error Propagateの下にOn Error Propagateと同じ感じでOn Error Continueを配置します。Payloadの値は「global error continue」としてください。また、On Error PropagateのSettings > Typeで「EXPRESSION」などを指定してください。（「VALIDATION:INVALID_NUMBER」をキャッチしないような指定をしてください。）
2. 先ほどと同じURLでアクセス。以下が返却されます。
  * status：200 OK
  * body：global error continue

    結果が変わります。これはOn Error Continueの場合、正常な結果をpalyoadとして返却するためです。一方、On Error Propagateの場合は、エラーとしてErrorオブジェクトが返却されます。そのため、On Error Propagateのset payloadで値を変更しても結果に反映されないまま、エラーステータスが返却されます。

エラーオブジェクトの内容はこんな感じです。is Numberで指定したmessageがdescriptionとして設定されています。
![errorobject.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367531/9557054a-cfb7-1181-5c81-51d47202264d.jpeg)

### フローレベル
続いてフローレベルの動作確認です。flowにエラーハンドラーを追加します。  
![flowPropagate.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367531/a971fd28-4bf7-0456-22b1-170b7b9a0619.jpeg)

1. フロー内のError HandlerにOn Error Propagateを配置します。
2. On Error Propagate内にSet Payloadを配置します。Setting > Valueに「flow error propagate」と指定します。
3. Set Payloadの横にLoggerを配置します。
4. 先ほどと同じURLでアクセス。以下が返却されます。
  * status：500 server error
  * body：error message  

debugモードで実施してみてください。フローレベルのOn Error Propagateで処理がされ、アプリケーションレベルのError処理では処理されていないことがわかります。

さらに、フローレベルのOn Error Continueの動きを見てみましょう。
![flowerrorcontinue.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367531/ac6be368-ef20-82ca-9872-83cdfd86292e.jpeg)

1. フローレベルのOn Error Propagateの下にOn Error Propagateと同じ感じにOn Error Continueを配置します。Payloadの値は「flow error continue」としてください。また、On Error PropagateのSettings > Typeで「EXPRESSION」などを指定してください。（「VALIDATION:INVALID_NUMBER」をキャッチしないような指定をしてください。）
2. 先ほどと同じURLでアクセス。以下が返却されます。
  * status：200 OK
  * body：flow error continue

フローレベルのOn Error Continueの処理の結果が返却されることが確認できるかと思います。

### プロセッサーレベル
最後にプロセッサーレベルのエラー処理になります。
![processorerrorpropagate.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367531/bd6bf002-ae17-ac43-9207-4308d1ba10a4.jpeg)

1. Tryをis Numberの前に配置し、is NumberをTry内に移動します。
2. Set PayloadをTryのError Handling内に配置します。Payloadの値は「processor error propagate」としてください。
3. Set Payloadに横にLoggerを配置します。
4. 先ほどと同じURLでアクセス。以下の応答が返却されます。
  * status：200 OK
  * body：flow error continue

これまでの流れからすると、プロセッサーレベルのOn Error Propagateで処理が終了しそうですが、プロセッサーレベルのOn Error Propagateだと、一つ上のエラー処理に処理がスローされます。ここではフローレベルのOn Error ContinueがプロセッサーレベルのOn Error Propagateの結果をキャッチして処理をします。

では、プロセッサーレベルのOn Error Continueの動きを確認してみましょう。

![processorerrorcontinue.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367531/976df15d-6e04-8f1d-744f-82825f81ad23.jpeg)


1. プロセッサーレベルのOn Error Propagateの下にOn Error Propagateと同じ感じでOn Error Continueを配置します。Payloadの値は「processor error continue」としてください。また、On Error PropagateのSettings > Typeで「EXPRESSION」などを指定してください。（「VALIDATION:INVALID_NUMBER」をキャッチしないような指定をしてください。）
2. 先ほどと同じURLでアクセス。以下が返却されます。
  * status：200 OK
  * body：no error

そうです。Is Numberの例外をプロセッサーレベルのOn Error Continueでキャッチし、On Error Continue内の処理を行った後、そのまま正常な処理として次の処理（Set Payload）へ流れます。

以上でMuleの例外処理のまとめとなります。特に複雑な動きをするわけではないですが、組み合わせによって、「あれ？」となりがちだったりしたので、基本的なところをまとめてみました。