diff --git a/retry/src/main/java/io/micronaut/retry/RetryState.java b/retry/src/main/java/io/micronaut/retry/RetryState.java index 8eec2d5fd0e..5285ecec5af 100644 --- a/retry/src/main/java/io/micronaut/retry/RetryState.java +++ b/retry/src/main/java/io/micronaut/retry/RetryState.java @@ -83,7 +83,7 @@ default RetryPredicate getRetryPredicate() { } /** - * @return The captured exception type (default to {@link RuntimeException} + * @return The captured exception type (default to {@link Exception} */ Class getCapturedException(); diff --git a/retry/src/main/java/io/micronaut/retry/annotation/Retryable.java b/retry/src/main/java/io/micronaut/retry/annotation/Retryable.java index 515ef77ae3e..f63d687fc14 100644 --- a/retry/src/main/java/io/micronaut/retry/annotation/Retryable.java +++ b/retry/src/main/java/io/micronaut/retry/annotation/Retryable.java @@ -88,9 +88,9 @@ Class predicate() default DefaultRetryPredicate.class; /** - * @return The capture exception types (defaults to RuntimeException) + * @return The capture exception types (defaults to Exception) */ - Class capturedException() default RuntimeException.class; + Class capturedException() default Exception.class; /** * @return The jitter factor used to apply random deviation to retry delays diff --git a/retry/src/main/java/io/micronaut/retry/intercept/AnnotationRetryStateBuilder.java b/retry/src/main/java/io/micronaut/retry/intercept/AnnotationRetryStateBuilder.java index 803be2f5434..5c8c26bffae 100644 --- a/retry/src/main/java/io/micronaut/retry/intercept/AnnotationRetryStateBuilder.java +++ b/retry/src/main/java/io/micronaut/retry/intercept/AnnotationRetryStateBuilder.java @@ -67,9 +67,9 @@ public RetryState build() { Class predicateClass = (Class) retry.classValue(PREDICATE).orElse(DefaultRetryPredicate.class); RetryPredicate predicate = createPredicate(predicateClass, retry); @SuppressWarnings("unchecked") - Class capturedException = (Class) retry + Class capturedException = (Class) retry .classValue(CAPTURED_EXCEPTION) - .orElse(RuntimeException.class); + .orElse(Exception.class); return new SimpleRetry( attempts, diff --git a/retry/src/test/groovy/io/micronaut/retry/intercept/SimpleRetrySpec.groovy b/retry/src/test/groovy/io/micronaut/retry/intercept/SimpleRetrySpec.groovy index b705e687512..9a30308d836 100644 --- a/retry/src/test/groovy/io/micronaut/retry/intercept/SimpleRetrySpec.groovy +++ b/retry/src/test/groovy/io/micronaut/retry/intercept/SimpleRetrySpec.groovy @@ -327,6 +327,22 @@ class SimpleRetrySpec extends Specification { context.stop() } + void "test retry with exception captured by default"() { + given: + ApplicationContext context = ApplicationContext.run() + CounterService counterService = context.getBean(CounterService) + + when: + counterService.getCountExceptionDefault() + + then: "retry kicked in because the exception thrown is captured by default" + noExceptionThrown() + counterService.countExceptionDefault == counterService.countThreshold + + cleanup: + context.stop() + } + void "test retry with value"() { given: ApplicationContext context = ApplicationContext.run() @@ -397,6 +413,7 @@ class SimpleRetrySpec extends Specification { int countPreThreshold = 3 int countThrowable = 0; int countThrowableUncaptured = 0; + int countExceptionDefault = 0; @Retryable(attempts = '5', delay = '5ms') int getCountSync() { @@ -544,5 +561,14 @@ class SimpleRetrySpec extends Specification { } return countThrowableUncaptured } + + @Retryable(attempts = '5', delay = '5ms') + Integer getCountExceptionDefault() { + countExceptionDefault++ + if(countExceptionDefault < countThreshold - 1) { + throw new Exception() + } + return countExceptionDefault + } } } diff --git a/src/main/docs/guide/aop/retry.adoc b/src/main/docs/guide/aop/retry.adoc index 8e3398c01e1..07b69ce5636 100644 --- a/src/main/docs/guide/aop/retry.adoc +++ b/src/main/docs/guide/aop/retry.adoc @@ -16,7 +16,7 @@ For example: snippet::io.micronaut.docs.aop.retry.BookService[tags="simple", indent=0, title="Simple Retry Example"] -With the above example if the `listBooks()` method throws a RuntimeException, it is retried until the maximum number of attempts is reached. +With the above example if the `listBooks()` method throws an Exception, it is retried until the maximum number of attempts is reached. The `multiplier` value of the `@Retryable` annotation can be used to configure a multiplier used to calculate the delay between retries, allowing exponential retry support.