javaspringspring-retryretry-logic

Spring @Retryable annotation -- why trying to recover on unmentioned exceptions?


I'm trying to use @Retryable and @Recover and there's clearly something I am missing.

The (very paraphrased, very simplified) code is essentially

// MyRetryableException is a RuntimeException
@Retryable(retryFor = MyRetryableException.class, maxAttempts = 3)
public void doSomething(String s) throws JustGiveUpException {
    final var response = talkToSomething(s);
    if (response.getStatus().equals("retryableProblem")) {
        throw new MyRetryableException(s);
    else if (response.getStatus().equals("someOtherProblem")) {
        throw new JustGiveUpException(s);
    }
}

// UnableToCommunicateException is a RuntimeException
@Recover
public void handleFailedRetries(MyRetryableException e, String s) {
    throw new UnableToCommunicateException(s);
}

When the response status is retryableProblem everything works as I'd expect. When I test the code using a mock that will always return a response with retryableProblem I ultimately get back a UnableToCommunicateException and can verify that talkToSomething was indeed called three times.

But when the response status is someOtherProblem I don't get what I'm expecting. I expected to get a JustGiveUpException. But instead I get an ExhaustedRetryException with a cause of JustGiveUpException and a message of Cannot locate recovery method. Though I do see that talkToSomething is only called once.

Why is that happening? I'm telling the Retryable annotation that it only should retry on MyRetryableException. So why is it trying to retry/recover on another exception?


Solution

  • You can try below annotation on doSomething() method:

    @Retryable(retryFor = MyRetryableException.class, notRecoverable=JustGiveUpException.class, maxAttempts = 3, backoff = @Backoff(delay = 2000))

    Most probably, the spring-retry version that you are using, requires "notRecoverable" attribute to specify the Exception(s) which needs to be excluded from retry logic.

    Hope it works.