Skip to content

Commit 067de96

Browse files
committed
GH-3945: Fix not eligible for getting processed (#3947)
* GH-3945: Fix `not eligible for getting processed` Fixes #3945 The `IntegrationManagementConfiguration` produces an `IntegrationManagementConfigurer` which is a `BeanPostProcessor`. According to Spring recommendation this kind of infrastructure beans must be declared as `static`. Due to an `implements ImportAware, EnvironmentAware` nature of the `IntegrationManagementConfiguration`, we cannot use `static @Bean` method. But since the `IntegrationManagementConfiguration` is not involved in any bean post-processing, it is safe to follow recommendation and mark it as a `@Role(BeanDefinition.ROLE_INFRASTRUCTURE)`. * Fix `MessagePublishingInterceptor` to initialize `MessagingTemplate` and `DestinationResolver` lazily * Fix `AbstractMethodAnnotationPostProcessor` to initialize `DestinationResolver` lazily **Cherry-pick to `5.5.x`** * Use `getChannelResolver()` internally in the `AbstractMethodAnnotationPostProcessor` instead of direct property access which might not be initialized yet * Use a plain `boolean` for `templateInitialized` in the `MessagePublishingInterceptor` to avoid skips in other thread where and move on with still not initialized properties * Remove unused import * Fix `this.` prefix for `beanFactory` property reference # Conflicts: # spring-integration-core/src/main/java/org/springframework/integration/config/annotation/AbstractMethodAnnotationPostProcessor.java
1 parent e4e8041 commit 067de96

File tree

3 files changed

+36
-24
lines changed

3 files changed

+36
-24
lines changed

spring-integration-core/src/main/java/org/springframework/integration/aop/MessagePublishingInterceptor.java

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -70,10 +70,12 @@ public class MessagePublishingInterceptor implements MethodInterceptor, BeanFact
7070

7171
private MessageBuilderFactory messageBuilderFactory = new DefaultMessageBuilderFactory();
7272

73-
private boolean messageBuilderFactorySet;
74-
7573
private String defaultChannelName;
7674

75+
private volatile boolean messageBuilderFactorySet;
76+
77+
private volatile boolean templateInitialized;
78+
7779
public MessagePublishingInterceptor(PublisherMetadataSource metadataSource) {
7880
Assert.notNull(metadataSource, "metadataSource must not be null");
7981
this.metadataSource = metadataSource;
@@ -94,10 +96,6 @@ public void setChannelResolver(DestinationResolver<MessageChannel> channelResolv
9496
@Override
9597
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
9698
this.beanFactory = beanFactory;
97-
this.messagingTemplate.setBeanFactory(beanFactory);
98-
if (this.channelResolver == null) {
99-
this.channelResolver = ChannelResolverUtils.getChannelResolver(this.beanFactory);
100-
}
10199
}
102100

103101
protected MessageBuilderFactory getMessageBuilderFactory() {
@@ -111,8 +109,9 @@ protected MessageBuilderFactory getMessageBuilderFactory() {
111109
}
112110

113111
@Override
114-
public final Object invoke(final MethodInvocation invocation) throws Throwable {
115-
final StandardEvaluationContext context = ExpressionUtils.createStandardEvaluationContext(this.beanFactory);
112+
public final Object invoke(MethodInvocation invocation) throws Throwable {
113+
initMessagingTemplateIfAny();
114+
StandardEvaluationContext context = ExpressionUtils.createStandardEvaluationContext(this.beanFactory);
116115
Class<?> targetClass = AopUtils.getTargetClass(invocation.getThis());
117116
final Method method = AopUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
118117
String[] argumentNames = resolveArgumentNames(method);
@@ -143,6 +142,16 @@ public final Object invoke(final MethodInvocation invocation) throws Throwable {
143142
}
144143
}
145144

145+
private void initMessagingTemplateIfAny() {
146+
if (!this.templateInitialized) {
147+
this.messagingTemplate.setBeanFactory(this.beanFactory);
148+
if (this.channelResolver == null) {
149+
this.channelResolver = ChannelResolverUtils.getChannelResolver(this.beanFactory);
150+
}
151+
this.templateInitialized = true;
152+
}
153+
}
154+
146155
private String[] resolveArgumentNames(Method method) {
147156
return this.parameterNameDiscoverer.getParameterNames(method);
148157
}
@@ -163,20 +172,14 @@ private void publishMessage(Method method, StandardEvaluationContext context) {
163172
}
164173
Message<?> message = builder.build();
165174
String channelName = this.metadataSource.getChannelName(method);
166-
MessageChannel channel = null;
167175
if (channelName != null) {
168-
Assert.state(this.channelResolver != null, "ChannelResolver is required to resolve channel names.");
169-
channel = this.channelResolver.resolveDestination(channelName);
170-
}
171-
if (channel != null) {
172-
this.messagingTemplate.send(channel, message);
176+
this.messagingTemplate.send(channelName, message);
173177
}
174178
else {
175179
String channelNameToUse = this.defaultChannelName;
176180
if (channelNameToUse != null && this.messagingTemplate.getDefaultDestination() == null) {
177181
Assert.state(this.channelResolver != null, "ChannelResolver is required to resolve channel names.");
178-
this.messagingTemplate.setDefaultChannel(
179-
this.channelResolver.resolveDestination(channelNameToUse));
182+
this.messagingTemplate.setDefaultChannel(this.channelResolver.resolveDestination(channelNameToUse));
180183
this.defaultChannelName = null;
181184
}
182185
this.messagingTemplate.send(message);

spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationManagementConfiguration.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
* @since 4.2
4444
*/
4545
@Configuration(proxyBeanMethods = false)
46+
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
4647
public class IntegrationManagementConfiguration implements ImportAware, EnvironmentAware {
4748

4849
private AnnotationAttributes attributes;

spring-integration-core/src/main/java/org/springframework/integration/config/annotation/AbstractMethodAnnotationPostProcessor.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,25 +125,33 @@ public abstract class AbstractMethodAnnotationPostProcessor<T extends Annotation
125125

126126
protected final ConversionService conversionService; // NOSONAR
127127

128-
protected final DestinationResolver<MessageChannel> channelResolver; // NOSONAR
129-
130128
protected final Class<T> annotationType; // NOSONAR
131129

130+
private volatile DestinationResolver<MessageChannel> channelResolver;
131+
132132
@SuppressWarnings(UNCHECKED)
133133
public AbstractMethodAnnotationPostProcessor(ConfigurableListableBeanFactory beanFactory) {
134134
Assert.notNull(beanFactory, "'beanFactory' must not be null");
135135
this.messageHandlerAttributes.add(SEND_TIMEOUT_ATTRIBUTE);
136136
this.beanFactory = beanFactory;
137137
this.definitionRegistry = (BeanDefinitionRegistry) beanFactory;
138-
this.conversionService = this.beanFactory.getConversionService() != null
139-
? this.beanFactory.getConversionService()
140-
: DefaultConversionService.getSharedInstance();
141-
this.channelResolver = ChannelResolverUtils.getChannelResolver(beanFactory);
138+
this.conversionService =
139+
this.beanFactory.getConversionService() != null
140+
? this.beanFactory.getConversionService()
141+
: DefaultConversionService.getSharedInstance();
142142
this.annotationType =
143143
(Class<T>) GenericTypeResolver.resolveTypeArgument(this.getClass(),
144144
MethodAnnotationPostProcessor.class);
145145
}
146146

147+
148+
protected DestinationResolver<MessageChannel> getChannelResolver() {
149+
if (this.channelResolver == null) {
150+
this.channelResolver = ChannelResolverUtils.getChannelResolver(this.beanFactory);
151+
}
152+
return this.channelResolver;
153+
}
154+
147155
@Override
148156
public Object postProcess(Object bean, String beanName, Method method, List<Annotation> annotations) {
149157
Object sourceHandler = null;
@@ -332,7 +340,7 @@ protected AbstractEndpoint createEndpoint(MessageHandler handler, @SuppressWarni
332340
if (StringUtils.hasText(inputChannelName)) {
333341
MessageChannel inputChannel;
334342
try {
335-
inputChannel = this.channelResolver.resolveDestination(inputChannelName);
343+
inputChannel = getChannelResolver().resolveDestination(inputChannelName);
336344
}
337345
catch (DestinationResolutionException e) {
338346
if (e.getCause() instanceof NoSuchBeanDefinitionException) {

0 commit comments

Comments
 (0)