Skip to content

Commit 0d13128

Browse files
olegzartembilan
authored andcommitted
INT-4571 Make MessageHandlerMethodFactory injectable
Make MessageHandlerMethodFactory injectable into MessagingMethodInvokerHelper Allow 'handlerMethod' to be overridden Deprecate HandlerMethodArgumentResolversHolder Add 'integrationMessageHandlerMethodFactory' property to IntegrationContextUtils Add test that actually validates that custom resolver gets picked up * Polishing code style and some code smells
1 parent 1d5e66b commit 0d13128

File tree

5 files changed

+199
-75
lines changed

5 files changed

+199
-75
lines changed

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

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@
5757
import org.springframework.integration.context.IntegrationProperties;
5858
import org.springframework.integration.handler.LoggingHandler;
5959
import org.springframework.integration.handler.support.CollectionArgumentResolver;
60-
import org.springframework.integration.handler.support.HandlerMethodArgumentResolversHolder;
6160
import org.springframework.integration.handler.support.MapArgumentResolver;
6261
import org.springframework.integration.handler.support.PayloadExpressionArgumentResolver;
6362
import org.springframework.integration.handler.support.PayloadsArgumentResolver;
@@ -187,7 +186,8 @@ private void registerErrorChannel() {
187186
if (!this.beanFactory.containsBean(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME)) {
188187
if (logger.isInfoEnabled()) {
189188
logger.info("No bean named '" + IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME +
190-
"' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created.");
189+
"' has been explicitly defined. " +
190+
"Therefore, a default PublishSubscribeChannel will be created.");
191191
}
192192
this.registry.registerBeanDefinition(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME,
193193
new RootBeanDefinition(PublishSubscribeChannel.class));
@@ -273,7 +273,8 @@ private void registerTaskScheduler() {
273273
if (!this.beanFactory.containsBean(IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME)) {
274274
if (logger.isInfoEnabled()) {
275275
logger.info("No bean named '" + IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME +
276-
"' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created.");
276+
"' has been explicitly defined. " +
277+
"Therefore, a default ThreadPoolTaskScheduler will be created.");
277278
}
278279
BeanDefinition scheduler = BeanDefinitionBuilder.genericBeanDefinition(ThreadPoolTaskScheduler.class)
279280
.addPropertyValue("poolSize", IntegrationProperties
@@ -479,7 +480,8 @@ private void registerArgumentResolverMessageConverter() {
479480
}
480481

481482
/**
482-
* Register the default {@link HandlerMethodArgumentResolversHolder} for handler
483+
* Register the default
484+
* {@link org.springframework.integration.handler.support.HandlerMethodArgumentResolversHolder} for handler
483485
* method invocation.
484486
*/
485487
private void registerArgumentResolvers() {
@@ -490,7 +492,8 @@ private void registerArgumentResolvers() {
490492
}
491493

492494
/**
493-
* Register the default {@link HandlerMethodArgumentResolversHolder} for handler
495+
* Register the default
496+
* {@link org.springframework.integration.handler.support.HandlerMethodArgumentResolversHolder} for handler
494497
* method invocation for lists.
495498
*/
496499
private void registerListCapableArgumentResolvers() {
@@ -500,6 +503,7 @@ private void registerListCapableArgumentResolvers() {
500503
}
501504
}
502505

506+
@SuppressWarnings("deprecation")
503507
private BeanDefinition internalArgumentResolversBuilder(boolean listCapable) {
504508
ManagedList<BeanDefinition> resolvers = new ManagedList<>();
505509
resolvers.add(new RootBeanDefinition(PayloadExpressionArgumentResolver.class));
@@ -518,7 +522,8 @@ private BeanDefinition internalArgumentResolversBuilder(boolean listCapable) {
518522
.getBeanDefinition());
519523
}
520524

521-
return BeanDefinitionBuilder.genericBeanDefinition(HandlerMethodArgumentResolversHolder.class)
525+
return BeanDefinitionBuilder.genericBeanDefinition(
526+
org.springframework.integration.handler.support.HandlerMethodArgumentResolversHolder.class)
522527
.addConstructorArgValue(resolvers)
523528
.getBeanDefinition();
524529
}

spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 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.
@@ -36,6 +36,7 @@
3636
* @author Josh Long
3737
* @author Artem Bilan
3838
* @author Gary Russell
39+
* @author Oleg Zhurakousky
3940
*/
4041
public abstract class IntegrationContextUtils {
4142

@@ -65,7 +66,8 @@ public abstract class IntegrationContextUtils {
6566

6667
public static final String AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME = "$autoCreateChannelCandidates";
6768

68-
public static final String DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME = "DefaultConfiguringBeanFactoryPostProcessor";
69+
public static final String DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME =
70+
"DefaultConfiguringBeanFactoryPostProcessor";
6971

7072
public static final String MESSAGING_ANNOTATION_POSTPROCESSOR_NAME =
7173
IntegrationConfigUtils.BASE_PACKAGE + ".internalMessagingAnnotationPostProcessor";
@@ -105,6 +107,8 @@ public abstract class IntegrationContextUtils {
105107

106108
public static final String DISPOSABLES_BEAN_NAME = "integrationDisposableAutoCreatedBeans";
107109

110+
public static final String MESSAGE_HANDLER_FACTORY_BEAN_NAME = "integrationMessageHandlerMethodFactory";
111+
108112
/**
109113
* @param beanFactory BeanFactory for lookup, must not be null.
110114
* @return The {@link MetadataStore} bean whose name is "metadataStore".

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2018 the original author or authors.
2+
* Copyright 2017-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.
@@ -28,8 +28,9 @@
2828
* @author Gary Russell
2929
*
3030
* @since 5.0
31-
*
31+
* @deprecated as of 5.1.2. Instead simply configure your own MessageHandlerMethodFactory as a bean.
3232
*/
33+
@Deprecated
3334
public class HandlerMethodArgumentResolversHolder {
3435

3536
private final List<HandlerMethodArgumentResolver> resolvers;

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

Lines changed: 83 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
import org.springframework.messaging.handler.annotation.Headers;
9595
import org.springframework.messaging.handler.annotation.Payload;
9696
import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory;
97+
import org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory;
9798
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
9899
import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;
99100
import org.springframework.messaging.handler.invocation.MethodArgumentResolutionException;
@@ -167,7 +168,7 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
167168
SPEL_COMPILERS.put(SpelCompilerMode.MIXED, EXPRESSION_PARSER_MIXED);
168169
}
169170

170-
private final DefaultMessageHandlerMethodFactory messageHandlerMethodFactory =
171+
private MessageHandlerMethodFactory messageHandlerMethodFactory =
171172
new DefaultMessageHandlerMethodFactory();
172173

173174
private final Object targetObject;
@@ -184,7 +185,7 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
184185

185186
private final List<Map<Class<?>, HandlerMethod>> handlerMethodsList;
186187

187-
private final HandlerMethod handlerMethod;
188+
private HandlerMethod handlerMethod;
188189

189190
private final TypeDescriptor expectedType;
190191

@@ -257,16 +258,7 @@ private MessagingMethodInvokerHelper(Object targetObject, Class<? extends Annota
257258

258259
Assert.notNull(targetObject, "targetObject must not be null");
259260
this.targetObject = targetObject;
260-
try {
261-
InvocableHandlerMethod invocableHandlerMethod =
262-
this.messageHandlerMethodFactory.createInvocableHandlerMethod(targetObject, method);
263-
this.handlerMethod = new HandlerMethod(invocableHandlerMethod, canProcessMessageList);
264-
this.defaultHandlerMethod = null;
265-
checkSpelInvokerRequired(getTargetClass(targetObject), method, this.handlerMethod);
266-
}
267-
catch (IneligibleMethodException e) {
268-
throw new IllegalArgumentException(e);
269-
}
261+
createHandlerMethod();
270262
this.handlerMethods = null;
271263
this.handlerMessageMethods = null;
272264
this.handlerMethodsList = null;
@@ -295,7 +287,8 @@ public void setUseSpelInvoker(boolean useSpelInvoker) {
295287
@Override
296288
public void setBeanFactory(@NonNull BeanFactory beanFactory) {
297289
super.setBeanFactory(beanFactory);
298-
this.messageHandlerMethodFactory.setBeanFactory(beanFactory);
290+
((DefaultMessageHandlerMethodFactory) this.messageHandlerMethodFactory).setBeanFactory(beanFactory);
291+
299292
if (beanFactory instanceof ConfigurableListableBeanFactory) {
300293
BeanExpressionResolver beanExpressionResolver = ((ConfigurableListableBeanFactory) beanFactory)
301294
.getBeanExpressionResolver();
@@ -310,7 +303,8 @@ public void setBeanFactory(@NonNull BeanFactory beanFactory) {
310303
public void setConversionService(ConversionService conversionService) {
311304
super.setConversionService(conversionService);
312305
if (conversionService != null) {
313-
this.messageHandlerMethodFactory.setConversionService(conversionService);
306+
((DefaultMessageHandlerMethodFactory) this.messageHandlerMethodFactory)
307+
.setConversionService(conversionService);
314308
}
315309
}
316310

@@ -403,6 +397,25 @@ private MessagingMethodInvokerHelper(Object targetObject, Class<? extends Annota
403397
this.jsonObjectMapper = mapper;
404398
}
405399

400+
private boolean isProvidedMessageHandlerFactoryBean() {
401+
BeanFactory beanFactory = getBeanFactory();
402+
return beanFactory != null
403+
&& beanFactory.containsBean(IntegrationContextUtils.MESSAGE_HANDLER_FACTORY_BEAN_NAME);
404+
}
405+
406+
private void createHandlerMethod() {
407+
try {
408+
InvocableHandlerMethod invocableHandlerMethod =
409+
this.messageHandlerMethodFactory.createInvocableHandlerMethod(this.targetObject, this.method);
410+
this.handlerMethod = new HandlerMethod(invocableHandlerMethod, this.canProcessMessageList);
411+
this.defaultHandlerMethod = null;
412+
checkSpelInvokerRequired(getTargetClass(this.targetObject), this.method, this.handlerMethod);
413+
}
414+
catch (IneligibleMethodException e) {
415+
throw new IllegalArgumentException(e);
416+
}
417+
}
418+
406419
private void setDisplayString(Object targetObject, Object targetMethod) {
407420
StringBuilder sb = new StringBuilder(targetObject.getClass().getName());
408421
if (targetMethod instanceof Method) {
@@ -503,37 +516,51 @@ private void initializeHandler(HandlerMethod candidate) {
503516
candidate.initialized = true;
504517
}
505518

519+
@SuppressWarnings("deprecation")
506520
private synchronized void initialize() throws Exception {
507521
if (!this.initialized) {
508522
BeanFactory beanFactory = getBeanFactory();
509-
if (beanFactory != null &&
510-
beanFactory.containsBean(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME)) {
511-
512-
try {
513-
MessageConverter messageConverter =
514-
beanFactory.getBean(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME,
515-
MessageConverter.class);
516-
517-
this.messageHandlerMethodFactory.setMessageConverter(messageConverter);
518-
519-
HandlerMethodArgumentResolversHolder handlerMethodArgumentResolversHolder =
520-
beanFactory.getBean(this.canProcessMessageList
521-
? IntegrationContextUtils.LIST_ARGUMENT_RESOLVERS_BEAN_NAME
522-
: IntegrationContextUtils.ARGUMENT_RESOLVERS_BEAN_NAME,
523-
HandlerMethodArgumentResolversHolder.class);
524-
525-
this.messageHandlerMethodFactory.setCustomArgumentResolvers(
526-
handlerMethodArgumentResolversHolder.getResolvers());
523+
if (isProvidedMessageHandlerFactoryBean()) {
524+
logger.info("Overriding default instance of MessageHandlerMethodFactory with provided one.");
525+
this.messageHandlerMethodFactory =
526+
beanFactory.getBean(IntegrationContextUtils.MESSAGE_HANDLER_FACTORY_BEAN_NAME,
527+
MessageHandlerMethodFactory.class);
528+
createHandlerMethod();
529+
}
530+
else {
531+
if (beanFactory != null &&
532+
beanFactory.containsBean(
533+
IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME)) {
534+
535+
try {
536+
MessageConverter messageConverter =
537+
beanFactory.getBean(
538+
IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME,
539+
MessageConverter.class);
540+
541+
((DefaultMessageHandlerMethodFactory) this.messageHandlerMethodFactory)
542+
.setMessageConverter(messageConverter);
543+
544+
HandlerMethodArgumentResolversHolder handlerMethodArgumentResolversHolder =
545+
beanFactory.getBean(this.canProcessMessageList
546+
? IntegrationContextUtils.LIST_ARGUMENT_RESOLVERS_BEAN_NAME
547+
: IntegrationContextUtils.ARGUMENT_RESOLVERS_BEAN_NAME,
548+
HandlerMethodArgumentResolversHolder.class);
549+
550+
((DefaultMessageHandlerMethodFactory) this.messageHandlerMethodFactory)
551+
.setCustomArgumentResolvers(
552+
handlerMethodArgumentResolversHolder.getResolvers());
553+
}
554+
catch (NoSuchBeanDefinitionException e) {
555+
configureLocalMessageHandlerFactory();
556+
}
527557
}
528-
catch (NoSuchBeanDefinitionException e) {
558+
else {
529559
configureLocalMessageHandlerFactory();
530560
}
531-
}
532-
else {
533-
configureLocalMessageHandlerFactory();
561+
((DefaultMessageHandlerMethodFactory) this.messageHandlerMethodFactory).afterPropertiesSet();
534562
}
535563

536-
this.messageHandlerMethodFactory.afterPropertiesSet();
537564
prepareEvaluationContext();
538565
this.initialized = true;
539566
}
@@ -545,26 +572,27 @@ private synchronized void initialize() throws Exception {
545572
*/
546573
private void configureLocalMessageHandlerFactory() {
547574
MessageConverter messageConverter = null;
548-
if (getBeanFactory() != null &&
549-
getBeanFactory()
550-
.containsBean(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME)) {
551-
messageConverter = getBeanFactory()
552-
.getBean(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME,
553-
MessageConverter.class);
554-
this.messageHandlerMethodFactory.setMessageConverter(messageConverter);
575+
BeanFactory beanFactory = getBeanFactory();
576+
if (beanFactory != null &&
577+
beanFactory.containsBean(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME)) {
578+
messageConverter = beanFactory
579+
.getBean(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME,
580+
MessageConverter.class);
581+
((DefaultMessageHandlerMethodFactory) this.messageHandlerMethodFactory)
582+
.setMessageConverter(messageConverter);
555583
}
556584
else {
557585
messageConverter = new ConfigurableCompositeMessageConverter();
558586
}
559587
NullAwarePayloadArgumentResolver nullResolver = new NullAwarePayloadArgumentResolver(messageConverter);
560588
PayloadExpressionArgumentResolver payloadExpressionArgumentResolver = new PayloadExpressionArgumentResolver();
561-
payloadExpressionArgumentResolver.setBeanFactory(getBeanFactory());
589+
payloadExpressionArgumentResolver.setBeanFactory(beanFactory);
562590

563591
PayloadsArgumentResolver payloadsArgumentResolver = new PayloadsArgumentResolver();
564-
payloadsArgumentResolver.setBeanFactory(getBeanFactory());
592+
payloadsArgumentResolver.setBeanFactory(beanFactory);
565593

566594
MapArgumentResolver mapArgumentResolver = new MapArgumentResolver();
567-
mapArgumentResolver.setBeanFactory(getBeanFactory());
595+
mapArgumentResolver.setBeanFactory(beanFactory);
568596

569597
List<HandlerMethodArgumentResolver> customArgumentResolvers = new LinkedList<>();
570598
customArgumentResolvers.add(payloadExpressionArgumentResolver);
@@ -573,13 +601,14 @@ private void configureLocalMessageHandlerFactory() {
573601

574602
if (this.canProcessMessageList) {
575603
CollectionArgumentResolver collectionArgumentResolver = new CollectionArgumentResolver(true);
576-
collectionArgumentResolver.setBeanFactory(getBeanFactory());
604+
collectionArgumentResolver.setBeanFactory(beanFactory);
577605
customArgumentResolvers.add(collectionArgumentResolver);
578606
}
579607

580608
customArgumentResolvers.add(mapArgumentResolver);
581609

582-
this.messageHandlerMethodFactory.setCustomArgumentResolvers(customArgumentResolvers);
610+
((DefaultMessageHandlerMethodFactory) this.messageHandlerMethodFactory)
611+
.setCustomArgumentResolvers(customArgumentResolvers);
583612
}
584613

585614
@SuppressWarnings("unchecked")
@@ -598,7 +627,8 @@ else if (e instanceof IllegalStateException) {
598627
if (!(e.getCause() instanceof IllegalArgumentException) ||
599628
!e.getStackTrace()[0].getClassName().equals(InvocableHandlerMethod.class.getName()) ||
600629
(!"argument type mismatch".equals(e.getCause().getMessage()) &&
601-
// JVM generates GeneratedMethodAccessor### after several calls with less error checking
630+
// JVM generates GeneratedMethodAccessor### after several calls with less error
631+
// checking
602632
!e.getCause().getMessage().startsWith("java.lang.ClassCastException@"))) {
603633
throw e;
604634
}
@@ -1133,7 +1163,9 @@ private String generateExpression(Method method) {
11331163
}
11341164
if (annotationType.equals(Payloads.class)) {
11351165
Assert.isTrue(this.canProcessMessageList,
1136-
"The @Payloads annotation can only be applied if method handler canProcessMessageList.");
1166+
"The @Payloads annotation can only be applied if method handler " +
1167+
"canProcessMessageList" +
1168+
".");
11371169
Assert.isTrue(Collection.class.isAssignableFrom(parameterType),
11381170
"The @Payloads annotation can only be applied to a Collection-typed parameter.");
11391171
sb.append("messages.![payload");

0 commit comments

Comments
 (0)