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>