GH-293: Fix Bean Resolver for CBreaker Expressions

Resolves https://github.com/spring-projects/spring-retry/issues/293

**cherry-pick to 1.3.x**

# Conflicts:
#	src/test/java/org/springframework/retry/annotation/CircuitBreakerTests.java
This commit is contained in:
Gary Russell
2022-04-20 13:35:28 -04:00
committed by Artem Bilan
parent cd43720b66
commit db0a050f58
2 changed files with 57 additions and 6 deletions

View File

@@ -62,7 +62,6 @@ import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.MethodCallback;
import org.springframework.util.StringUtils;
/**
@@ -254,8 +253,15 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn
private long getOpenTimeout(CircuitBreaker circuit) {
if (StringUtils.hasText(circuit.openTimeoutExpression())) {
Long value = PARSER.parseExpression(resolve(circuit.openTimeoutExpression()), PARSER_CONTEXT)
.getValue(Long.class);
Long value = null;
if (isTemplate(circuit.openTimeoutExpression())) {
value = PARSER.parseExpression(resolve(circuit.openTimeoutExpression()), PARSER_CONTEXT)
.getValue(this.evaluationContext, Long.class);
}
else {
value = PARSER.parseExpression(resolve(circuit.openTimeoutExpression()))
.getValue(this.evaluationContext, Long.class);
}
if (value != null) {
return value;
}
@@ -265,8 +271,15 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn
private long getResetTimeout(CircuitBreaker circuit) {
if (StringUtils.hasText(circuit.resetTimeoutExpression())) {
Long value = PARSER.parseExpression(resolve(circuit.resetTimeoutExpression()), PARSER_CONTEXT)
.getValue(Long.class);
Long value = null;
if (isTemplate(circuit.openTimeoutExpression())) {
value = PARSER.parseExpression(resolve(circuit.resetTimeoutExpression()), PARSER_CONTEXT)
.getValue(this.evaluationContext, Long.class);
}
else {
value = PARSER.parseExpression(resolve(circuit.resetTimeoutExpression()))
.getValue(this.evaluationContext, Long.class);
}
if (value != null) {
return value;
}
@@ -274,6 +287,11 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn
return circuit.resetTimeout();
}
private boolean isTemplate(String expression) {
return expression.contains(PARSER_CONTEXT.getExpressionPrefix())
&& expression.contains(PARSER_CONTEXT.getExpressionSuffix());
}
private RetryTemplate createTemplate(String[] listenersBeanNames) {
RetryTemplate template = new RetryTemplate();
if (listenersBeanNames.length > 0) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015-2019 the original author or authors.
* Copyright 2015-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,6 +40,7 @@ import static org.junit.Assert.fail;
/**
* @author Dave Syer
* @author Gary Russell
* @author Artem Bilan
*
*/
public class CircuitBreakerTests {
@@ -81,6 +82,8 @@ public class CircuitBreakerTests {
assertEquals(3, service.getCount());
service.expressionService();
assertEquals(4, service.getCount());
service.expressionService2();
assertEquals(5, service.getCount());
Advised advised = (Advised) service;
Advisor advisor = advised.getAdvisors()[0];
Map<?, ?> delegates = (Map<?, ?>) new DirectFieldAccessor(advisor).getPropertyValue("advice.delegates");
@@ -94,6 +97,12 @@ public class CircuitBreakerTests {
assertEquals(20000L, accessor.getPropertyValue("retryOperations.retryPolicy.resetTimeout"));
assertEquals("#root instanceof RuntimeExpression",
accessor.getPropertyValue("retryOperations.retryPolicy.delegate.expression.expression"));
interceptor = (MethodInterceptor) methodMap.get(Service.class.getDeclaredMethod("expressionService2"));
accessor = new DirectFieldAccessor(interceptor);
assertEquals(10, accessor.getPropertyValue("retryOperations.retryPolicy.delegate.maxAttempts"));
assertEquals(10000L, accessor.getPropertyValue("retryOperations.retryPolicy.openTimeout"));
assertEquals(20000L, accessor.getPropertyValue("retryOperations.retryPolicy.resetTimeout"));
context.close();
}
@@ -106,6 +115,21 @@ public class CircuitBreakerTests {
return new ServiceImpl();
}
@Bean
Configs configs() {
return new Configs();
}
}
public static class Configs {
public int maxAttempts = 10;
public long openTimeout = 10000;
public long resetTimeout = 20000;
}
interface Service {
@@ -114,6 +138,8 @@ public class CircuitBreakerTests {
void expressionService();
void expressionService2();
int getCount();
RetryContext getContext();
@@ -143,6 +169,13 @@ public class CircuitBreakerTests {
this.count++;
}
@Override
@CircuitBreaker(maxAttemptsExpression = "@configs.maxAttempts", openTimeoutExpression = "@configs.openTimeout",
resetTimeoutExpression = "@configs.resetTimeout")
public void expressionService2() {
this.count++;
}
@Override
public RetryContext getContext() {
return this.context;