...
The DefaultErrorHandler
does very little: it ends the Exchange immediately and propagates the thrown Exception back to the caller.
The DeadLetterChannel
lets you control behaviors including redelivery, whether to propagate the thrown Exception to the caller (the handled
option), and where the (failed) Exchange should now be routed to.
The DeadLetterChannel
is also by default configured to not be verbose in the logs, so when a message is handled and moved to the dead letter endpoint, then there is nothing logged. If you want some level of logging you can use the various options on the redelivery policy / dead letter channel to configure this. For example if you want the message history then set logExhaustedMessageHistory=true
(and logHandled=true
for Camel 2.15.x or older).
When the DeadLetterChannel
moves a message to the dead letter endpoint, any new Exception thrown is by default handled by the dead letter channel as well. This ensures that the DeadLetterChannel
will always succeed. From Camel 2.15: this behavior can be changed by setting the option deadLetterHandleNewException=false
. Then if a new Exception is thrown, then the dead letter channel will fail and propagate back that new Exception (which is the behavior of the default error handler). When a new Exception occurs then the dead letter channel logs this at WARN
level. This can be turned off by setting logNewException=false
.
...
For instance configuring the dead letter channel as:
Using the Fluent Builders
...
...
Using the Spring XML Extensions
...
...
The Dead Letter Channel above will clear the caused exception setException(null)
, by moving the caused exception to a property on the Exchange, with the key Exchange.EXCEPTION_CAUGHT
. Then the Exchange is moved to the jms:queue:dead
destination and the client will not notice the failure.
...
For instance if you have this route:
...
The route listen for JMS messages and validates, transforms and handle it. During this the Exchange payload is transformed/modified. So in case something goes wrong and we want to move the message to another JMS destination, then we can configure our Dead Letter Channel with the useOriginalMessage
option. But when we move the Exchange to this destination we do not know in which state the message is in. Did the error happen in before the transformOrder
or after? So to be sure we want to move the original input message we received from jms:queue:order:input
. So we can do this by enabling the useOriginalMessage
option as shown below:
...
Then the messages routed to the jms:queue:dead
is the original input. If we want to manually retry we can move the JMS message from the failed to the input queue, with no problem as the message is the same as the original we received.
...
When Dead Letter Channel is doing redeliver its possible to configure a Processor that is executed just before every redelivery attempt. This can be used for the situations where you need to alter the message before its redelivered. See below for sample.
...
...
We also support for per onException to set an onRedeliver
. That means you can do special on redelivery for different exceptions, as opposed to onRedelivery
set on Dead Letter Channel can be viewed as a global scope.
Redelivery Default Values
...
When Camel routes messages it will decorate the Exchange with a property that contains the last endpoint Camel send the Exchange to:
...
...
The Exchange.TO_ENDPOINT
have the constant value CamelToEndpoint
. This information is updated when Camel sends a message to any endpoint. So if it exists its the last endpoint which Camel send the Exchange to.
When for example processing the Exchange at a given Endpoint and the message is to be moved into the dead letter queue, then Camel also decorates the Exchange with another property that contains that last endpoint:
...
...
The Exchange.FAILURE_ENDPOINT
have the constant value CamelFailureEndpoint
.
...
Note: this information is retained on the Exchange even if the message is subsequently processed successfully by a given endpoint only to fail, for example, in local Bean processing instead. So, beware that this is a hint that helps pinpoint errors.
...
...
Now suppose the route above and a failure happens in the foo
bean. Then the Exchange.TO_ENDPOINT
and Exchange.FAILURE_ENDPOINT
will still contain the value of http://someserver/somepath
.
...
For example, the following processor adds a header with the exception message:
...
Then configure the error handler to use the processor as follows:
...
Configuring this from XML DSL is as follows:
...
...
The onPrepare
is also available using the default error handler.
...
When Camel error handler handles an error such as Dead Letter Channel or using Exception Clause with handled=true
, then Camel will decorate the Exchange with the route id where the error occurred.
Example:
...
...
The Exchange.FAILURE_ROUTE_ID
have the constant value CamelFailureRouteId
. This allows for example you to fetch this information in your dead letter queue and use that for error reporting.
...
For example, the following snippet shows how to do this with Java DSL and XML DSL: XML DSL: Wiki Markup Wiki Markup
Samples
The following example shows how to configure the Dead Letter Channel configuration using the DSL Wiki Markup Wiki Markup
How Can I Modify the Exchange Before Redelivery?
We support directly in Dead Letter Channel to set a Processor that is executed before each redelivery attempt. When Dead Letter Channel is doing redeliver its possible to configure a Processor that is executed just before every redelivery attempt. This can be used for the situations where you need to alter the message before its redelivered. Here we configure the Dead Letter Channel to use our processor MyRedeliveryProcessor
to be executed before each redelivery. Wiki Markup MyRedeliveryProcessor
where we alter the message. Wiki Markup
How Can I Log What Caused the Dead Letter Channel to be Invoked?
You often need to know what went wrong that caused the Dead Letter Channel to be used and it does not offer logging for this purpose. So the Dead Letter Channel's endpoint can be set to a endpoint of our own (such as direct:deadLetterChannel
). We write a route to accept this Exchange and log the Exception, then forward on to where we want the failed Exchange moved to (which might be a DLQ queue for instance). See also http://stackoverflow.com/questions/13711462/logging-camel-exceptions-and-sending-to-the-dead-letter-channel Using This Pattern Include Page