From db0a050f58fd0dfbad170514bfa7d03226065779 Mon Sep 17 00:00:00 2001 From: Gary Russell Date: Wed, 20 Apr 2022 13:35:28 -0400 Subject: [PATCH] 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 --- ...tationAwareRetryOperationsInterceptor.java | 28 ++++++++++++--- .../retry/annotation/CircuitBreakerTests.java | 35 ++++++++++++++++++- 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/springframework/retry/annotation/AnnotationAwareRetryOperationsInterceptor.java b/src/main/java/org/springframework/retry/annotation/AnnotationAwareRetryOperationsInterceptor.java index a06b960..a851852 100644 --- a/src/main/java/org/springframework/retry/annotation/AnnotationAwareRetryOperationsInterceptor.java +++ b/src/main/java/org/springframework/retry/annotation/AnnotationAwareRetryOperationsInterceptor.java @@ -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) { diff --git a/src/test/java/org/springframework/retry/annotation/CircuitBreakerTests.java b/src/test/java/org/springframework/retry/annotation/CircuitBreakerTests.java index 6f07d55..62aa5c1 100644 --- a/src/test/java/org/springframework/retry/annotation/CircuitBreakerTests.java +++ b/src/test/java/org/springframework/retry/annotation/CircuitBreakerTests.java @@ -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;