简体   繁体   中英

How to retry a camel direct route once?

With camel, I want to send an HTTP request and, if it fails, take some corrective action and try it once more.

Sending the request is wrapped in a direct route and requires the generation of a unique token, apart from that the request should be exactly the same. If the request fails the second time, it should fail the "normal" way.

I want the sending logic in it's own route because sometimes I want to call it without retry.

How can I set up this scenario with the camel DSL? I tried various combinations of onException and errorHandler but it doesn't even seem to catch the exception.

Example (that doesn't work):

from("direct:send-request-no-retry")
  .setHeader("token").exchange(this::generateToken)
  .to("http://example.com");

from("direct:fix-the-error")
  // ...
  ;

from("direct:send-request")
  .onException(HttpOperationFailedException.class)
    .to("direct:fix-the-error")
    .maximumRedeliveries(1)
    .useOriginalMessage()
    .end()
  .to("direct:send-request-no-retry");

I have mainly used onException() clause as a global exception handler. With quick testing it does not indeed catch the exceptions when put directly into a route. Couple of options that come to my mind are:

1st option do-try clauses:

        from("direct:send-request")
            .doTry()
                .to("direct:send-request-no-retry")
            .doCatch(HttpOperationFailedException.class)
                .to("direct:fix-the-error")
                .to("direct:send-request-no-retry")
            .doFinally()
                .whatevs()
            .endDoTry();

But this is a bit janky since you would have to handle the exception again from the doCatch clause. Another one is to throw custom exception from the "send-request-no-retry".

 from("direct:send-request-no-retry")
            .setHeader("token").exchange(this::generateToken)
            .doTry()
                .to("http://example.com")
            .doCatch(HttpOperationFailedException.class)
                .throwException(new CustomExceptionThatExtendsRunTimeException())
            .doFinally();

onException(CustomExceptionThatExtendsRunTimeException.class)
        .handled(true)
        .to("direct:fix-the-error")
        .maximumRedeliveries(1)
        .useOriginalMessage()
        .to("direct:send-request-no-retry")
        .end();

I didn't test this so I'm not sure if this creates an infinite feedback loop or if the maximumRedeliveries will cut it off. If it does you can implement another "direct:send-request-no-retry" route that does not throw the customException but just fails silently or throws the HttpOperationFailedException and pass the request there from onException(). Or set the retryAmount to a header and check that header in onException handler to see if we want to try again.

The customException is for the purposes that the onException() clause catches all exceptions from every route of the specified type. And I think you don't want to pass every failed http request to your retryroute.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM