2.3.3. doTry、doCatch、および doFinally

概要

ルート内で例外を処理するには、Java の trycatch、および finally ブロックと同様の方法で例外を処理する、doTrydoCatch、および doFinally 句の組み合わせを使用できます。

doCatch と Java における catch の類似点

通常、ルート定義内の doCatch() 句は、Java コードの catch() 文と同様の動作をします。具体的には、以下の機能が doCatch() 句でサポートされています。

  • 複数の doCatch 句 -  1 つの doTry ブロック内に複数の doCatch 句を持たせることができます。この doCatch 句は、Java の catch() 文と同様に、表示される順序でテストされます。Apache Camel は、スローされた例外に一致する最初の doCatch 句を実行します。

    注記

    このアルゴリズムは、onException 句で使用される例外一致アルゴリズムとは異なります。詳細は 「onException 句」 を参照してください。

  • 例外の再スロー  - handled サブ句を使用すると、doCatch 句から現在の例外を再スローできます (「doCatch での例外の再スロー」 を参照)。

doCatch の特別機能

ただし、doCatch() 句には Java の catch() 文に類似するものがない特別な機能がいくつかあります。以下の機能は doCatch ()固有の 機能です。

  • 複数の例外 の取得( doCatch 句)では、1 つの例外のみをキャッチする Java catch ()ステートメントとは対照的に、キャッチ する例外の一覧を指定できます( 「例」を参照)。
  • 条件キャッチ - 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 での例外の再スロー

以下のように、引数を false に設定して handled() サブ句の呼び出すことにより、doCatch() 句で例外を再スローすることができます。

from("direct:start")
    .doTry()
        .process(new ProcessorFail())
        .to("mock:result")
    .doCatch(IOException.class)
        // mark this as NOT handled, eg the caller will also get the exception
        .handled(false)
        .to("mock:io")
    .doCatch(Exception.class)
        // and catch all other exceptions
        .to("mock:error")
    .end();

上記の例では、IOExceptiondoCatch() にキャッチされると、現在のエクスチェンジが mock:io エンドポイントに送信され、その後に IOException が再スローされます。これにより、ルートの先頭 (from() コマンド) にあるコンシューマーエンドポイントにも例外を処理する機会が与えられます。

以下の例では、Spring XML で同じルートを定義する方法を示しています。

<route>
    <from uri="direct:start"/>
    <doTry>
        <process ref="processorFail"/>
        <to uri="mock:result"/>
        <doCatch>
            <exception>java.io.IOException</exception>
            <!-- mark this as NOT handled, eg the caller will also get the exception -->
            <handled>
                <constant>false</constant>
            </handled>
            <to uri="mock:io"/>
        </doCatch>
        <doCatch>
            <!-- and catch all other exceptions they are handled by default (ie handled = true) -->
            <exception>java.lang.Exception</exception>
            <to uri="mock:error"/>
        </doCatch>
    </doTry>
</route>

onWhen による条件付き例外キャッチ

Apache Camel の doCatch() 句の特別な機能として、実行時に評価される式に基づいて例外のキャッチを条件付けすることができます。つまり、doCatch(ExceptionList).doWhen(Expression) の形式の句を使用して例外をキャッチした場合、述語の式 Expression が実行時に true に評価された場合にのみ例外がキャッチされます。

たとえば、以下の doTry ブロックは、例外メッセージが単語 Severe を含む場合にのみ、例外 IOExceptionIllegalStateException をキャッチします。

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();