2.11. OnCompletion
Overview
The OnCompletion DSL name is used to define an action that is to take place when a
Unit of Work
is completed. A Unit of Work
is a Camel concept that encompasses an entire exchange. See Section 43.1, “Exchanges”. The onCompletion
command has the following features:
- The scope of the
OnCompletion
command can be global or per route. A route scope overrides global scope. OnCompletion
can be configured to be triggered on success for failure.- The
onWhen
predicate can be used to only trigger theonCompletion
in certain situations. - You can define whether or not to use a thread pool, though the default is no thread pool.
Route Only Scope for onCompletion
When an
onCompletion
DSL is specified on an exchange, Camel spins off a new thread. This allows the original thread to continue without interference from the onCompletion
task. A route will only support one onCompletion
. In the following example, the onCompletion
is triggered whether the exchange completes with success or failure. This is the default action.
from("direct:start") .onCompletion() // this route is only invoked when the original route is complete as a kind // of 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");
For XML the format is as follows:
<route> <from uri="direct:start"/> <!-- this onCompletion block will only be executed when the exchange is done being routed --> <!-- this callback is always triggered even if the exchange failed --> <onCompletion> <!-- so this is a kinda like an after completion callback --> <to uri="log:sync"/> <to uri="mock:sync"/> </onCompletion> <process ref="myProcessor"/> <to uri="mock:result"/> </route>
To trigger the
onCompletion
on failure, the onFailureOnly
parameter can be used. Similarly, to trigger the onCompletion
on success, use the onCompleteOnly
parameter.
from("direct:start") // here we qualify onCompletion to only invoke when the exchange failed (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");
For XML,
onFailureOnly
and onCompleteOnly
are expressed as booleans on the onCompletion
tag:
<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>
Global Scope for onCompletion
To define
onCompletion
for more than just one route:
// 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");
Using onWhen
To trigger the
onCompletion
under certain circumstances, use the onWhen
predicate. The following example will trigger the onCompletion
when the body of the message contains the word Hello
:
/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");
Using onCompletion with or without a thread pool
As of Camel 2.14,
onCompletion
will not use a thread pool by default. To force the use of a thread pool, either set an executorService
or set parallelProcessing
to true. For example, in Java DSL, use the following format:
onCompletion().parallelProcessing() .to("mock:before") .delay(1000) .setBody(simple("OnComplete:${body}"));
For XML the format is:
<onCompletion parallelProcessing="true"> <to uri="before"/> <delay><constant>1000</constant></delay> <setBody><simple>OnComplete:${body}<simple></setBody> </onCompletion>
Use the
executorServiceRef
option to refer to a specific thread pool:
<onCompletion executorServiceRef="myThreadPool" <to uri="before"/> <delay><constant>1000</constant></delay> <setBody><simple>OnComplete:${body}</simple></setBody> </onCompletion>>
Run onCompletion before Consumer Sends Response
onCompletion
can be run in two modes:
- AfterConsumer - The default mode which runs after the consumer is finished
- BeforeConsumer - Runs before the consumer writes a response back to the callee. This allows
onCompletion
to modify the Exchange, such as adding special headers, or to log the Exchange as a response logger.
For example, to add a
created by
header to the response, use modeBeforeConsumer()
as shown below:
.onCompletion().modeBeforeConsumer() .setHeader("createdBy", constant("Someone")) .end()
For XML, set the mode attribute to
BeforeConsumer
:
<onCompletion mode="BeforeConsumer"> <setHeader headerName="createdBy"> <constant>Someone</constant> </setHeader> </onCompletion>