Alpar Alpar -3 years ago 72
Java Question

Camel Idempotent removeOnFailure for some exception types only

Considering this simple Camel route:

from("timer:some timer")
.bean(someBeanThatProducesLists)
.split(body()).parallelProcessing() .
.idempotentConsumer(simple("${body.id}"), myIdempotentRepository)
.bean(beamThatProcesses)


This is working as expected. When an exception occurs in
beamThatProcesses
the key is removed and is re-processed if
someBeanThatProducesLists
returns an entry with the same ID again.
What I would like is to have

onException(MyCustomException.class)
.maximumRedeliveries(3)


And keep the ID in the idempotent repository after the re-deliveries are exhausted, but only for this specific exception, so
removeOnFailure
doesn't really help here.

I browsed through the documentation and also Camel In Action second edition v12, but could not find any way to implement this. I did find that marking exception
handled
does not help.

I could set
removeOnFailure
to false, and then have custom exception handlers that remove it in most exceptions and keep it on custom when retries exhausted, but it's error prone as the idempotent key would have to be computed in multiple places, exceptions can occur anywhere in the route etc.

I guess I could catch the exception in
beamThatProcesses
and deal with it there, but I'm hoping there is a way to instruct camel to do it.

Answer Source

I ended up implementing something like this in my idempotent repository:

    @Override
    public boolean remove(Exchange exchange, Object key) {
        Throwable caught = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Throwable.class);
        if (exchange.getException() == null && caught != null) {
            logger.info("Exception was handled, not removing key");
            return false;
        } else {
            // ... remove the message
        }
     }
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download