From dbfb3c782372ab5abd6ef6ec05217f0e9f61819a Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Mon, 11 Dec 2023 13:24:49 -0500 Subject: [PATCH] GH-405: Re-throw as is after recoverer Fixes: #405 The unchecked exception is wrapped into `UndeclaredThrowableException` if `recoverer` is in use; it is not otherwise * Fix `RetryTemplate` to catch `UndeclaredThrowableException` from `recoveryCallback.recover()` and re-throw its `cause` instead to re-align behavior when no recoverer provided --- .../retry/support/RetryTemplate.java | 12 +++++++++--- .../retry/annotation/EnableRetryTests.java | 13 +++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/springframework/retry/support/RetryTemplate.java b/src/main/java/org/springframework/retry/support/RetryTemplate.java index ac715fe..c6a52a5 100644 --- a/src/main/java/org/springframework/retry/support/RetryTemplate.java +++ b/src/main/java/org/springframework/retry/support/RetryTemplate.java @@ -16,6 +16,7 @@ package org.springframework.retry.support; +import java.lang.reflect.UndeclaredThrowableException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -545,9 +546,14 @@ public class RetryTemplate implements RetryOperations { boolean doRecover = !Boolean.TRUE.equals(context.getAttribute(RetryContext.NO_RECOVERY)); if (recoveryCallback != null) { if (doRecover) { - T recovered = recoveryCallback.recover(context); - context.setAttribute(RetryContext.RECOVERED, true); - return recovered; + try { + T recovered = recoveryCallback.recover(context); + context.setAttribute(RetryContext.RECOVERED, true); + return recovered; + } + catch (UndeclaredThrowableException undeclaredThrowableException) { + throw wrapIfNecessary(undeclaredThrowableException.getUndeclaredThrowable()); + } } else { logger.debug("Retry exhausted and recovery disabled for this throwable"); diff --git a/src/test/java/org/springframework/retry/annotation/EnableRetryTests.java b/src/test/java/org/springframework/retry/annotation/EnableRetryTests.java index a8a3ad9..b0a8183 100644 --- a/src/test/java/org/springframework/retry/annotation/EnableRetryTests.java +++ b/src/test/java/org/springframework/retry/annotation/EnableRetryTests.java @@ -190,6 +190,9 @@ public class EnableRetryTests { service.setExceptionToThrow(new IllegalArgumentException()); service.service(); assertThat(service.getCount()).isEqualTo(3); + + assertThatExceptionOfType(InstantiationException.class).isThrownBy(service::reThrowAsIs).withMessage("noRetry"); + context.close(); } @@ -750,6 +753,16 @@ public class EnableRetryTests { this.exceptionToThrow = exceptionToThrow; } + @Retryable(noRetryFor = InstantiationException.class, recover = "noRetryRecovery") + public void reThrowAsIs() throws InstantiationException { + throw new InstantiationException("noRetry"); + } + + @Recover + public void noRetryRecovery(Throwable ex) throws Throwable { + throw ex; + } + } protected static class StatefulService {