-
Notifications
You must be signed in to change notification settings - Fork 1.6k
GH-2967: Some minor improvements in RetryableTopicAnnotationProcessor #2967
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -82,8 +82,8 @@ public class RetryableTopicAnnotationProcessor { | |
* @param beanFactory the bean factory. | ||
*/ | ||
public RetryableTopicAnnotationProcessor(BeanFactory beanFactory) { | ||
this(beanFactory, new StandardBeanExpressionResolver(), beanFactory instanceof ConfigurableBeanFactory | ||
? new BeanExpressionContext((ConfigurableBeanFactory) beanFactory, null) | ||
this(beanFactory, new StandardBeanExpressionResolver(), beanFactory instanceof ConfigurableBeanFactory cbf | ||
? new BeanExpressionContext(cbf, null) | ||
: null); // NOSONAR | ||
} | ||
|
||
|
@@ -101,7 +101,6 @@ public RetryableTopicAnnotationProcessor(BeanFactory beanFactory, BeanExpression | |
this.expressionContext = expressionContext; | ||
} | ||
|
||
@SuppressWarnings("deprecation") | ||
public RetryTopicConfiguration processAnnotation(String[] topics, Method method, RetryableTopic annotation, | ||
Object bean) { | ||
|
||
|
@@ -121,16 +120,14 @@ public RetryTopicConfiguration processAnnotation(String[] topics, Method method, | |
traverse = traverseResolved; | ||
} | ||
else { | ||
traverse = includes.size() > 0 || excludes.size() > 0; | ||
traverse = !includes.isEmpty() || !excludes.isEmpty(); | ||
} | ||
} | ||
Boolean autoStartDlt = null; | ||
if (StringUtils.hasText(annotation.autoStartDltHandler())) { | ||
autoStartDlt = resolveExpressionAsBoolean(annotation.autoStartDltHandler(), "autoStartDltContainer"); | ||
} | ||
return RetryTopicConfigurationBuilder.newInstance() | ||
.maxAttempts(resolveExpressionAsInteger(annotation.attempts(), "attempts", true)) | ||
.concurrency(resolveExpressionAsInteger(annotation.concurrency(), "concurrency", false)) | ||
RetryTopicConfigurationBuilder builder = RetryTopicConfigurationBuilder.newInstance() | ||
.customBackoff(createBackoffFromAnnotation(annotation.backoff(), this.beanFactory)) | ||
.retryTopicSuffix(resolveExpressionAsString(annotation.retryTopicSuffix(), "retryTopicSuffix")) | ||
.dltSuffix(resolveExpressionAsString(annotation.dltTopicSuffix(), "dltTopicSuffix")) | ||
|
@@ -147,8 +144,17 @@ public RetryTopicConfiguration processAnnotation(String[] topics, Method method, | |
.autoStartDltHandler(autoStartDlt) | ||
.setTopicSuffixingStrategy(annotation.topicSuffixingStrategy()) | ||
.sameIntervalTopicReuseStrategy(annotation.sameIntervalTopicReuseStrategy()) | ||
.timeoutAfter(timeout) | ||
.create(getKafkaTemplate(resolveExpressionAsString(annotation.kafkaTemplate(), "kafkaTemplate"), topics)); | ||
.timeoutAfter(timeout); | ||
|
||
Integer attempts = resolveExpressionAsInteger(annotation.attempts(), "attempts", true); | ||
if (attempts != null) { | ||
builder.maxAttempts(attempts); | ||
} | ||
Integer concurrency = resolveExpressionAsInteger(annotation.concurrency(), "concurrency", false); | ||
if (concurrency != null) { | ||
builder.concurrency(concurrency); | ||
} | ||
return builder.create(getKafkaTemplate(resolveExpressionAsString(annotation.kafkaTemplate(), "kafkaTemplate"), topics)); | ||
} | ||
|
||
private SleepingBackOffPolicy<?> createBackoffFromAnnotation(Backoff backoff, BeanFactory beanFactory) { // NOSONAR | ||
|
@@ -173,9 +179,13 @@ private SleepingBackOffPolicy<?> createBackoffFromAnnotation(Backoff backoff, Be | |
if (backoff.random()) { | ||
policy = new ExponentialRandomBackOffPolicy(); | ||
} | ||
policy.setInitialInterval(min); | ||
if (min != null) { | ||
policy.setInitialInterval(min); | ||
} | ||
policy.setMultiplier(multiplier); | ||
policy.setMaxInterval(max > min ? max : ExponentialBackOffPolicy.DEFAULT_MAX_INTERVAL); | ||
if (max != null && min != null && max > min) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What will There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good comment! Below is the relevant code snippet:
so regardless of whether we set the same default value or not in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let me know whether we need to revert back old behaviour. I am perfectly fine with either way. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But don't we need to set that value in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As I showed above, the policy class will set the fields to default values already just after the instance was initiated but before constructor is invoked, so after the default constructor was invoked, we have ended up with valid state already. Am I missing something here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I got it. Thanks for the explanation. |
||
policy.setMaxInterval(max); | ||
} | ||
return policy; | ||
} | ||
if (max != null && min != null && max > min) { | ||
|
@@ -200,7 +210,6 @@ private EndpointHandlerMethod getDltProcessor(Method listenerMethod, Object bean | |
.orElse(RetryTopicConfigurer.DEFAULT_DLT_HANDLER); | ||
} | ||
|
||
@SuppressWarnings("deprecation") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. seems leftover of previous JDK. In JDK17, I saw no compiling warnings after the removal of it. |
||
private KafkaOperations<?, ?> getKafkaTemplate(String kafkaTemplateName, String[] topics) { | ||
if (StringUtils.hasText(kafkaTemplateName)) { | ||
Assert.state(this.beanFactory != null, "BeanFactory must be set to obtain kafka template by bean name"); | ||
|
@@ -213,6 +222,7 @@ private EndpointHandlerMethod getDltProcessor(Method listenerMethod, Object bean | |
+ " with id '" + kafkaTemplateName + "' was found in the application context", ex); | ||
} | ||
} | ||
Assert.state(this.beanFactory != null, "BeanFactory must be set to obtain kafka template by default bean name"); | ||
try { | ||
return this.beanFactory.getBean(RetryTopicBeanNames.DEFAULT_KAFKA_TEMPLATE_BEAN_NAME, | ||
KafkaOperations.class); | ||
|
@@ -228,8 +238,8 @@ private EndpointHandlerMethod getDltProcessor(Method listenerMethod, Object bean | |
|
||
private String resolveExpressionAsString(String value, String attribute) { | ||
Object resolved = resolveExpression(value); | ||
if (resolved instanceof String) { | ||
return (String) resolved; | ||
if (resolved instanceof String str) { | ||
return str; | ||
} | ||
else if (resolved != null) { | ||
throw new IllegalStateException(THE_OSQ + attribute + "] must resolve to a String. " | ||
|
@@ -241,16 +251,13 @@ else if (resolved != null) { | |
private Integer resolveExpressionAsInteger(String value, String attribute, boolean required) { | ||
Object resolved = resolveExpression(value); | ||
Integer result = null; | ||
if (resolved instanceof String) { | ||
if (!required && !StringUtils.hasText((String) resolved)) { | ||
result = null; | ||
} | ||
else { | ||
result = Integer.parseInt((String) resolved); | ||
if (resolved instanceof String str) { | ||
if (required || StringUtils.hasText(str)) { | ||
result = Integer.parseInt(str); | ||
} | ||
} | ||
else if (resolved instanceof Number) { | ||
result = ((Number) resolved).intValue(); | ||
else if (resolved instanceof Number num) { | ||
result = num.intValue(); | ||
} | ||
else if (resolved != null || required) { | ||
throw new IllegalStateException( | ||
|
@@ -264,16 +271,13 @@ else if (resolved != null || required) { | |
private Short resolveExpressionAsShort(String value, String attribute, boolean required) { | ||
Object resolved = resolveExpression(value); | ||
Short result = null; | ||
if (resolved instanceof String) { | ||
if (!required && !StringUtils.hasText((String) resolved)) { | ||
result = null; | ||
} | ||
else { | ||
result = Short.parseShort((String) resolved); | ||
if (resolved instanceof String str) { | ||
if (required || StringUtils.hasText(str)) { | ||
result = Short.parseShort(str); | ||
} | ||
} | ||
else if (resolved instanceof Number) { | ||
result = ((Number) resolved).shortValue(); | ||
else if (resolved instanceof Number num) { | ||
result = num.shortValue(); | ||
} | ||
else if (resolved != null || required) { | ||
throw new IllegalStateException( | ||
|
@@ -287,16 +291,13 @@ else if (resolved != null || required) { | |
private Long resolveExpressionAsLong(String value, String attribute, boolean required) { | ||
Object resolved = resolveExpression(value); | ||
Long result = null; | ||
if (resolved instanceof String) { | ||
if (!required && !StringUtils.hasText((String) resolved)) { | ||
result = null; | ||
} | ||
else { | ||
result = Long.parseLong((String) resolved); | ||
if (resolved instanceof String str) { | ||
if (required || StringUtils.hasText(str)) { | ||
result = Long.parseLong(str); | ||
} | ||
} | ||
else if (resolved instanceof Number) { | ||
result = ((Number) resolved).longValue(); | ||
else if (resolved instanceof Number num) { | ||
result = num.longValue(); | ||
} | ||
else if (resolved != null || required) { | ||
throw new IllegalStateException( | ||
|
@@ -310,16 +311,13 @@ else if (resolved != null || required) { | |
private Double resolveExpressionAsDouble(String value, String attribute, boolean required) { | ||
Object resolved = resolveExpression(value); | ||
Double result = null; | ||
if (resolved instanceof String) { | ||
if (!required && !StringUtils.hasText((String) resolved)) { | ||
result = null; | ||
} | ||
else { | ||
result = Double.parseDouble((String) resolved); | ||
if (resolved instanceof String str) { | ||
if (required || StringUtils.hasText(str)) { | ||
result = Double.parseDouble(str); | ||
} | ||
} | ||
else if (resolved instanceof Number) { | ||
result = ((Number) resolved).doubleValue(); | ||
else if (resolved instanceof Number num) { | ||
result = num.doubleValue(); | ||
} | ||
else if (resolved != null || required) { | ||
throw new IllegalStateException( | ||
|
@@ -333,11 +331,11 @@ else if (resolved != null || required) { | |
private Boolean resolveExpressionAsBoolean(String value, String attribute) { | ||
Object resolved = resolveExpression(value); | ||
Boolean result = null; | ||
if (resolved instanceof Boolean) { | ||
result = (Boolean) resolved; | ||
if (resolved instanceof Boolean bool) { | ||
result = bool; | ||
} | ||
else if (resolved instanceof String) { | ||
result = Boolean.parseBoolean((String) resolved); | ||
else if (resolved instanceof String str) { | ||
result = Boolean.parseBoolean(str); | ||
} | ||
else if (resolved != null) { | ||
throw new IllegalStateException( | ||
|
@@ -368,8 +366,8 @@ private List<Class<? extends Throwable>> resolveClasses(Class<? extends Throwabl | |
} | ||
|
||
private Object resolveExpression(String value) { | ||
String resolved = resolve(value); | ||
if (this.expressionContext != null) { | ||
String resolved = resolve(value); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. seems the |
||
return this.resolver.evaluate(resolved, this.expressionContext); | ||
} | ||
else { | ||
|
@@ -378,8 +376,8 @@ private Object resolveExpression(String value) { | |
} | ||
|
||
private String resolve(String value) { | ||
if (this.beanFactory != null && this.beanFactory instanceof ConfigurableBeanFactory) { | ||
return ((ConfigurableBeanFactory) this.beanFactory).resolveEmbeddedValue(value); | ||
if (this.beanFactory instanceof ConfigurableBeanFactory cbf) { | ||
return cbf.resolveEmbeddedValue(value); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. of course, the original nullness checking is unnecessary for |
||
} | ||
return value; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there are many loose ends regarding nullness safety net. Not sure why there is no usage of the following two entries in the package-info.java within the package of
annotation
:if we added them, many NPE issues in this package would be better exposed.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. Feel free to send another PR with that change if you are up to it.