2.3.3. doTry、doCatch、および doFinally
概要
ルート内で例外を処理するには、Java の try
、catch
、および finally
ブロックと同様の方法で例外を処理する、doTry
、doCatch
、および doFinally
句の組み合わせを使用できます。
doCatch と Java における catch の類似点
通常、ルート定義内の doCatch()
句は、Java コードの catch()
文と同様の動作をします。具体的には、以下の機能が doCatch()
句でサポートされています。
複数の doCatch 句 - 1 つの
doTry
ブロック内に複数のdoCatch
句を持たせることができます。このdoCatch
句は、Java のcatch()
文と同様に、表示される順序でテストされます。Apache Camel は、出力された例外に一致する最初のdoCatch
句を実行します。注記このアルゴリズムは、
onException
句で使用される例外一致アルゴリズムとは異なります。詳細は 「onException 句」 を参照してください。-
例外 の再出力 — コンストラクトを使用して
doCatch
句内から現在の例外を再出力できます (「doCatch での例外の再出力」)。
doCatch の特別機能
ただし、doCatch()
句には Java の catch()
文に類似するものがない特別な機能がいくつかあります。以下の機能は、doCatch()
に固有のものです。
-
条件キャッチ -
doCatch
句にonWhen
サブ句を追加することで、例外を条件付きでキャッチできます (「onWhen による条件付き例外キャッチ」 を参照)。
例
以下の例は、Java DSL で doTry
ブロックを書く方法を示しています。doCatch()
句は、IOException
例外または IllegalStateException
例外のいずれかが発生した場合に実行され、doFinally()
句は例外が発生したかどうかに関係なく、常に 実行されます。
from("direct:start") .doTry() .process(new ProcessorFail()) .to("mock:result") .doCatch(IOException.class, IllegalStateException.class) .to("mock:catch") .doFinally() .to("mock:finally") .end();
または、Spring XML で同等のものを記述するとこのようになります。
<route> <from uri="direct:start"/> <!-- here the try starts. its a try .. catch .. finally just as regular java code --> <doTry> <process ref="processorFail"/> <to uri="mock:result"/> <doCatch> <!-- catch multiple exceptions --> <exception>java.io.IOException</exception> <exception>java.lang.IllegalStateException</exception> <to uri="mock:catch"/> </doCatch> <doFinally> <to uri="mock:finally"/> </doFinally> </doTry> </route>
doCatch での例外の再出力
次のように、コンストラクトを使用して、doCatch ()
句で例外を再出力することができます。
from("direct:start") .doTry() .process(new ProcessorFail()) .to("mock:result") .doCatch(IOException.class) .to("mock:io") // Rethrow the exception using a construct instead ofhandled(false)
which is deprecated in adoTry/doCatch
clause. .throwException(new IllegalArgumentException("Forced")) .doCatch(Exception.class) // Catch all other exceptions. .to("mock:error") .end();
doTry/doCatch
句で非推奨となった handled (false)
の代わりにプロセッサーを使用して例外を再出力することもできます。
.process(exchange -> {throw exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);})
上記の例では、IOException
が doCatch()
にキャッチされると、現在のエクスチェンジが mock:io
エンドポイントに送信され、その後に IOException
が再出力されます。これにより、ルートの先頭 (from()
コマンド) にあるコンシューマーエンドポイントにも例外を処理する機会が与えられます。
以下の例では、Spring XML で同じルートを定義する方法を示しています。
<route> <from uri="direct:start"/> <doTry> <process ref="processorFail"/> <to uri="mock:result"/> <doCatch> <to uri="mock:io"/> <throwException message="Forced" exceptionType="java.lang.IllegalArgumentException"/> </doCatch> <doCatch> <!-- Catch all other exceptions. --> <exception>java.lang.Exception</exception> <to uri="mock:error"/> </doCatch> </doTry> </route>
onWhen による条件付き例外キャッチ
Apache Camel の doCatch()
句の特別な機能として、実行時に評価される式に基づいて例外のキャッチを条件付けすることができます。つまり、doCatch(ExceptionList).doWhen(Expression)
の形式の句を使用して例外をキャッチした場合、述語の式 Expression が実行時に true
に評価された場合にのみ例外がキャッチされます。
たとえば、以下の doTry
ブロックは、例外メッセージが単語 Severe
を含む場合にのみ、例外 IOException
と IllegalStateException
をキャッチします。
from("direct:start")
.doTry()
.process(new ProcessorFail())
.to("mock:result")
.doCatch(IOException.class, IllegalStateException.class)
.onWhen(exceptionMessage().contains("Severe"))
.to("mock:catch")
.doCatch(CamelExchangeException.class)
.to("mock:catchCamel")
.doFinally()
.to("mock:finally")
.end();
または、Spring XML で同等のものを記述するとこのようになります。
<route> <from uri="direct:start"/> <doTry> <process ref="processorFail"/> <to uri="mock:result"/> <doCatch> <exception>java.io.IOException</exception> <exception>java.lang.IllegalStateException</exception> <onWhen> <simple>${exception.message} contains 'Severe'</simple> </onWhen> <to uri="mock:catch"/> </doCatch> <doCatch> <exception>org.apache.camel.CamelExchangeException</exception> <to uri="mock:catchCamel"/> </doCatch> <doFinally> <to uri="mock:finally"/> </doFinally> </doTry> </route>
doTry のネストされた条件
Camel の例外処理を JavaDSL ルートに追加するためのオプションは複数あります。dotry()
は例外を処理するための try または catch ブロックを作成します。これはルート固有のエラー処理に役立ちます。
ChoiceDefinition
内部で例外をキャッチする場合は、以下のように doTry
ブロックを使用できます。
from("direct:wayne-get-token").setExchangePattern(ExchangePattern.InOut) .doTry() .to("https4://wayne-token-service") .choice() .when().simple("${header.CamelHttpResponseCode} == '200'") .convertBodyTo(String.class) .setHeader("wayne-token").groovy("body.replaceAll('\"','')") .log(">> Wayne Token : ${header.wayne-token}") .endChoice() .doCatch(java.lang.Class (java.lang.Exception>) .log(">> Exception") .endDoTry(); from("direct:wayne-get-token").setExchangePattern(ExchangePattern.InOut) .doTry() .to("https4://wayne-token-service") .doCatch(Exception.class) .log(">> Exception") .endDoTry();