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
This commit is contained in:
committed by
Artem Bilan
parent
1d5e66b0ee
commit
0d1312874c
@@ -57,7 +57,6 @@ import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.context.IntegrationProperties;
|
||||
import org.springframework.integration.handler.LoggingHandler;
|
||||
import org.springframework.integration.handler.support.CollectionArgumentResolver;
|
||||
import org.springframework.integration.handler.support.HandlerMethodArgumentResolversHolder;
|
||||
import org.springframework.integration.handler.support.MapArgumentResolver;
|
||||
import org.springframework.integration.handler.support.PayloadExpressionArgumentResolver;
|
||||
import org.springframework.integration.handler.support.PayloadsArgumentResolver;
|
||||
@@ -187,7 +186,8 @@ class DefaultConfiguringBeanFactoryPostProcessor
|
||||
if (!this.beanFactory.containsBean(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME)) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("No bean named '" + IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME +
|
||||
"' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created.");
|
||||
"' has been explicitly defined. " +
|
||||
"Therefore, a default PublishSubscribeChannel will be created.");
|
||||
}
|
||||
this.registry.registerBeanDefinition(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME,
|
||||
new RootBeanDefinition(PublishSubscribeChannel.class));
|
||||
@@ -273,7 +273,8 @@ class DefaultConfiguringBeanFactoryPostProcessor
|
||||
if (!this.beanFactory.containsBean(IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME)) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("No bean named '" + IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME +
|
||||
"' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created.");
|
||||
"' has been explicitly defined. " +
|
||||
"Therefore, a default ThreadPoolTaskScheduler will be created.");
|
||||
}
|
||||
BeanDefinition scheduler = BeanDefinitionBuilder.genericBeanDefinition(ThreadPoolTaskScheduler.class)
|
||||
.addPropertyValue("poolSize", IntegrationProperties
|
||||
@@ -479,7 +480,8 @@ class DefaultConfiguringBeanFactoryPostProcessor
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the default {@link HandlerMethodArgumentResolversHolder} for handler
|
||||
* Register the default
|
||||
* {@link org.springframework.integration.handler.support.HandlerMethodArgumentResolversHolder} for handler
|
||||
* method invocation.
|
||||
*/
|
||||
private void registerArgumentResolvers() {
|
||||
@@ -490,7 +492,8 @@ class DefaultConfiguringBeanFactoryPostProcessor
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the default {@link HandlerMethodArgumentResolversHolder} for handler
|
||||
* Register the default
|
||||
* {@link org.springframework.integration.handler.support.HandlerMethodArgumentResolversHolder} for handler
|
||||
* method invocation for lists.
|
||||
*/
|
||||
private void registerListCapableArgumentResolvers() {
|
||||
@@ -500,6 +503,7 @@ class DefaultConfiguringBeanFactoryPostProcessor
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private BeanDefinition internalArgumentResolversBuilder(boolean listCapable) {
|
||||
ManagedList<BeanDefinition> resolvers = new ManagedList<>();
|
||||
resolvers.add(new RootBeanDefinition(PayloadExpressionArgumentResolver.class));
|
||||
@@ -518,7 +522,8 @@ class DefaultConfiguringBeanFactoryPostProcessor
|
||||
.getBeanDefinition());
|
||||
}
|
||||
|
||||
return BeanDefinitionBuilder.genericBeanDefinition(HandlerMethodArgumentResolversHolder.class)
|
||||
return BeanDefinitionBuilder.genericBeanDefinition(
|
||||
org.springframework.integration.handler.support.HandlerMethodArgumentResolversHolder.class)
|
||||
.addConstructorArgValue(resolvers)
|
||||
.getBeanDefinition();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -36,6 +36,7 @@ import org.springframework.util.Assert;
|
||||
* @author Josh Long
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
public abstract class IntegrationContextUtils {
|
||||
|
||||
@@ -65,7 +66,8 @@ public abstract class IntegrationContextUtils {
|
||||
|
||||
public static final String AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME = "$autoCreateChannelCandidates";
|
||||
|
||||
public static final String DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME = "DefaultConfiguringBeanFactoryPostProcessor";
|
||||
public static final String DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME =
|
||||
"DefaultConfiguringBeanFactoryPostProcessor";
|
||||
|
||||
public static final String MESSAGING_ANNOTATION_POSTPROCESSOR_NAME =
|
||||
IntegrationConfigUtils.BASE_PACKAGE + ".internalMessagingAnnotationPostProcessor";
|
||||
@@ -105,6 +107,8 @@ public abstract class IntegrationContextUtils {
|
||||
|
||||
public static final String DISPOSABLES_BEAN_NAME = "integrationDisposableAutoCreatedBeans";
|
||||
|
||||
public static final String MESSAGE_HANDLER_FACTORY_BEAN_NAME = "integrationMessageHandlerMethodFactory";
|
||||
|
||||
/**
|
||||
* @param beanFactory BeanFactory for lookup, must not be null.
|
||||
* @return The {@link MetadataStore} bean whose name is "metadataStore".
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2018 the original author or authors.
|
||||
* Copyright 2017-2019 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.
|
||||
@@ -28,8 +28,9 @@ import org.springframework.messaging.handler.invocation.HandlerMethodArgumentRes
|
||||
* @author Gary Russell
|
||||
*
|
||||
* @since 5.0
|
||||
*
|
||||
* @deprecated as of 5.1.2. Instead simply configure your own MessageHandlerMethodFactory as a bean.
|
||||
*/
|
||||
@Deprecated
|
||||
public class HandlerMethodArgumentResolversHolder {
|
||||
|
||||
private final List<HandlerMethodArgumentResolver> resolvers;
|
||||
|
||||
@@ -94,6 +94,7 @@ import org.springframework.messaging.handler.annotation.Header;
|
||||
import org.springframework.messaging.handler.annotation.Headers;
|
||||
import org.springframework.messaging.handler.annotation.Payload;
|
||||
import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory;
|
||||
import org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory;
|
||||
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
|
||||
import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;
|
||||
import org.springframework.messaging.handler.invocation.MethodArgumentResolutionException;
|
||||
@@ -167,7 +168,7 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
SPEL_COMPILERS.put(SpelCompilerMode.MIXED, EXPRESSION_PARSER_MIXED);
|
||||
}
|
||||
|
||||
private final DefaultMessageHandlerMethodFactory messageHandlerMethodFactory =
|
||||
private MessageHandlerMethodFactory messageHandlerMethodFactory =
|
||||
new DefaultMessageHandlerMethodFactory();
|
||||
|
||||
private final Object targetObject;
|
||||
@@ -184,7 +185,7 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
|
||||
private final List<Map<Class<?>, HandlerMethod>> handlerMethodsList;
|
||||
|
||||
private final HandlerMethod handlerMethod;
|
||||
private HandlerMethod handlerMethod;
|
||||
|
||||
private final TypeDescriptor expectedType;
|
||||
|
||||
@@ -257,16 +258,7 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
|
||||
Assert.notNull(targetObject, "targetObject must not be null");
|
||||
this.targetObject = targetObject;
|
||||
try {
|
||||
InvocableHandlerMethod invocableHandlerMethod =
|
||||
this.messageHandlerMethodFactory.createInvocableHandlerMethod(targetObject, method);
|
||||
this.handlerMethod = new HandlerMethod(invocableHandlerMethod, canProcessMessageList);
|
||||
this.defaultHandlerMethod = null;
|
||||
checkSpelInvokerRequired(getTargetClass(targetObject), method, this.handlerMethod);
|
||||
}
|
||||
catch (IneligibleMethodException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
createHandlerMethod();
|
||||
this.handlerMethods = null;
|
||||
this.handlerMessageMethods = null;
|
||||
this.handlerMethodsList = null;
|
||||
@@ -295,7 +287,8 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
@Override
|
||||
public void setBeanFactory(@NonNull BeanFactory beanFactory) {
|
||||
super.setBeanFactory(beanFactory);
|
||||
this.messageHandlerMethodFactory.setBeanFactory(beanFactory);
|
||||
((DefaultMessageHandlerMethodFactory) this.messageHandlerMethodFactory).setBeanFactory(beanFactory);
|
||||
|
||||
if (beanFactory instanceof ConfigurableListableBeanFactory) {
|
||||
BeanExpressionResolver beanExpressionResolver = ((ConfigurableListableBeanFactory) beanFactory)
|
||||
.getBeanExpressionResolver();
|
||||
@@ -310,7 +303,8 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
super.setConversionService(conversionService);
|
||||
if (conversionService != null) {
|
||||
this.messageHandlerMethodFactory.setConversionService(conversionService);
|
||||
((DefaultMessageHandlerMethodFactory) this.messageHandlerMethodFactory)
|
||||
.setConversionService(conversionService);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,6 +397,25 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
this.jsonObjectMapper = mapper;
|
||||
}
|
||||
|
||||
private boolean isProvidedMessageHandlerFactoryBean() {
|
||||
BeanFactory beanFactory = getBeanFactory();
|
||||
return beanFactory != null
|
||||
&& beanFactory.containsBean(IntegrationContextUtils.MESSAGE_HANDLER_FACTORY_BEAN_NAME);
|
||||
}
|
||||
|
||||
private void createHandlerMethod() {
|
||||
try {
|
||||
InvocableHandlerMethod invocableHandlerMethod =
|
||||
this.messageHandlerMethodFactory.createInvocableHandlerMethod(this.targetObject, this.method);
|
||||
this.handlerMethod = new HandlerMethod(invocableHandlerMethod, this.canProcessMessageList);
|
||||
this.defaultHandlerMethod = null;
|
||||
checkSpelInvokerRequired(getTargetClass(this.targetObject), this.method, this.handlerMethod);
|
||||
}
|
||||
catch (IneligibleMethodException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setDisplayString(Object targetObject, Object targetMethod) {
|
||||
StringBuilder sb = new StringBuilder(targetObject.getClass().getName());
|
||||
if (targetMethod instanceof Method) {
|
||||
@@ -503,37 +516,51 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
candidate.initialized = true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private synchronized void initialize() throws Exception {
|
||||
if (!this.initialized) {
|
||||
BeanFactory beanFactory = getBeanFactory();
|
||||
if (beanFactory != null &&
|
||||
beanFactory.containsBean(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME)) {
|
||||
|
||||
try {
|
||||
MessageConverter messageConverter =
|
||||
beanFactory.getBean(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME,
|
||||
MessageConverter.class);
|
||||
|
||||
this.messageHandlerMethodFactory.setMessageConverter(messageConverter);
|
||||
|
||||
HandlerMethodArgumentResolversHolder handlerMethodArgumentResolversHolder =
|
||||
beanFactory.getBean(this.canProcessMessageList
|
||||
? IntegrationContextUtils.LIST_ARGUMENT_RESOLVERS_BEAN_NAME
|
||||
: IntegrationContextUtils.ARGUMENT_RESOLVERS_BEAN_NAME,
|
||||
HandlerMethodArgumentResolversHolder.class);
|
||||
|
||||
this.messageHandlerMethodFactory.setCustomArgumentResolvers(
|
||||
handlerMethodArgumentResolversHolder.getResolvers());
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException e) {
|
||||
configureLocalMessageHandlerFactory();
|
||||
}
|
||||
if (isProvidedMessageHandlerFactoryBean()) {
|
||||
logger.info("Overriding default instance of MessageHandlerMethodFactory with provided one.");
|
||||
this.messageHandlerMethodFactory =
|
||||
beanFactory.getBean(IntegrationContextUtils.MESSAGE_HANDLER_FACTORY_BEAN_NAME,
|
||||
MessageHandlerMethodFactory.class);
|
||||
createHandlerMethod();
|
||||
}
|
||||
else {
|
||||
configureLocalMessageHandlerFactory();
|
||||
if (beanFactory != null &&
|
||||
beanFactory.containsBean(
|
||||
IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME)) {
|
||||
|
||||
try {
|
||||
MessageConverter messageConverter =
|
||||
beanFactory.getBean(
|
||||
IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME,
|
||||
MessageConverter.class);
|
||||
|
||||
((DefaultMessageHandlerMethodFactory) this.messageHandlerMethodFactory)
|
||||
.setMessageConverter(messageConverter);
|
||||
|
||||
HandlerMethodArgumentResolversHolder handlerMethodArgumentResolversHolder =
|
||||
beanFactory.getBean(this.canProcessMessageList
|
||||
? IntegrationContextUtils.LIST_ARGUMENT_RESOLVERS_BEAN_NAME
|
||||
: IntegrationContextUtils.ARGUMENT_RESOLVERS_BEAN_NAME,
|
||||
HandlerMethodArgumentResolversHolder.class);
|
||||
|
||||
((DefaultMessageHandlerMethodFactory) this.messageHandlerMethodFactory)
|
||||
.setCustomArgumentResolvers(
|
||||
handlerMethodArgumentResolversHolder.getResolvers());
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException e) {
|
||||
configureLocalMessageHandlerFactory();
|
||||
}
|
||||
}
|
||||
else {
|
||||
configureLocalMessageHandlerFactory();
|
||||
}
|
||||
((DefaultMessageHandlerMethodFactory) this.messageHandlerMethodFactory).afterPropertiesSet();
|
||||
}
|
||||
|
||||
this.messageHandlerMethodFactory.afterPropertiesSet();
|
||||
prepareEvaluationContext();
|
||||
this.initialized = true;
|
||||
}
|
||||
@@ -545,26 +572,27 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
*/
|
||||
private void configureLocalMessageHandlerFactory() {
|
||||
MessageConverter messageConverter = null;
|
||||
if (getBeanFactory() != null &&
|
||||
getBeanFactory()
|
||||
.containsBean(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME)) {
|
||||
messageConverter = getBeanFactory()
|
||||
.getBean(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME,
|
||||
MessageConverter.class);
|
||||
this.messageHandlerMethodFactory.setMessageConverter(messageConverter);
|
||||
BeanFactory beanFactory = getBeanFactory();
|
||||
if (beanFactory != null &&
|
||||
beanFactory.containsBean(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME)) {
|
||||
messageConverter = beanFactory
|
||||
.getBean(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME,
|
||||
MessageConverter.class);
|
||||
((DefaultMessageHandlerMethodFactory) this.messageHandlerMethodFactory)
|
||||
.setMessageConverter(messageConverter);
|
||||
}
|
||||
else {
|
||||
messageConverter = new ConfigurableCompositeMessageConverter();
|
||||
}
|
||||
NullAwarePayloadArgumentResolver nullResolver = new NullAwarePayloadArgumentResolver(messageConverter);
|
||||
PayloadExpressionArgumentResolver payloadExpressionArgumentResolver = new PayloadExpressionArgumentResolver();
|
||||
payloadExpressionArgumentResolver.setBeanFactory(getBeanFactory());
|
||||
payloadExpressionArgumentResolver.setBeanFactory(beanFactory);
|
||||
|
||||
PayloadsArgumentResolver payloadsArgumentResolver = new PayloadsArgumentResolver();
|
||||
payloadsArgumentResolver.setBeanFactory(getBeanFactory());
|
||||
payloadsArgumentResolver.setBeanFactory(beanFactory);
|
||||
|
||||
MapArgumentResolver mapArgumentResolver = new MapArgumentResolver();
|
||||
mapArgumentResolver.setBeanFactory(getBeanFactory());
|
||||
mapArgumentResolver.setBeanFactory(beanFactory);
|
||||
|
||||
List<HandlerMethodArgumentResolver> customArgumentResolvers = new LinkedList<>();
|
||||
customArgumentResolvers.add(payloadExpressionArgumentResolver);
|
||||
@@ -573,13 +601,14 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
|
||||
if (this.canProcessMessageList) {
|
||||
CollectionArgumentResolver collectionArgumentResolver = new CollectionArgumentResolver(true);
|
||||
collectionArgumentResolver.setBeanFactory(getBeanFactory());
|
||||
collectionArgumentResolver.setBeanFactory(beanFactory);
|
||||
customArgumentResolvers.add(collectionArgumentResolver);
|
||||
}
|
||||
|
||||
customArgumentResolvers.add(mapArgumentResolver);
|
||||
|
||||
this.messageHandlerMethodFactory.setCustomArgumentResolvers(customArgumentResolvers);
|
||||
((DefaultMessageHandlerMethodFactory) this.messageHandlerMethodFactory)
|
||||
.setCustomArgumentResolvers(customArgumentResolvers);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -598,7 +627,8 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
if (!(e.getCause() instanceof IllegalArgumentException) ||
|
||||
!e.getStackTrace()[0].getClassName().equals(InvocableHandlerMethod.class.getName()) ||
|
||||
(!"argument type mismatch".equals(e.getCause().getMessage()) &&
|
||||
// JVM generates GeneratedMethodAccessor### after several calls with less error checking
|
||||
// JVM generates GeneratedMethodAccessor### after several calls with less error
|
||||
// checking
|
||||
!e.getCause().getMessage().startsWith("java.lang.ClassCastException@"))) {
|
||||
throw e;
|
||||
}
|
||||
@@ -1133,7 +1163,9 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
}
|
||||
if (annotationType.equals(Payloads.class)) {
|
||||
Assert.isTrue(this.canProcessMessageList,
|
||||
"The @Payloads annotation can only be applied if method handler canProcessMessageList.");
|
||||
"The @Payloads annotation can only be applied if method handler " +
|
||||
"canProcessMessageList" +
|
||||
".");
|
||||
Assert.isTrue(Collection.class.isAssignableFrom(parameterType),
|
||||
"The @Payloads annotation can only be applied to a Collection-typed parameter.");
|
||||
sb.append("messages.![payload");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -61,7 +61,9 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.SpelCompilerMode;
|
||||
import org.springframework.expression.spel.SpelEvaluationException;
|
||||
@@ -70,19 +72,26 @@ import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.integration.annotation.ServiceActivator;
|
||||
import org.springframework.integration.annotation.UseSpelInvoker;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.config.EnableIntegration;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.gateway.GatewayProxyFactoryBean;
|
||||
import org.springframework.integration.gateway.RequestReplyExchanger;
|
||||
import org.springframework.integration.handler.support.MessagingMethodInvokerHelper;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
import org.springframework.messaging.MessageHandlingException;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.messaging.PollableChannel;
|
||||
import org.springframework.messaging.handler.annotation.Header;
|
||||
import org.springframework.messaging.handler.annotation.Payload;
|
||||
import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory;
|
||||
import org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory;
|
||||
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
@@ -107,6 +116,67 @@ public class MethodInvokingMessageProcessorTests {
|
||||
@Rule
|
||||
public ExpectedException expected = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void testMessageHandlerMethodFactoryOverride() {
|
||||
try (AnnotationConfigApplicationContext context =
|
||||
new AnnotationConfigApplicationContext(MyConfiguration.class)) {
|
||||
MessageChannel channel = context.getBean("foo", MessageChannel.class);
|
||||
channel.send(MessageBuilder.withPayload("Bob Smith").build());
|
||||
PollableChannel out = context.getBean("out", PollableChannel.class);
|
||||
assertEquals("Person: Bob Smith", out.receive().getPayload());
|
||||
}
|
||||
}
|
||||
|
||||
@EnableIntegration
|
||||
public static class MyConfiguration {
|
||||
|
||||
@ServiceActivator(inputChannel = "foo", outputChannel = "out")
|
||||
public String foo(Person person) {
|
||||
return person.toString();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PollableChannel out() {
|
||||
return new QueueChannel();
|
||||
}
|
||||
|
||||
@Bean(IntegrationContextUtils.MESSAGE_HANDLER_FACTORY_BEAN_NAME)
|
||||
public MessageHandlerMethodFactory messageHandlerMethodFactory() {
|
||||
DefaultMessageHandlerMethodFactory f = new DefaultMessageHandlerMethodFactory();
|
||||
HandlerMethodArgumentResolver resolver = new HandlerMethodArgumentResolver() {
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, Message<?> message) throws Exception {
|
||||
String[] names = ((String) message.getPayload()).split(" ");
|
||||
return new Person(names[0], names[1]);
|
||||
}
|
||||
};
|
||||
f.setArgumentResolvers(Collections.singletonList(resolver));
|
||||
f.afterPropertiesSet();
|
||||
return f;
|
||||
}
|
||||
|
||||
public static class Person {
|
||||
|
||||
private final String name;
|
||||
|
||||
public Person(String fname, String lname) {
|
||||
this.name = fname + " " + lname;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Person: " + name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandlerInheritanceMethodImplInSuper() {
|
||||
class A {
|
||||
@@ -115,6 +185,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
public Message<String> myMethod(final Message<String> msg) {
|
||||
return MessageBuilder.fromMessage(msg).setHeader("A", "A").build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
@@ -127,7 +198,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
}
|
||||
|
||||
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(new B(), "myMethod");
|
||||
Message<?> message = (Message<?>) processor.processMessage(new GenericMessage<String>(""));
|
||||
Message<?> message = (Message<?>) processor.processMessage(new GenericMessage<>(""));
|
||||
assertEquals("A", message.getHeaders().get("A"));
|
||||
}
|
||||
|
||||
@@ -139,6 +210,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
public Message<String> myMethod(Message<String> msg) {
|
||||
return MessageBuilder.fromMessage(msg).setHeader("A", "A").build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
@@ -147,6 +219,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
public Message<String> myMethod(Message<String> msg) {
|
||||
return MessageBuilder.fromMessage(msg).setHeader("B", "B").build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@@ -155,7 +228,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
}
|
||||
|
||||
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(new B(), "myMethod");
|
||||
Message<?> message = (Message<?>) processor.processMessage(new GenericMessage<String>(""));
|
||||
Message<?> message = (Message<?>) processor.processMessage(new GenericMessage<>(""));
|
||||
assertEquals("B", message.getHeaders().get("B"));
|
||||
}
|
||||
|
||||
@@ -166,6 +239,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
public Message<String> myMethod(Message<String> msg) {
|
||||
return MessageBuilder.fromMessage(msg).setHeader("A", "A").build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
@@ -174,6 +248,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
public Message<String> myMethod(Message<String> msg) {
|
||||
return MessageBuilder.fromMessage(msg).setHeader("B", "B").build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class C extends B {
|
||||
@@ -182,10 +257,11 @@ public class MethodInvokingMessageProcessorTests {
|
||||
public Message<String> myMethod(Message<String> msg) {
|
||||
return MessageBuilder.fromMessage(msg).setHeader("C", "C").build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(new C(), "myMethod");
|
||||
Message<?> message = (Message<?>) processor.processMessage(new GenericMessage<String>(""));
|
||||
Message<?> message = (Message<?>) processor.processMessage(new GenericMessage<>(""));
|
||||
assertEquals("C", message.getHeaders().get("C"));
|
||||
}
|
||||
|
||||
@@ -196,6 +272,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
public Message<String> myMethod(Message<String> msg) {
|
||||
return MessageBuilder.fromMessage(msg).setHeader("A", "A").build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
@@ -208,10 +285,11 @@ public class MethodInvokingMessageProcessorTests {
|
||||
public Message<String> myMethod(Message<String> msg) {
|
||||
return MessageBuilder.fromMessage(msg).setHeader("C", "C").build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(new C(), "myMethod");
|
||||
Message<?> message = (Message<?>) processor.processMessage(new GenericMessage<String>(""));
|
||||
Message<?> message = (Message<?>) processor.processMessage(new GenericMessage<>(""));
|
||||
assertEquals("C", message.getHeaders().get("C"));
|
||||
}
|
||||
|
||||
@@ -219,7 +297,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
public void payloadAsMethodParameterAndObjectAsReturnValue() {
|
||||
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(new TestBean(),
|
||||
"acceptPayloadAndReturnObject");
|
||||
Object result = processor.processMessage(new GenericMessage<String>("testing"));
|
||||
Object result = processor.processMessage(new GenericMessage<>("testing"));
|
||||
assertEquals("testing-1", result);
|
||||
}
|
||||
|
||||
@@ -227,7 +305,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
public void testPayloadCoercedToString() {
|
||||
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(new TestBean(),
|
||||
"acceptPayloadAndReturnObject");
|
||||
Object result = processor.processMessage(new GenericMessage<Integer>(123456789));
|
||||
Object result = processor.processMessage(new GenericMessage<>(123456789));
|
||||
assertEquals("123456789-1", result);
|
||||
}
|
||||
|
||||
@@ -235,7 +313,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
public void payloadAsMethodParameterAndMessageAsReturnValue() {
|
||||
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(new TestBean(),
|
||||
"acceptPayloadAndReturnMessage");
|
||||
Message<?> result = (Message<?>) processor.processMessage(new GenericMessage<String>("testing"));
|
||||
Message<?> result = (Message<?>) processor.processMessage(new GenericMessage<>("testing"));
|
||||
assertEquals("testing-2", result.getPayload());
|
||||
}
|
||||
|
||||
@@ -243,7 +321,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
public void messageAsMethodParameterAndObjectAsReturnValue() {
|
||||
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(new TestBean(),
|
||||
"acceptMessageAndReturnObject");
|
||||
Object result = processor.processMessage(new GenericMessage<String>("testing"));
|
||||
Object result = processor.processMessage(new GenericMessage<>("testing"));
|
||||
assertEquals("testing-3", result);
|
||||
}
|
||||
|
||||
@@ -251,7 +329,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
public void messageAsMethodParameterAndMessageAsReturnValue() {
|
||||
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(new TestBean(),
|
||||
"acceptMessageAndReturnMessage");
|
||||
Message<?> result = (Message<?>) processor.processMessage(new GenericMessage<String>("testing"));
|
||||
Message<?> result = (Message<?>) processor.processMessage(new GenericMessage<>("testing"));
|
||||
assertEquals("testing-4", result.getPayload());
|
||||
}
|
||||
|
||||
@@ -259,7 +337,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
public void messageSubclassAsMethodParameterAndMessageAsReturnValue() {
|
||||
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(new TestBean(),
|
||||
"acceptMessageSubclassAndReturnMessage");
|
||||
Message<?> result = (Message<?>) processor.processMessage(new GenericMessage<String>("testing"));
|
||||
Message<?> result = (Message<?>) processor.processMessage(new GenericMessage<>("testing"));
|
||||
assertEquals("testing-5", result.getPayload());
|
||||
}
|
||||
|
||||
@@ -267,7 +345,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
public void messageSubclassAsMethodParameterAndMessageSubclassAsReturnValue() {
|
||||
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(new TestBean(),
|
||||
"acceptMessageSubclassAndReturnMessageSubclass");
|
||||
Message<?> result = (Message<?>) processor.processMessage(new GenericMessage<String>("testing"));
|
||||
Message<?> result = (Message<?>) processor.processMessage(new GenericMessage<>("testing"));
|
||||
assertEquals("testing-6", result.getPayload());
|
||||
}
|
||||
|
||||
@@ -293,7 +371,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
AnnotatedTestService service = new AnnotatedTestService();
|
||||
Method method = service.getClass().getMethod("messageOnly", Message.class);
|
||||
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(service, method);
|
||||
Object result = processor.processMessage(new GenericMessage<String>("foo"));
|
||||
Object result = processor.processMessage(new GenericMessage<>("foo"));
|
||||
assertEquals("foo", result);
|
||||
}
|
||||
|
||||
@@ -562,6 +640,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
public String getBar() {
|
||||
return "foo";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -654,6 +733,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
public Object m3() {
|
||||
return "FOO";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Foo targetObject = new Foo();
|
||||
@@ -715,7 +795,8 @@ public class MethodInvokingMessageProcessorTests {
|
||||
|
||||
}
|
||||
|
||||
MessagingMethodInvokerHelper helper = new MessagingMethodInvokerHelper(new Foo(), ServiceActivator.class, false);
|
||||
MessagingMethodInvokerHelper helper = new MessagingMethodInvokerHelper(new Foo(), ServiceActivator.class,
|
||||
false);
|
||||
|
||||
assertEquals("FOO", helper.process(new GenericMessage<>("foo")));
|
||||
assertEquals("BAR", helper.process(new GenericMessage<>("bar")));
|
||||
@@ -773,6 +854,7 @@ public class MethodInvokingMessageProcessorTests {
|
||||
public void myMethod(Object payload) {
|
||||
throw new IllegalStateException(new IllegalArgumentException("argument type mismatch"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(new A(), "myMethod");
|
||||
|
||||
Reference in New Issue
Block a user