If includes is empty and excludes is not, retry not excluded exceptions
Close #108
This commit is contained in:
@@ -348,12 +348,13 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn
|
||||
for (Class<? extends Throwable> type : excludes) {
|
||||
policyMap.put(type, false);
|
||||
}
|
||||
boolean retryNotExcluded = includes.length == 0;
|
||||
if (hasExpression) {
|
||||
return new ExpressionRetryPolicy(maxAttempts, policyMap, true, exceptionExpression)
|
||||
return new ExpressionRetryPolicy(maxAttempts, policyMap, true, exceptionExpression, retryNotExcluded)
|
||||
.withBeanFactory(this.beanFactory);
|
||||
}
|
||||
else {
|
||||
return new SimpleRetryPolicy(maxAttempts, policyMap, true);
|
||||
return new SimpleRetryPolicy(maxAttempts, policyMap, true, retryNotExcluded);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,8 @@ public @interface CircuitBreaker {
|
||||
/**
|
||||
* Exception types that are not retryable. Defaults to empty (and if includes is also
|
||||
* empty all exceptions are retried).
|
||||
* @return exception types to retry
|
||||
* If includes is empty but excludes is not, all not excluded exceptions are retried
|
||||
* @return exception types not to retry
|
||||
*/
|
||||
Class<? extends Throwable>[] exclude() default {};
|
||||
|
||||
|
||||
@@ -60,7 +60,8 @@ public @interface Retryable {
|
||||
/**
|
||||
* Exception types that are not retryable. Defaults to empty (and if includes is also
|
||||
* empty all exceptions are retried).
|
||||
* @return exception types to retry
|
||||
* If includes is empty but excludes is not, all not excluded exceptions are retried
|
||||
* @return exception types not to retry
|
||||
*/
|
||||
Class<? extends Throwable>[] exclude() default {};
|
||||
|
||||
|
||||
@@ -83,10 +83,11 @@ public class ExpressionRetryPolicy extends SimpleRetryPolicy implements BeanFact
|
||||
* @param retryableExceptions the exceptions
|
||||
* @param traverseCauses true to examine causes
|
||||
* @param expressionString the expression.
|
||||
* @param defaultValue the default action
|
||||
*/
|
||||
public ExpressionRetryPolicy(int maxAttempts, Map<Class<? extends Throwable>, Boolean> retryableExceptions,
|
||||
boolean traverseCauses, String expressionString) {
|
||||
super(maxAttempts, retryableExceptions, traverseCauses);
|
||||
boolean traverseCauses, String expressionString, boolean defaultValue) {
|
||||
super(maxAttempts, retryableExceptions, traverseCauses, defaultValue);
|
||||
Assert.notNull(expressionString, "'expressionString' cannot be null");
|
||||
this.expression = new SpelExpressionParser().parseExpression(expressionString, PARSER_CONTEXT);
|
||||
}
|
||||
|
||||
@@ -130,6 +130,26 @@ public class EnableRetryTests {
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void excludesOnly() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
TestConfiguration.class);
|
||||
ExcludesOnlyService service = context.getBean(ExcludesOnlyService.class);
|
||||
service.setExceptionToThrow(new IllegalStateException());
|
||||
try {
|
||||
service.service();
|
||||
fail("Expected IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
assertEquals(1, service.getCount());
|
||||
|
||||
service.setExceptionToThrow(new IllegalArgumentException());
|
||||
service.service();
|
||||
assertEquals(3, service.getCount());
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stateful() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
@@ -297,6 +317,11 @@ public class EnableRetryTests {
|
||||
return new ExcludesService();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ExcludesOnlyService excludesOnly() {
|
||||
return new ExcludesOnlyService();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MethodInterceptor retryInterceptor() {
|
||||
return RetryInterceptorBuilder.stateless().maxAttempts(5).build();
|
||||
@@ -441,6 +466,27 @@ public class EnableRetryTests {
|
||||
|
||||
}
|
||||
|
||||
protected static class ExcludesOnlyService {
|
||||
|
||||
private int count = 0;
|
||||
private RuntimeException exceptionToThrow;
|
||||
|
||||
@Retryable(exclude = IllegalStateException.class)
|
||||
public void service() {
|
||||
if (count++ < 2) {
|
||||
throw exceptionToThrow;
|
||||
}
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setExceptionToThrow(RuntimeException exceptionToThrow) {
|
||||
this.exceptionToThrow = exceptionToThrow;
|
||||
}
|
||||
}
|
||||
|
||||
protected static class StatefulService {
|
||||
|
||||
private int count = 0;
|
||||
|
||||
Reference in New Issue
Block a user