« Return to Thread: [CONF] Apache Camel: Dead Letter Channel (page edited)
|
Page Edited :
CAMEL :
Dead Letter Channel
Dead Letter Channel has been edited by Claus Ibsen (Jul 05, 2009). Content:Dead Letter ChannelCamel supports the Dead Letter Channel
RedeliveryIt is common for a temporary outage or database deadlock to cause a message to fail to process; but the chances are if its tried a few more times with some time delay then it will complete fine. So we typically wish to use some kind of redelivery policy to decide how many times to try redeliver a message and how long to wait before redelivery attempts. The RedeliveryPolicy
Once all attempts at redelivering the message fails then the message is forwarded to the dead letter queue. About moving Exchange to dead letter queue and using handledHandled on Dead Letter Channel was introduced in Camel 2.0, this feature does not exist in Camel 1.x When all attempts of redelivery have failed the Exchange is moved to the dead letter queue (the dead letter endpoint). The exchange is then complete and from the client point of view it was processed. As such the Dead Letter Channel have handled the Exchange. For instance configuring the dead letter channel as: errorHandler(deadLetterChannel("jms:queue:dead").maximumRedeliveries(3).redeliverDealy(5000));
The Dead Letter Channel above will clear the caused exception when the Exchange is moved to the jms:queue:dead destination and the client will not notice the failure. By default handled is true. How to let the client notice the error?If you want to move the message to the dead letter queue and also let the client notice the error, then you can configure the Dead Letter Channel to not handle the error. For example: errorHandler(deadLetterChannel("jms:queue:dead").maximumRedeliveries(3).redeliverDealy(5000).handled(false)); When all attempts of redelivery have failed the Exchange is moved to the dead letter queue (the dead letter endpoint). As the Dead Letter Channel
About moving Exchange to dead letter queue and using the original bodyAvailable as of Camel 2.0 For instance if you have this route: from("jms:queue:order:input") .to("bean:validateOrder"); .to("bean:transformOrder") .to("bean:handleOrder"); 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 useOriginalBody 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 useOriginalBody option as shown below: // will use original body errorHandler(deadLetterChannel("jms:queue:dead") .useOriginalBody().mamimumRedeliveries(5).redeliverDelay(5000); 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. OnRedeliveryAvailable in Camel 1.5.1 onwards 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.
Redelivery default valuesIn Camel 2.0 redelivery is disabled by default, as opposed to Camel 1.x in which Dead Letter Channel is configured with maximumRedeliveries=5. The default redeliver policy will use the following values:
The maximum redeliver delay ensures that a delay is never longer than the value, default 1 minute. This can happen if you turn on the exponential backoff. The maximum redeliveries is the number of re delivery attempts. By default Camel will try to process the exchange 1 + 5 times. 1 time for the normal attempt and then 5 attempts as redeliveries. Camel will log delivery failures at the DEBUG logging level by default. You can change this by specifying retriesExhaustedLogLevel and/or retryAttemptedLogLevel. See ExceptionBuilderWithRetryLoggingLevelSetTest In Camel 2.0 you can turn logging of stack traces on/off. If turned off Camel will still log the redelivery attempt. Its just much less verbose. Redeliver Delay PatternAvailable as of Camel 2.0 The idea is to set groups of ranges using the following syntax: limit:delay;limit 2:delay 2;limit 3:delay 3;...;limit N:delay N Each group has two values separated with colon
Lets clarify this with an example: That gives us 3 groups:
Resulting in these delays for redelivery attempt:
You can start a group with limit 0 to eg have a starting delay: delayPattern=0:1000;5:5000
There is no requirement that the next delay should be higher than the previous. You can use any delay value you like. For example with delayPattern=0:5000;3:1000 we start with 5 sec delay and then later reduce that to 1 second. Redelivery headerWhen a message is redelivered the DeadLetterChannel And a boolean flag whether it is being redelivered or not (first attempt) SamplesThe following example shows how to configure the Dead Letter Channel configuration using the DSL RouteBuilder builder = new RouteBuilder() { public void configure() { // using dead letter channel with a seda queue for errors errorHandler(deadLetterChannel("seda:errors")); // here is our route from("seda:a").to("seda:b"); } }; You can also configure the RedeliveryPolicy RouteBuilder builder = new RouteBuilder() { public void configure() { // configures dead letter channel to use seda queue for errors and use at most 2 redelveries // and exponential backoff errorHandler(deadLetterChannel("seda:errors").maximumRedeliveries(2).useExponentialBackOff()); // here is our route from("seda:a").to("seda:b"); } }; How can I modify the Exchange before redelivery?In Camel 1.5.1 we added support directly in Dead Letter Channel to set a Processor that is executed before each redelivery attempt. In older releases you have to sort to other solutions that isn't as solid as this new feature. Camel 1.5.0 or olderWhen Dead Letter Channel is doing redeliver it redeliveries immediately with the original Exchange that caused the error in the first place. However in some situations you might want to be able to alter the message before its redelivered. As Camel at this time of writing doesn't have a nice DSL syntax or configuration on the Dead Letter Channel to allow custom processing before redeliver we are gonna show a different solution, that actually also pin points the flexibility Camel has. We are going to use an interceptor that gets triggered when an Exchange is being redelivered. We use the fact that interceptors by default will proceed from the point of interceptor. This is the Detour EIP pattern we are using. The code below demonstrates this. An error occurred: http://svn.apache.org/repos/asf/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/InterceptAlterMessageBeforeRedeliveryTest.java. The system administrator has been notified.
However you should notice as Camel will keep the redeliver flag on the Exchange for the remainder of its routing this interceptor will kick in for subsequence processing. So you should keep track if you already have altered the message before redelivery. Camel 1.5.1 or newerWhen 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. // we configure our Dead Letter Channel to invoke // MyRedeliveryProcessor before a redelivery is // attempted. This allows us to alter the message before errorHandler(deadLetterChannel("mock:error") .onRedelivery(new MyRedeliverPrcessor()) // setting delay to zero is just to make unit teting faster .redeliverDelay(0L)); And this is the processor MyRedeliveryProcessor where we alter the message. // This is our processor that is executed before every redelivery attempt // here we can do what we want in the java code, such as altering the message public class MyRedeliverPrcessor implements Processor { public void process(Exchange exchange) throws Exception { // the message is being redelivered so we can alter it // we just append the redelivery counter to the body // you can of course do all kind of stuff instead String body = exchange.getIn().getBody(String.class); int count = exchange.getIn().getHeader("CamelRedeliveryCounter", Integer.class); exchange.getIn().setBody(body + count); } } Using This PatternIf you would like to use this EIP Pattern then please read the Getting Started, you may also find the Architecture useful particularly the description of Endpoint and URIs. Then you could try out some of the Examples first before trying this pattern out. |
« Return to Thread: [CONF] Apache Camel: Dead Letter Channel (page edited)
| Free embeddable forum powered by Nabble | Forum Help |