Skip to content

Commit eed16f0

Browse files
artembilangaryrussell
authored andcommitted
Fix BeanFactory propagation for MMInvokerHelper (#2694)
* Fix BeanFactory propagation for MMInvokerHelper * Remove check for `null` in the `MessagingMethodInvokerHelper.isProvidedMessageHandlerFactoryBean()` * Fix `RecipientListRouter` for `BeanFactory` propagation to the `Recipient.selector` * Fix tests for `BeanFactory` population and propagation * Add `errorChannel` into the `TestUtils.createTestApplicationContext()` * Fix some Sonar smell, including new reported * * Restore NPE check for the `BeanFactory` in the `MessagingMethodInvokerHelper` to avoid breaking changes in the current point release * Some other polishing and optimizations in the `MessagingMethodInvokerHelper`
1 parent 63684e2 commit eed16f0

File tree

47 files changed

+1163
-679
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1163
-679
lines changed

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

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -98,17 +98,17 @@ public abstract class AbstractMethodAnnotationPostProcessor<T extends Annotation
9898

9999
protected static final String SEND_TIMEOUT_ATTRIBUTE = "sendTimeout";
100100

101-
protected final Log logger = LogFactory.getLog(this.getClass());
101+
protected final Log logger = LogFactory.getLog(this.getClass()); // NOSONAR
102102

103-
protected final List<String> messageHandlerAttributes = new ArrayList<>();
103+
protected final List<String> messageHandlerAttributes = new ArrayList<>(); // NOSONAR
104104

105-
protected final ConfigurableListableBeanFactory beanFactory;
105+
protected final ConfigurableListableBeanFactory beanFactory; // NOSONAR
106106

107-
protected final ConversionService conversionService;
107+
protected final ConversionService conversionService; // NOSONAR
108108

109-
protected final DestinationResolver<MessageChannel> channelResolver;
109+
protected final DestinationResolver<MessageChannel> channelResolver; // NOSONAR
110110

111-
protected final Class<T> annotationType;
111+
protected final Class<T> annotationType; // NOSONAR
112112

113113
protected final Disposables disposables; // NOSONAR
114114

@@ -192,7 +192,8 @@ public Object postProcess(Object bean, String beanName, Method method, List<Anno
192192

193193
if (AnnotatedElementUtils.isAnnotated(method, IdempotentReceiver.class.getName())
194194
&& !AnnotatedElementUtils.isAnnotated(method, Bean.class.getName())) {
195-
String[] interceptors = AnnotationUtils.getAnnotation(method, IdempotentReceiver.class).value(); // NOSONAR never null
195+
String[] interceptors =
196+
AnnotationUtils.getAnnotation(method, IdempotentReceiver.class).value(); // NOSONAR never null
196197
for (String interceptor : interceptors) {
197198
DefaultBeanFactoryPointcutAdvisor advisor = new DefaultBeanFactoryPointcutAdvisor();
198199
advisor.setAdviceBeanName(interceptor);
@@ -281,9 +282,7 @@ else if (adviceChainBean instanceof Advice[]) {
281282
else if (adviceChainBean instanceof Collection) {
282283
@SuppressWarnings("unchecked")
283284
Collection<Advice> adviceChainEntries = (Collection<Advice>) adviceChainBean;
284-
for (Advice advice : adviceChainEntries) {
285-
adviceChain.add(advice);
286-
}
285+
adviceChain.addAll(adviceChainEntries);
287286
}
288287
else {
289288
throw new IllegalArgumentException("Invalid advice chain type:" +
@@ -346,7 +345,7 @@ protected AbstractEndpoint doCreateEndpoint(MessageHandler handler, MessageChann
346345
}
347346

348347
protected void configurePollingEndpoint(AbstractPollingEndpoint pollingEndpoint, List<Annotation> annotations) {
349-
PollerMetadata pollerMetadata = null;
348+
PollerMetadata pollerMetadata;
350349
Poller[] pollers = MessagingAnnotationUtils.resolveAttribute(annotations, "poller", Poller[].class);
351350
if (!ObjectUtils.isEmpty(pollers)) {
352351
Assert.state(pollers.length == 1,

spring-integration-core/src/main/java/org/springframework/integration/handler/BeanNameMessageProcessor.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,10 @@ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
5656
public T processMessage(Message<?> message) {
5757
if (this.delegate == null) {
5858
Object target = this.beanFactory.getBean(this.beanName);
59-
this.delegate = new MethodInvokingMessageProcessor<>(target, this.methodName);
59+
MethodInvokingMessageProcessor<T> methodInvokingMessageProcessor =
60+
new MethodInvokingMessageProcessor<>(target, this.methodName);
61+
methodInvokingMessageProcessor.setBeanFactory(this.beanFactory);
62+
this.delegate = methodInvokingMessageProcessor;
6063
}
6164
return this.delegate.processMessage(message);
6265
}

spring-integration-core/src/main/java/org/springframework/integration/handler/support/MessagingMethodInvokerHelper.java

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -437,14 +437,14 @@ private void prepareEvaluationContext() throws Exception {
437437
if (this.expectedType != null) {
438438
Assert.state(context.getTypeConverter()
439439
.canConvert(TypeDescriptor.valueOf((this.method).getReturnType()), this.expectedType),
440-
"Cannot convert to expected type (" + this.expectedType + ") from " + this.method);
440+
() -> "Cannot convert to expected type (" + this.expectedType + ") from " + this.method);
441441
}
442442
}
443443
else {
444444
AnnotatedMethodFilter filter = new AnnotatedMethodFilter(this.annotationType, this.methodName,
445445
this.requiresReply);
446446
Assert.state(canReturnExpectedType(filter, targetType, context.getTypeConverter()),
447-
"Cannot convert to expected type (" + this.expectedType + ") from " + this.method);
447+
() -> "Cannot convert to expected type (" + this.expectedType + ") from " + this.method);
448448
context.registerMethodFilter(targetType, filter);
449449
}
450450
context.setVariable("target", this.targetObject);
@@ -705,9 +705,7 @@ && contentTypeIsJson(parameters.message)) {
705705

706706
}
707707
catch (Exception e) {
708-
if (logger.isDebugEnabled()) {
709-
logger.debug("Failed to convert from JSON", e);
710-
}
708+
logger.debug("Failed to convert from JSON", e);
711709
}
712710
}
713711
}
@@ -901,13 +899,14 @@ else if (!Modifier.isPublic(method1.getModifiers())) {
901899
}
902900

903901
Assert.state(!fallbackMethods.isEmpty() || !fallbackMessageMethods.isEmpty(),
904-
"Target object of type [" + this.targetObject.getClass() +
902+
() -> "Target object of type [" + this.targetObject.getClass() +
905903
"] has no eligible methods for handling Messages.");
906904

907-
Assert.isNull(ambiguousFallbackType.get(), "Found ambiguous parameter type [" + ambiguousFallbackType
908-
+ "] for method match: " + fallbackMethods.values());
905+
Assert.isNull(ambiguousFallbackType.get(),
906+
() -> "Found ambiguous parameter type [" + ambiguousFallbackType +
907+
"] for method match: " + fallbackMethods.values());
909908
Assert.isNull(ambiguousFallbackMessageGenericType.get(),
910-
"Found ambiguous parameter type ["
909+
() -> "Found ambiguous parameter type ["
911910
+ ambiguousFallbackMessageGenericType
912911
+ "] for method match: "
913912
+ fallbackMethods.values());
@@ -969,8 +968,9 @@ private void findSingleSpecifMethodOnInterfacesIfProxy(final Object targetObject
969968
}
970969

971970
private void checkSpelInvokerRequired(final Class<?> targetClass, Method methodArg, HandlerMethod handlerMethod) {
972-
UseSpelInvoker useSpel = AnnotationUtils.findAnnotation(AopUtils.getMostSpecificMethod(methodArg, targetClass),
973-
UseSpelInvoker.class);
971+
UseSpelInvoker useSpel =
972+
AnnotationUtils.findAnnotation(AopUtils.getMostSpecificMethod(methodArg, targetClass),
973+
UseSpelInvoker.class);
974974
if (useSpel == null) {
975975
useSpel = AnnotationUtils.findAnnotation(targetClass, UseSpelInvoker.class);
976976
}
@@ -1007,14 +1007,12 @@ private Class<?> getTargetClass(Object targetObject) {
10071007
try {
10081008
// Maybe a proxy with no target - e.g. gateway
10091009
Class<?>[] interfaces = ((Advised) targetObject).getProxiedInterfaces();
1010-
if (interfaces != null && interfaces.length == 1) {
1010+
if (interfaces.length == 1) {
10111011
targetClass = interfaces[0];
10121012
}
10131013
}
10141014
catch (Exception e) {
1015-
if (logger.isDebugEnabled()) {
1016-
logger.debug("Exception trying to extract interface", e);
1017-
}
1015+
logger.debug("Exception trying to extract interface", e);
10181016
}
10191017
}
10201018
}
@@ -1135,7 +1133,10 @@ public String toString() {
11351133
}
11361134

11371135
private String generateExpression(Method method) {
1138-
StringBuilder sb = new StringBuilder("#target." + method.getName() + "(");
1136+
StringBuilder sb =
1137+
new StringBuilder("#target.")
1138+
.append(method.getName())
1139+
.append('(');
11391140
Class<?>[] parameterTypes = method.getParameterTypes();
11401141
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
11411142
boolean hasUnqualifiedMapParameter = false;
@@ -1163,9 +1164,8 @@ private String generateExpression(Method method) {
11631164
}
11641165
if (annotationType.equals(Payloads.class)) {
11651166
Assert.isTrue(this.canProcessMessageList,
1166-
"The @Payloads annotation can only be applied if method handler " +
1167-
"canProcessMessageList" +
1168-
".");
1167+
"The @Payloads annotation can only be applied " +
1168+
"if method handler canProcessMessageList.");
11691169
Assert.isTrue(Collection.class.isAssignableFrom(parameterType),
11701170
"The @Payloads annotation can only be applied to a Collection-typed parameter.");
11711171
sb.append("messages.![payload");
@@ -1350,9 +1350,7 @@ public static class ParametersWrapper {
13501350
*/
13511351
public static Object getHeader(Map<?, ?> headers, String header) {
13521352
Object object = headers.get(header);
1353-
if (object == null) {
1354-
throw new IllegalArgumentException("required header not available: " + header);
1355-
}
1353+
Assert.notNull(object, () -> "required header not available: " + header);
13561354
return object;
13571355
}
13581356

spring-integration-core/src/main/java/org/springframework/integration/router/RecipientListRouter.java

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import java.util.concurrent.ConcurrentLinkedQueue;
2929
import java.util.stream.Collectors;
3030

31+
import org.springframework.beans.factory.BeanFactory;
32+
import org.springframework.beans.factory.BeanFactoryAware;
3133
import org.springframework.beans.factory.InitializingBean;
3234
import org.springframework.integration.core.MessageSelector;
3335
import org.springframework.integration.filter.ExpressionEvaluatingSelector;
@@ -97,9 +99,8 @@ public void setRecipients(List<Recipient> recipients) {
9799
Assert.notEmpty(recipients, "'recipients' must not be empty");
98100
Queue<Recipient> newRecipients = new ConcurrentLinkedQueue<>(recipients);
99101

100-
if (getBeanFactory() != null) {
101-
newRecipients.forEach(recipient -> recipient.setChannelResolver(getChannelResolver()));
102-
}
102+
newRecipients.forEach(this::setupRecipient);
103+
103104
if (logger.isDebugEnabled()) {
104105
logger.debug("Channel Recipients: " + this.recipients + " replaced with: " + newRecipients);
105106
}
@@ -145,9 +146,7 @@ private void addRecipient(String channelName, String selectorExpression, Queue<R
145146
new ExpressionEvaluatingSelector(selectorExpression);
146147
expressionEvaluatingSelector.setBeanFactory(getBeanFactory());
147148
Recipient recipient = new Recipient(channelName, expressionEvaluatingSelector);
148-
if (getBeanFactory() != null) {
149-
recipient.setChannelResolver(getChannelResolver());
150-
}
149+
setupRecipient(recipient);
151150
recipients.add(recipient);
152151
}
153152

@@ -164,9 +163,7 @@ public void addRecipient(String channelName, MessageSelector selector) {
164163
private void addRecipient(String channelName, MessageSelector selector, Queue<Recipient> recipients) {
165164
Assert.hasText(channelName, "'channelName' must not be empty.");
166165
Recipient recipient = new Recipient(channelName, selector);
167-
if (getBeanFactory() != null) {
168-
recipient.setChannelResolver(getChannelResolver());
169-
}
166+
setupRecipient(recipient);
170167
recipients.add(recipient);
171168
}
172169

@@ -176,10 +173,18 @@ public void addRecipient(MessageChannel channel) {
176173

177174
public void addRecipient(MessageChannel channel, MessageSelector selector) {
178175
Recipient recipient = new Recipient(channel, selector);
179-
if (getBeanFactory() != null) {
176+
setupRecipient(recipient);
177+
this.recipients.add(recipient);
178+
}
179+
180+
private void setupRecipient(Recipient recipient) {
181+
BeanFactory beanFactory = getBeanFactory();
182+
if (beanFactory != null) {
180183
recipient.setChannelResolver(getChannelResolver());
184+
if (recipient.selector instanceof BeanFactoryAware) {
185+
((BeanFactoryAware) recipient.selector).setBeanFactory(beanFactory);
186+
}
181187
}
182-
this.recipients.add(recipient);
183188
}
184189

185190
@Override
@@ -225,14 +230,14 @@ public void replaceRecipients(Properties recipientMappings) {
225230
for (String key : keys) {
226231
Assert.notNull(key, "channelName can't be null.");
227232
if (StringUtils.hasText(recipientMappings.getProperty(key))) {
228-
this.addRecipient(key, recipientMappings.getProperty(key));
233+
addRecipient(key, recipientMappings.getProperty(key));
229234
}
230235
else {
231-
this.addRecipient(key);
236+
addRecipient(key);
232237
}
233238
}
234239
if (logger.isDebugEnabled()) {
235-
logger.debug("Channel Recipients:" + originalRecipients + " replaced with:" + this.recipients);
240+
logger.debug("Channel Recipients:" + originalRecipients + " replaced with:" + this.recipients);
236241
}
237242
}
238243

@@ -259,7 +264,7 @@ protected Collection<MessageChannel> determineTargetChannels(Message<?> message)
259264
@Override
260265
protected void onInit() {
261266
super.onInit();
262-
this.recipients.forEach(recipient -> recipient.setChannelResolver(getChannelResolver()));
267+
this.recipients.forEach(this::setupRecipient);
263268
}
264269

265270
public static class Recipient {

spring-integration-core/src/test/java/org/springframework/integration/aggregator/CorrelationStrategyAdapterTests.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2019 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.
@@ -17,17 +17,20 @@
1717
package org.springframework.integration.aggregator;
1818

1919
import static org.junit.Assert.assertEquals;
20+
import static org.mockito.Mockito.mock;
2021

2122
import org.junit.Before;
2223
import org.junit.Test;
2324

25+
import org.springframework.beans.factory.BeanFactory;
2426
import org.springframework.integration.support.MessageBuilder;
2527
import org.springframework.messaging.Message;
2628
import org.springframework.messaging.handler.annotation.Header;
2729
import org.springframework.util.ReflectionUtils;
2830

2931
/**
3032
* @author Dave Syer
33+
* @author Artem Bilan
3134
*
3235
*/
3336
public class CorrelationStrategyAdapterTests {
@@ -43,34 +46,40 @@ public void init() {
4346
public void testMethodName() {
4447
MethodInvokingCorrelationStrategy adapter =
4548
new MethodInvokingCorrelationStrategy(new SimpleMessageCorrelator(), "getKey");
49+
adapter.setBeanFactory(mock(BeanFactory.class));
4650
assertEquals("b", adapter.getCorrelationKey(message));
4751
}
4852

4953
@Test
5054
public void testCorrelationStrategyAdapterObjectMethod() {
51-
MethodInvokingCorrelationStrategy adapter = new MethodInvokingCorrelationStrategy(new SimpleMessageCorrelator(),
55+
MethodInvokingCorrelationStrategy adapter =
56+
new MethodInvokingCorrelationStrategy(new SimpleMessageCorrelator(),
5257
ReflectionUtils.findMethod(SimpleMessageCorrelator.class, "getKey", Message.class));
58+
adapter.setBeanFactory(mock(BeanFactory.class));
5359
assertEquals("b", adapter.getCorrelationKey(message));
5460
}
5561

5662
@Test
5763
public void testCorrelationStrategyAdapterPojoMethod() {
5864
MethodInvokingCorrelationStrategy adapter =
5965
new MethodInvokingCorrelationStrategy(new SimplePojoCorrelator(), "getKey");
66+
adapter.setBeanFactory(mock(BeanFactory.class));
6067
assertEquals("foo", adapter.getCorrelationKey(message));
6168
}
6269

6370
@Test
6471
public void testHeaderPojoMethod() {
6572
MethodInvokingCorrelationStrategy adapter =
6673
new MethodInvokingCorrelationStrategy(new SimpleHeaderCorrelator(), "getKey");
74+
adapter.setBeanFactory(mock(BeanFactory.class));
6775
assertEquals("b", adapter.getCorrelationKey(message));
6876
}
6977

7078
@Test
7179
public void testHeadersPojoMethod() {
7280
MethodInvokingCorrelationStrategy adapter = new MethodInvokingCorrelationStrategy(new MultiHeaderCorrelator(),
7381
ReflectionUtils.findMethod(MultiHeaderCorrelator.class, "getKey", String.class, String.class));
82+
adapter.setBeanFactory(mock(BeanFactory.class));
7483
assertEquals("bd", adapter.getCorrelationKey(message));
7584
}
7685

0 commit comments

Comments
 (0)