2.14. OnCompletion

概要

OnCompletion DSL 名は、Unit of Work の完了時に行うアクションを定義するために使用できます。Unit of Work は、エクスチェンジ全体に対応する Camel の概念です。「エクスチェンジ」 を参照してください。onCompletion コマンドの機能は以下のとおりです。

  • OnCompletion コマンドのスコープは、グローバルまたはルートごとに指定できます。ルートスコープはグローバルスコープよりも優先されます。
  • OnCompletion は、失敗時または成功時にトリガーされるように設定することができます。
  • onWhen 述語は、特定の状況で onCompletion のみをトリガーするために使用できます。
  • スレッドプールを使用するかどうかを設定できますが、デフォルトではスレッドプールは使用しません。

onCompletion のルート専用スコープ

エクスチェンジにて onCompletion DSL が指定されると、Camel は新しいスレッドを生成します。これにより、onCompletion タスクに干渉されることなく、元のスレッドを継続することができます。1 つのルートは 1 つの onCompletion のみをサポートします。以下の例では、エクスチェンジが成功または失敗で完了したかに関係なく、onCompletion がトリガーされます。これがデフォルト動作です。

from("direct:start")
     .onCompletion()
         // This route is invoked when the original route is complete.
         // This is similar to a completion callback.
         .to("log:sync")
         .to("mock:sync")
     // Must use end to denote the end of the onCompletion route.
     .end()
     // here the original route contiues
     .process(new MyProcessor())
     .to("mock:result");

XML の場合、以下のようになります。

<route>
    <from uri="direct:start"/>
    <!-- This onCompletion block is executed when the exchange is done being routed. -->
    <!-- This callback is always triggered even if the exchange fails. -->
    <onCompletion>
        <!-- This is similar to an after completion callback. -->
        <to uri="log:sync"/>
        <to uri="mock:sync"/>
    </onCompletion>
    <process ref="myProcessor"/>
    <to uri="mock:result"/>
</route>

失敗時に onCompletion をトリガーするには、onFailureOnly パラメーターを使用することができます。同様に、成功時に onCompletion をトリガーするには、onCompleteOnly パラメーターを使用します。

from("direct:start")
     // Here onCompletion is qualified to invoke only when the exchange fails (exception or FAULT body).
     .onCompletion().onFailureOnly()
         .to("log:sync")
         .to("mock:sync")
     // Must use end to denote the end of the onCompletion route.
     .end()
     // here the original route continues
     .process(new MyProcessor())
     .to("mock:result");

XML の場合、onFailureOnly および onCompleteOnly は、onCompletion タグのブール値として表現されます。

<route>
    <from uri="direct:start"/>
    <!-- this onCompletion block will only be executed when the exchange is done being routed -->
    <!-- this callback is only triggered when the exchange failed, as we have onFailure=true -->
    <onCompletion onFailureOnly="true">
        <to uri="log:sync"/>
        <to uri="mock:sync"/>
    </onCompletion>
    <process ref="myProcessor"/>
    <to uri="mock:result"/>
</route>

グローバルスコープの onCompletion

onCompletion を複数のルートに対して定義するには、以下を実行します。

// define a global on completion that is invoked when the exchange is complete
 onCompletion().to("log:global").to("mock:sync");

 from("direct:start")
     .process(new MyProcessor())
     .to("mock:result");

onWhen の使用

特定条件で onCompletion を起動するには、onWhen 述語を使用します。次の例では、メッセージのボディーに Hello という単語が含まれている場合に、onCompletion がトリガーされます。

/from("direct:start")
     .onCompletion().onWhen(body().contains("Hello"))
         // this route is only invoked when the original route is complete as a kind
         // of completion callback. And also only if the onWhen predicate is true
         .to("log:sync")
         .to("mock:sync")
     // must use end to denote the end of the onCompletion route
     .end()
     // here the original route contiues
     .to("log:original")
     .to("mock:result");

onCompletion でのスレッドプール

Camel 2.14 以降、onCompletion はデフォルトでスレッドプールを使用しません。スレッドプールを強制的に使用するには、executorService を設定するか、parallelProcessing を true に設定します。たとえば、Java DSL では以下の形式を使用します。

onCompletion().parallelProcessing()
     .to("mock:before")
     .delay(1000)
     .setBody(simple("OnComplete:${body}"));

XML の場合は以下のようになります。

<onCompletion parallelProcessing="true">
   <to uri="before"/>
   <delay><constant>1000</constant></delay>
   <setBody><simple>OnComplete:${body}<simple></setBody>
 </onCompletion>

特定のスレッドプールを参照するには executorServiceRef オプションを使用します。

<onCompletion executorServiceRef="myThreadPool"
   <to uri="before"/>
   <delay><constant>1000</constant></delay>
   <setBody><simple>OnComplete:${body}</simple></setBody>
 </onCompletion>>

コンシューマーの応答送信前に onCompletion を実行

onCompletion は 2 つのモードで実行できます。

  • AfterConsumer: コンシューマーが終了した後に実行されるデフォルトのモードです。
  • BeforeConsumer: コンシューマーが呼び出し元に応答を返信する前に実行されます。これにより、onCompletion は、特別なヘッダーの追加などエクスチェンジを変更したり、応答ロガーとしてエクスチェンジをログに記録したりすることができます。

たとえば、created by ヘッダーを応答に追加するには、次に示すように modeBeforeConsumer() を使用します。

.onCompletion().modeBeforeConsumer()
     .setHeader("createdBy", constant("Someone"))
 .end()

XML の場合、mode 属性を BeforeConsumer に設定します。

<onCompletion mode="BeforeConsumer">
   <setHeader headerName="createdBy">
     <constant>Someone</constant>
   </setHeader>
 </onCompletion>