From 2f1c202c20f59db2873a20fb04537f9e4da42882 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Tue, 15 Nov 2022 14:47:46 -0500 Subject: [PATCH] GH-3945: Fix `not eligible for getting processed` (#3947) * GH-3945: Fix `not eligible for getting processed` Fixes https://github.com/spring-projects/spring-integration/issues/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 --- .../aop/MessagePublishingInterceptor.java | 37 ++++++++++--------- ...AbstractMethodAnnotationPostProcessor.java | 15 +++++--- .../IntegrationManagementConfiguration.java | 2 + 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aop/MessagePublishingInterceptor.java b/spring-integration-core/src/main/java/org/springframework/integration/aop/MessagePublishingInterceptor.java index 72a5dd20bc..1c61c845a6 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aop/MessagePublishingInterceptor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aop/MessagePublishingInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-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. @@ -70,10 +70,12 @@ public class MessagePublishingInterceptor implements MethodInterceptor, BeanFact private MessageBuilderFactory messageBuilderFactory = new DefaultMessageBuilderFactory(); - private boolean messageBuilderFactorySet; - private String defaultChannelName; + private volatile boolean messageBuilderFactorySet; + + private volatile boolean templateInitialized; + public MessagePublishingInterceptor(PublisherMetadataSource metadataSource) { Assert.notNull(metadataSource, "metadataSource must not be null"); this.metadataSource = metadataSource; @@ -94,10 +96,6 @@ public class MessagePublishingInterceptor implements MethodInterceptor, BeanFact @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; - this.messagingTemplate.setBeanFactory(beanFactory); - if (this.channelResolver == null) { - this.channelResolver = ChannelResolverUtils.getChannelResolver(this.beanFactory); - } } protected MessageBuilderFactory getMessageBuilderFactory() { @@ -111,8 +109,9 @@ public class MessagePublishingInterceptor implements MethodInterceptor, BeanFact } @Override - public final Object invoke(final MethodInvocation invocation) throws Throwable { - final StandardEvaluationContext context = ExpressionUtils.createStandardEvaluationContext(this.beanFactory); + public final Object invoke(MethodInvocation invocation) throws Throwable { + initMessagingTemplateIfAny(); + StandardEvaluationContext context = ExpressionUtils.createStandardEvaluationContext(this.beanFactory); Class targetClass = AopUtils.getTargetClass(invocation.getThis()); final Method method = AopUtils.getMostSpecificMethod(invocation.getMethod(), targetClass); String[] argumentNames = resolveArgumentNames(method); @@ -143,6 +142,16 @@ public class MessagePublishingInterceptor implements MethodInterceptor, BeanFact } } + private void initMessagingTemplateIfAny() { + if (!this.templateInitialized) { + this.messagingTemplate.setBeanFactory(this.beanFactory); + if (this.channelResolver == null) { + this.channelResolver = ChannelResolverUtils.getChannelResolver(this.beanFactory); + } + this.templateInitialized = true; + } + } + private String[] resolveArgumentNames(Method method) { return this.parameterNameDiscoverer.getParameterNames(method); } @@ -163,20 +172,14 @@ public class MessagePublishingInterceptor implements MethodInterceptor, BeanFact } Message message = builder.build(); String channelName = this.metadataSource.getChannelName(method); - MessageChannel channel = null; if (channelName != null) { - Assert.state(this.channelResolver != null, "ChannelResolver is required to resolve channel names."); - channel = this.channelResolver.resolveDestination(channelName); - } - if (channel != null) { - this.messagingTemplate.send(channel, message); + this.messagingTemplate.send(channelName, message); } else { String channelNameToUse = this.defaultChannelName; if (channelNameToUse != null && this.messagingTemplate.getDefaultDestination() == null) { Assert.state(this.channelResolver != null, "ChannelResolver is required to resolve channel names."); - this.messagingTemplate.setDefaultChannel( - this.channelResolver.resolveDestination(channelNameToUse)); + this.messagingTemplate.setDefaultChannel(this.channelResolver.resolveDestination(channelNameToUse)); this.defaultChannelName = null; } this.messagingTemplate.send(message); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/AbstractMethodAnnotationPostProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/config/AbstractMethodAnnotationPostProcessor.java index b3903955e5..4645a58431 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/AbstractMethodAnnotationPostProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/AbstractMethodAnnotationPostProcessor.java @@ -141,7 +141,7 @@ public abstract class AbstractMethodAnnotationPostProcessor channelResolver; + private volatile DestinationResolver channelResolver; @SuppressWarnings(UNCHECKED) public AbstractMethodAnnotationPostProcessor() { @@ -154,10 +154,10 @@ public abstract class AbstractMethodAnnotationPostProcessor getChannelResolver() { + if (this.channelResolver == null) { + this.channelResolver = ChannelResolverUtils.getChannelResolver(this.beanFactory); + } return this.channelResolver; } @@ -569,7 +572,7 @@ public abstract class AbstractMethodAnnotationPostProcessor