To handle exceptions within a route, you can use a combination of the
doTry
, doCatch
, and doFinally
clauses, which
handle exceptions in a similar way to Java's try
, catch
, and
finally
blocks.
In general, the doCatch()
clause in a route definition behaves in an
analogous way to the catch()
statement in Java code. In particular, the
following features are supported by the doCatch()
clause:
Multiple doCatch clauses—you can have multiple
doCatch
clauses within a singledoTry
block. ThedoCatch
clauses are tested in the order they appear, just like Javacatch()
statements. Apache Camel executes the firstdoCatch
clause that matches the thrown exception.Note This algorithm is different from the exception matching algorithm used by the
onException
clause—see onException Clause for details.Rethrowing exceptions—you can rethrow the current exception from within a
doCatch
clause using thehandled
sub-clause (see Rethrowing exceptions in doCatch).
There are some special features of the doCatch()
clause, however, that
have no analogue in the Java catch()
statement. The following features are
specific to doCatch()
:
Catching multiple exceptions—the
doCatch
clause allows you to specify a list of exceptions to catch, in contrast to the Javacatch()
statement, which catches only one exception (see Example).Conditional catching—you can catch an exception conditionally, by appending an
onWhen
sub-clause to thedoCatch
clause (see Conditional exception catching using onWhen).
The following example shows how to write a doTry
block in the Java DSL,
where the doCatch()
clause will be executed, if either the
IOException
exception or the IllegalStateException
exception
are raised, and the doFinally()
clause is always
executed, irrespective of whether an exception is raised or not.
from("direct:start") .doTry() .process(new ProcessorFail()) .to("mock:result") .doCatch(IOException.class, IllegalStateException.class) .to("mock:catch") .doFinally() .to("mock:finally") .end();
Or equivalently, in 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>
It is possible to rethrow an exception in a doCatch()
clause by calling
the handled()
sub-clause with its argument set to false
, as
follows:
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();
In the preceding example, if the IOException
is caught by
doCatch()
, the current exchange is sent to the mock:io
endpoint, and then the IOException
is rethrown. This gives the consumer
endpoint at the start of the route (in the from()
command) an opportunity to
handle the exception as well.
The following example shows how to define the same route in 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>
A special feature of the Apache Camel
doCatch()
clause is that you can conditionalize the catching of exceptions
based on an expression that is evaluated at run time. In other words, if you catch an
exception using a clause of the form,
doCatch(
,
an exception will only be caught, if the predicate expression,
ExceptionList
).doWhen(Expression
)Expression
, evaluates to true
at run
time.
For example, the following doTry
block will catch the exceptions,
IOException
and IllegalStateException
, only if the exception
message contains the word, Severe
:
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();
Or equivalently, in 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>