You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Karsten Vileid <km...@gmail.com> on 2014/06/26 13:39:32 UTC

Not recoverable error following a recoverable error

Hello,
I am having a problem with error handling and I am not sure if it is a
limitation or something I have misunderstood.

I have deadLetterChannel that handle faults without any redeliveries. For
some recoverable errors (such as java.net.ConnectException) I have defined
an onException clause, which will retry for many hours. The idea being to
smoothly handle transient problems on network etc.

My observation is:
transient problem -> caught by onException handling recoverable errors,
doing redelivery
transient problem resolved, but another not recoverable error occurs on
route -> is for some reason caught by onException handling recoverable
errors. But this is useless since the error is not recoverable, and
redeliveries will fail as well. Causing consumer to be blocked for a not
recoverable error until all retry attemtps are exhausted (which in our case
is many hours).


Below is a TestCase reproducing my observation. (Tested with Camel
version 2.12.3
and latest from github)

import org.apache.camel.ContextTestSupport;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;

public class OnExceptionNotRecoverableErrorAfterRecoverableError extends
ContextTestSupport {

    public void testOnException() throws Exception {
        getMockEndpoint("mock:dlq").expectedMessageCount(1);
        getMockEndpoint("mock:recoverable").expectedMessageCount(0);

        template.sendBody("direct:start", "Hello World");

        assertMockEndpointsSatisfied();
    }

    @Override
    protected RouteBuilder createRouteBuilder() throws Exception {
        return new RouteBuilder() {
            @Override
            public void configure() throws Exception {
                errorHandler(deadLetterChannel("mock:dlq"));
                onException(RecoverableException.class).handled(true)

.maximumRedeliveries(2).delayPattern("1:0").to("mock:recoverable");

                from("direct:start").process(new ExceptionProcessor());
            }
        };
    }

    private static class ExceptionProcessor implements Processor {
        private int count = 0;

        @Override
        public void process(Exchange exchange) throws Exception {
            count++;
            if (count == 1) {
                throw new RecoverableException();
            } else {
                throw new NotRecoverableException();
            }
        }
    }

    private static class RecoverableException extends Exception {
        private static final long serialVersionUID = 1L;
    }

    private static class NotRecoverableException extends Exception {
        private static final long serialVersionUID = 1L;
    }
}

Best regards,
Karsten Vileid