Camel repeat control with a few exceptions

Foreword: I am pretty new to Camel, and after digesting Camel in action as best as I can, I will adapt it to the project in which I work. In this project, we have a rather complicated error handling, and I want to make sure that I can replicate this when we get the code back.

In our project (as in most cases) there is a set of Exceptions that we want to repeat, and a set that we donโ€™t have, but more specifically, there is a set that we want to repeat more than others (not all recoverable errors can be treated equally). In this case, I tried to define an onException block to change the override policy. However, it looks like Exchange supports counting ( Exchange.REDELIVERY_COUNTER ) and that this count does not depend on which exception is thrown. Is there a way to make this account specific to this exception?

For example, I have two exceptions FooException and BarException . In my route (or indeed in the whole context), I want to repeat FooExceptions 10 times, but BarException should repeat only 2 times. Thus, the context will contain:

 <onException> <exception>my.exception.FooException</exception> <redeliveryPolicy maximumRedeliveries="10" redeliveryDelay="2000" </onException> <onException> <exception>my.exception.BarException</exception> <redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="5000" </onException> 

Now, the concern is if my application throws a FooException and repeats 4 times (each time throwing a FooException ), and then on the 5th attempt, it throws a BarException , it looks like Exchange is working, it has the REDELIVERY_COUNTER value of 5, and when I reset the policy will be try only twice, it (logically) concludes that the route should not be repeated and throws an exception. However, in my application, BarExceptions should be repeated twice, no matter how many FooExceptions are selected. And similarly, if it alternates throwing Foo and Bar exceptions, I would like it to increment the counter for that exception only.

The very end of Camel in Action fosters the use of retryWhile - is this the only way to capture the type of control I'm looking for? Do I need to create a stateful bean that knows about the exception bill? Or am I missing something simple? I want to make sure that when I come to this refactor, I do not start us on an ugly path.

Using Camel 2.10.1

+4
source share
2 answers

I checked your case with the following test:

 import org.apache.camel.EndpointInject; import org.apache.camel.Exchange; import org.apache.camel.Produce; import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.test.junit4.CamelTestSupport; import org.junit.Test; import java.util.concurrent.atomic.AtomicLong; /** * @author Illarion Kovalchuk * Date: 12/7/12 * Time: 2:58 PM */ public class Test extends CamelTestSupport { private static final String MIDDLE_QUEUE = "seda:middle"; @EndpointInject(uri = "mock:result") protected MockEndpoint resultEndpoint; @Produce(uri = "direct:start") protected ProducerTemplate template; private Processor processor = new Processor(); @Test public void shouldRedeliverOnErrors() throws Exception { resultEndpoint.expectedBodiesReceived("Body"); template.sendBodyAndHeader(MIDDLE_QUEUE, "Body", "Header", "HV"); resultEndpoint.assertIsNotSatisfied(); } @Override protected RouteBuilder createRouteBuilder() { return new RouteBuilder() { @Override public void configure() throws Exception { onException(FooException.class) .redeliveryDelay(2000) .maximumRedeliveries(10); onException(BarException.class) .redeliveryDelay(5000) .maximumRedeliveries(2); from(MIDDLE_QUEUE) .bean(Processor.class, "process") .to(resultEndpoint) .end(); } }; } public static class Processor { private static AtomicLong retryState = new AtomicLong(0L); public static void process(Exchange e) throws FooException, BarException { long rs = retryState.getAndAdd(1L); if (rs < 4) { System.err.println("Foo Attempt "+ rs); throw new FooException(); } if (rs == 4) { System.err.println("Bar Attempt "+ rs); throw new BarException(); } System.err.println("Normal Attempt "+ rs); } } public static class FooException extends Throwable { } private static class BarException extends Throwable { } } 

As a result, your consigner was approved: delivery attempts were exhausted after a BarException, even if we have only 4 FooExceptions and 1 BarException.

Unfortunately, I canโ€™t completely answer your question right now, but I dig in it and update my opinion if I get something new.

+1
source

Try replacing the order that defines your exceptions, for example:

 <onException> <exception>my.exception.BarException</exception> <redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="5000" </onException> <onException> <exception>my.exception.FooException</exception> <redeliveryPolicy maximumRedeliveries="10" redeliveryDelay="2000" </onException> 
0
source

All Articles