John B
John B

Reputation: 32969

Trigger new onException route from onRedelivery

I have an ErrorHandler (DefaultErrorHandler) into which I have provided an onRedelivery ref. By default the ErrorHandler retries unlimited times. However, if a certain condition exists (currently determined by the onRedelivery ref) I would like to exit the redelivery loop and execute a different route.

My initial thought was to have the onRedelivery ref throw and exception and have an appropriate onException direct this to the appropriate route. However, I find that the RedeliveryErrorHandler catches this exception and keeps looping.

I have also found that I can set the Exchange.REDELIVERY_EXHAUSTED to true which will exit the redelivery loop but will not direct me to my recovery route.

Any suggestions?

Edit

So I have found that if I add the original exception type to the onException of the exception type in the RouteBuilder in which I have my ErrorHandler, and if I set the Exchange.REDELIVERY_EXHAUSTED to true, the original exception will be thrown to the RouteBuilder scope and caught by the onException. However, I would really prefer to throw and catch a new exception type so that the handling is explicit to this case.

Answer

So Peter's suggestion of using retryWhile was great in that it allows me to programmatically determine when to stop retrying. It's too. It only went half way thought. The second part was to send the failing exchange to a new / different route for error handling. This is accomplished by using the DeadLetterChannel instead of the DefaultErrorHandler.

Upvotes: 0

Views: 272

Answers (1)

Peter Keller
Peter Keller

Reputation: 7646

Use retryWhile in combination with deadLetterChannel:

public class MyRouteBuilder extends RouteBuilder {
    @Override
    public void configure() {
        errorHandler(deadLetterChannel("direct:special")
            .retryWhile(method(new MyPredicate())));

        from("direct:start")
            .log("Starting...")
            .throwException(new Exception("dummy"));

        from("direct:special")
            .log("...Special");
    }
}

public class MyPredicate implements Predicate {
    @Override
    public boolean matches(final Exchange exchange) {
        AtomicInteger counter = exchange.getProperty("myCounter");
        if (counter == null) {
            counter = new AtomicInteger(0);
            exchange.setProperty("myCounter", counter);
        }
        int count = counter.incrementAndGet();
        LOG.info("Count = {}", count);
        return count < 3; // or whatever condition is suitable
    }
}

This prints:

INFO  Starting...
INFO  Count = 1
INFO  Count = 2
INFO  Count = 3
INFO  ...Special

Upvotes: 1

Related Questions