Post merge polishing
JIRA: https://jira.spring.io/browse/INT-4363 * Register `HandlerMethodArgumentResolver`s in the `IntegrationRegistrar` as `BeanDefinition`s to let them be configured by the `BeanFactory` callback. The direct instance doesn't call callbacks * Use `JacksonPresent` in the `IntegrationRegistrar` instead of local property * Some code style polishing for the `IntegrationRegistrar` * Add `JsonPathTests.testJsonPathOnPayloadAnnotation()` to ensure that `PayloadExpressionArgumentResolver` is properly configured by the `BeanFactory` and `#jsonPath()` SpEL-function is properly evaluated on the `@Payload` for method `@ServiceActivator` method argument
This commit is contained in:
@@ -26,6 +26,7 @@ import org.springframework.messaging.handler.invocation.HandlerMethodArgumentRes
|
||||
* A holder for the configured argument resolvers.
|
||||
*
|
||||
* @author Gary Russell
|
||||
*
|
||||
* @since 5.0
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -37,6 +37,7 @@ import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.support.ManagedSet;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
@@ -54,9 +55,10 @@ import org.springframework.integration.handler.support.PayloadsArgumentResolver;
|
||||
import org.springframework.integration.support.DefaultMessageBuilderFactory;
|
||||
import org.springframework.integration.support.converter.ConfigurableCompositeMessageConverter;
|
||||
import org.springframework.integration.support.converter.DefaultDatatypeChannelMessageConverter;
|
||||
import org.springframework.integration.support.json.JacksonPresent;
|
||||
import org.springframework.integration.support.utils.IntegrationUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.messaging.converter.CompositeMessageConverter;
|
||||
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
@@ -64,6 +66,7 @@ import org.springframework.util.ClassUtils;
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, BeanClassLoaderAware {
|
||||
@@ -73,17 +76,13 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
|
||||
private final static IntegrationConverterInitializer INTEGRATION_CONVERTER_INITIALIZER =
|
||||
new IntegrationConverterInitializer();
|
||||
|
||||
private static final Set<Integer> registriesProcessed = new HashSet<Integer>();
|
||||
private static final Set<Integer> registriesProcessed = new HashSet<>();
|
||||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
private volatile boolean jackson2Present;
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
this.jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
|
||||
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,7 +92,9 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
|
||||
* to register the messaging annotation post processors (for {@code <int:annotation-config/>}).
|
||||
*/
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
|
||||
public void registerBeanDefinitions(@Nullable AnnotationMetadata importingClassMetadata,
|
||||
BeanDefinitionRegistry registry) {
|
||||
|
||||
registerImplicitChannelCreator(registry);
|
||||
registerIntegrationConfigurationBeanFactoryPostProcessor(registry);
|
||||
registerIntegrationEvaluationContext(registry);
|
||||
@@ -280,13 +281,15 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
|
||||
.isBeanNameInUse(IntegrationContextUtils.TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME);
|
||||
}
|
||||
|
||||
if (!alreadyRegistered && !registriesProcessed.contains(registryId) && this.jackson2Present) {
|
||||
registry.registerBeanDefinition(IntegrationContextUtils.TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME,
|
||||
if (!alreadyRegistered && !registriesProcessed.contains(registryId) && JacksonPresent.isJackson2Present()) {
|
||||
registry.registerBeanDefinition(
|
||||
IntegrationContextUtils.TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME,
|
||||
BeanDefinitionBuilder.genericBeanDefinition(IntegrationConfigUtils.BASE_PACKAGE +
|
||||
".json.ToStringFriendlyJsonNodeToStringConverter")
|
||||
.getBeanDefinition());
|
||||
INTEGRATION_CONVERTER_INITIALIZER.registerConverter(registry,
|
||||
new RuntimeBeanReference(IntegrationContextUtils.TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME));
|
||||
new RuntimeBeanReference(
|
||||
IntegrationContextUtils.TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME));
|
||||
}
|
||||
|
||||
registriesProcessed.add(registryId);
|
||||
@@ -303,7 +306,8 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
|
||||
.containsBean(IntegrationContextUtils.DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME);
|
||||
}
|
||||
else {
|
||||
alreadyRegistered = registry.isBeanNameInUse(IntegrationContextUtils.DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME);
|
||||
alreadyRegistered =
|
||||
registry.isBeanNameInUse(IntegrationContextUtils.DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME);
|
||||
}
|
||||
if (!alreadyRegistered) {
|
||||
BeanDefinitionBuilder postProcessorBuilder =
|
||||
@@ -422,8 +426,7 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
|
||||
* @param registry the registry.
|
||||
*/
|
||||
private void registerArgumentResolverMessageConverter(BeanDefinitionRegistry registry) {
|
||||
if (!registry.containsBeanDefinition(
|
||||
IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME)) {
|
||||
if (!registry.containsBeanDefinition(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME)) {
|
||||
BeanDefinitionBuilder converterBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(ConfigurableCompositeMessageConverter.class);
|
||||
registry.registerBeanDefinition(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME,
|
||||
@@ -439,7 +442,7 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
|
||||
private void registerArgumentResolvers(BeanDefinitionRegistry registry) {
|
||||
if (!registry.containsBeanDefinition(IntegrationContextUtils.ARGUMENT_RESOLVERS_BEAN_NAME)) {
|
||||
registry.registerBeanDefinition(IntegrationContextUtils.ARGUMENT_RESOLVERS_BEAN_NAME,
|
||||
internalArgumentResolversBuilder(registry, false).getBeanDefinition());
|
||||
internalArgumentResolversBuilder(false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,22 +452,25 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
|
||||
* @param registry the registry.
|
||||
*/
|
||||
private void registerListCapableArgumentResolvers(BeanDefinitionRegistry registry) {
|
||||
if (!registry.containsBeanDefinition(
|
||||
IntegrationContextUtils.LIST_ARGUMENT_RESOLVERS_BEAN_NAME)) {
|
||||
if (!registry.containsBeanDefinition(IntegrationContextUtils.LIST_ARGUMENT_RESOLVERS_BEAN_NAME)) {
|
||||
registry.registerBeanDefinition(IntegrationContextUtils.LIST_ARGUMENT_RESOLVERS_BEAN_NAME,
|
||||
internalArgumentResolversBuilder(registry, true).getBeanDefinition());
|
||||
internalArgumentResolversBuilder(true));
|
||||
}
|
||||
}
|
||||
|
||||
private BeanDefinitionBuilder internalArgumentResolversBuilder(BeanDefinitionRegistry registry,
|
||||
boolean listCapable) {
|
||||
ManagedList<HandlerMethodArgumentResolver> resolvers = new ManagedList<>();
|
||||
resolvers.add(new PayloadExpressionArgumentResolver());
|
||||
resolvers.add(new PayloadsArgumentResolver());
|
||||
resolvers.add(new CollectionArgumentResolver(listCapable));
|
||||
resolvers.add(new MapArgumentResolver());
|
||||
private BeanDefinition internalArgumentResolversBuilder(boolean listCapable) {
|
||||
ManagedList<BeanDefinition> resolvers = new ManagedList<>();
|
||||
resolvers.add(new RootBeanDefinition(PayloadExpressionArgumentResolver.class));
|
||||
resolvers.add(new RootBeanDefinition(PayloadsArgumentResolver.class));
|
||||
resolvers.add(new RootBeanDefinition(MapArgumentResolver.class));
|
||||
resolvers.add(
|
||||
BeanDefinitionBuilder.genericBeanDefinition(CollectionArgumentResolver.class)
|
||||
.addConstructorArgValue(listCapable)
|
||||
.getBeanDefinition());
|
||||
|
||||
return BeanDefinitionBuilder.genericBeanDefinition(HandlerMethodArgumentResolversHolder.class)
|
||||
.addConstructorArgValue(resolvers);
|
||||
.addConstructorArgValue(resolvers)
|
||||
.getBeanDefinition();
|
||||
}
|
||||
|
||||
private void registerMessageBuilderFactory(BeanDefinitionRegistry registry) {
|
||||
|
||||
@@ -58,11 +58,11 @@ public abstract class IntegrationContextUtils {
|
||||
|
||||
public static final String DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME = "DefaultConfiguringBeanFactoryPostProcessor";
|
||||
|
||||
public static final String MESSAGING_ANNOTATION_POSTPROCESSOR_NAME = IntegrationConfigUtils.BASE_PACKAGE
|
||||
+ ".internalMessagingAnnotationPostProcessor";
|
||||
public static final String MESSAGING_ANNOTATION_POSTPROCESSOR_NAME =
|
||||
IntegrationConfigUtils.BASE_PACKAGE + ".internalMessagingAnnotationPostProcessor";
|
||||
|
||||
public static final String PUBLISHER_ANNOTATION_POSTPROCESSOR_NAME = IntegrationConfigUtils.BASE_PACKAGE
|
||||
+ ".internalPublisherAnnotationBeanPostProcessor";
|
||||
public static final String PUBLISHER_ANNOTATION_POSTPROCESSOR_NAME =
|
||||
IntegrationConfigUtils.BASE_PACKAGE + ".internalPublisherAnnotationBeanPostProcessor";
|
||||
|
||||
public static final String INTEGRATION_CONFIGURATION_POST_PROCESSOR_BEAN_NAME =
|
||||
"IntegrationConfigurationBeanFactoryPostProcessor";
|
||||
@@ -75,8 +75,7 @@ public abstract class IntegrationContextUtils {
|
||||
public static final String INTEGRATION_FIXED_SUBSCRIBER_CHANNEL_BPP_BEAN_NAME =
|
||||
"fixedSubscriberChannelBeanFactoryPostProcessor";
|
||||
|
||||
public static final String GLOBAL_CHANNEL_INTERCEPTOR_PROCESSOR_BEAN_NAME =
|
||||
"globalChannelInterceptorProcessor";
|
||||
public static final String GLOBAL_CHANNEL_INTERCEPTOR_PROCESSOR_BEAN_NAME = "globalChannelInterceptorProcessor";
|
||||
|
||||
public static final String TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME =
|
||||
"toStringFriendlyJsonNodeToStringConverter";
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.springframework.util.Assert;
|
||||
* to convert the value to the target type.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
@@ -71,6 +72,7 @@ public class CollectionArgumentResolver extends AbstractExpressionEvaluator
|
||||
Assert.state(value instanceof Collection,
|
||||
"This Argument Resolver only supports messages with a payload of Collection<Message<?>>, "
|
||||
+ "payload is: " + value.getClass());
|
||||
|
||||
Collection<Message<?>> messages = (Collection<Message<?>>) value;
|
||||
|
||||
parameter.increaseNestingLevel();
|
||||
|
||||
@@ -130,14 +130,14 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
|
||||
private static final ExpressionParser EXPRESSION_PARSER_DEFAULT = EXPRESSION_PARSER;
|
||||
|
||||
private static final ExpressionParser EXPRESSION_PARSER_OFF = new SpelExpressionParser(
|
||||
new SpelParserConfiguration(SpelCompilerMode.OFF, null));
|
||||
private static final ExpressionParser EXPRESSION_PARSER_OFF =
|
||||
new SpelExpressionParser(new SpelParserConfiguration(SpelCompilerMode.OFF, null));
|
||||
|
||||
private static final ExpressionParser EXPRESSION_PARSER_IMMEDIATE = new SpelExpressionParser(
|
||||
new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null));
|
||||
private static final ExpressionParser EXPRESSION_PARSER_IMMEDIATE =
|
||||
new SpelExpressionParser(new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null));
|
||||
|
||||
private static final ExpressionParser EXPRESSION_PARSER_MIXED = new SpelExpressionParser(
|
||||
new SpelParserConfiguration(SpelCompilerMode.MIXED, null));
|
||||
private static final ExpressionParser EXPRESSION_PARSER_MIXED =
|
||||
new SpelExpressionParser(new SpelParserConfiguration(SpelCompilerMode.MIXED, null));
|
||||
|
||||
private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER =
|
||||
new LocalVariableTableParameterNameDiscoverer();
|
||||
@@ -149,8 +149,8 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
@SuppressWarnings("unused")
|
||||
private static final Collection<Message<?>> dummyMessages = Collections.emptyList();
|
||||
|
||||
private static final TypeDescriptor messageListTypeDescriptor = new TypeDescriptor(
|
||||
ReflectionUtils.findField(MessagingMethodInvokerHelper.class, "dummyMessages"));
|
||||
private static final TypeDescriptor messageListTypeDescriptor =
|
||||
new TypeDescriptor(ReflectionUtils.findField(MessagingMethodInvokerHelper.class, "dummyMessages"));
|
||||
|
||||
private static final TypeDescriptor messageArrayTypeDescriptor = TypeDescriptor.valueOf(Message[].class);
|
||||
|
||||
@@ -201,6 +201,7 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
|
||||
public MessagingMethodInvokerHelper(Object targetObject, Method method, Class<?> expectedType,
|
||||
boolean canProcessMessageList) {
|
||||
|
||||
this(targetObject, null, method, expectedType, canProcessMessageList);
|
||||
}
|
||||
|
||||
@@ -210,6 +211,7 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
|
||||
public MessagingMethodInvokerHelper(Object targetObject, String methodName, Class<?> expectedType,
|
||||
boolean canProcessMessageList) {
|
||||
|
||||
this(targetObject, null, methodName, expectedType, canProcessMessageList);
|
||||
}
|
||||
|
||||
@@ -219,14 +221,60 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
|
||||
public MessagingMethodInvokerHelper(Object targetObject, Class<? extends Annotation> annotationType,
|
||||
boolean canProcessMessageList) {
|
||||
|
||||
this(targetObject, annotationType, null, canProcessMessageList);
|
||||
}
|
||||
|
||||
public MessagingMethodInvokerHelper(Object targetObject, Class<? extends Annotation> annotationType,
|
||||
Class<?> expectedType, boolean canProcessMessageList) {
|
||||
|
||||
this(targetObject, annotationType, (String) null, expectedType, canProcessMessageList);
|
||||
}
|
||||
|
||||
private MessagingMethodInvokerHelper(Object targetObject, Class<? extends Annotation> annotationType,
|
||||
Method method, Class<?> expectedType, boolean canProcessMessageList) {
|
||||
|
||||
this.annotationType = annotationType;
|
||||
this.canProcessMessageList = canProcessMessageList;
|
||||
Assert.notNull(method, "method must not be null");
|
||||
this.method = method;
|
||||
this.requiresReply = expectedType != null;
|
||||
if (expectedType != null) {
|
||||
Assert.isTrue(method.getReturnType() != Void.class && method.getReturnType() != Void.TYPE,
|
||||
"method must have a return type");
|
||||
this.expectedType = TypeDescriptor.valueOf(expectedType);
|
||||
}
|
||||
else {
|
||||
this.expectedType = null;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
this.handlerMethods = null;
|
||||
this.handlerMessageMethods = null;
|
||||
this.handlerMethodsList = null;
|
||||
setDisplayString(targetObject, method);
|
||||
|
||||
JsonObjectMapper<?, ?> mapper;
|
||||
try {
|
||||
mapper = JsonObjectMapperProvider.newInstance();
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
mapper = null;
|
||||
}
|
||||
this.jsonObjectMapper = mapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@code boolean} flag to use SpEL Expression evaluation or {@link InvocableHandlerMethod}
|
||||
* for target method invocation.
|
||||
@@ -247,8 +295,7 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
if (beanExpressionResolver != null) {
|
||||
this.resolver = beanExpressionResolver;
|
||||
}
|
||||
this.expressionContext =
|
||||
new BeanExpressionContext((ConfigurableListableBeanFactory) beanFactory, null);
|
||||
this.expressionContext = new BeanExpressionContext((ConfigurableListableBeanFactory) beanFactory, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,7 +325,8 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
Class<?> type = this.handlerMethod.getTargetParameterType();
|
||||
if ((message.getPayload() instanceof String && !type.equals(String.class)
|
||||
|| message.getPayload() instanceof byte[] && !type.equals(byte[].class))
|
||||
&& contentTypeIsJson(message)) {
|
||||
&& contentTypeIsJson(message)) {
|
||||
|
||||
try {
|
||||
return getMessageBuilderFactory()
|
||||
.withPayload(this.jsonObjectMapper.fromJson(message.getPayload(), type))
|
||||
@@ -297,7 +345,7 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
|
||||
private boolean contentTypeIsJson(Message<?> message) {
|
||||
Object contentType = message.getHeaders().get(MessageHeaders.CONTENT_TYPE);
|
||||
return contentType != null ? contentType.toString().contains("json") : false;
|
||||
return contentType != null && contentType.toString().contains("json");
|
||||
}
|
||||
|
||||
public T process(Collection<Message<?>> messages, Map<String, Object> headers) throws Exception {
|
||||
@@ -333,48 +381,6 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
* Private constructors for internal use
|
||||
*/
|
||||
|
||||
private MessagingMethodInvokerHelper(Object targetObject, Class<? extends Annotation> annotationType,
|
||||
Method method, Class<?> expectedType, boolean canProcessMessageList) {
|
||||
this.annotationType = annotationType;
|
||||
this.canProcessMessageList = canProcessMessageList;
|
||||
Assert.notNull(method, "method must not be null");
|
||||
this.method = method;
|
||||
this.requiresReply = expectedType != null;
|
||||
if (expectedType != null) {
|
||||
Assert.isTrue(method.getReturnType() != Void.class && method.getReturnType() != Void.TYPE,
|
||||
"method must have a return type");
|
||||
this.expectedType = TypeDescriptor.valueOf(expectedType);
|
||||
}
|
||||
else {
|
||||
this.expectedType = null;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
this.handlerMethods = null;
|
||||
this.handlerMessageMethods = null;
|
||||
this.handlerMethodsList = null;
|
||||
this.setDisplayString(targetObject, method);
|
||||
JsonObjectMapper<?, ?> mapper;
|
||||
try {
|
||||
mapper = JsonObjectMapperProvider.newInstance();
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
mapper = null;
|
||||
}
|
||||
this.jsonObjectMapper = mapper;
|
||||
}
|
||||
|
||||
private MessagingMethodInvokerHelper(Object targetObject, Class<? extends Annotation> annotationType,
|
||||
String methodName, Class<?> expectedType, boolean canProcessMessageList) {
|
||||
this.annotationType = annotationType;
|
||||
@@ -517,8 +523,8 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
String compilerMode = resolveExpression(candidate.useSpelInvoker.compilerMode(),
|
||||
"UseSpelInvoker.compilerMode:").toUpperCase();
|
||||
parser = !StringUtils.hasText(compilerMode)
|
||||
? EXPRESSION_PARSER_DEFAULT
|
||||
: SPEL_COMPILERS.get(SpelCompilerMode.valueOf(compilerMode));
|
||||
? EXPRESSION_PARSER_DEFAULT
|
||||
: SPEL_COMPILERS.get(SpelCompilerMode.valueOf(compilerMode));
|
||||
}
|
||||
candidate.expression = parser.parseExpression(candidate.expressionString);
|
||||
candidate.initialized = true;
|
||||
@@ -526,23 +532,25 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
|
||||
private synchronized void initialize() throws Exception {
|
||||
if (!this.initialized) {
|
||||
if (getBeanFactory() != null
|
||||
&& getBeanFactory().containsBean(
|
||||
IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME)) {
|
||||
BeanFactory beanFactory = getBeanFactory();
|
||||
if (beanFactory != null &&
|
||||
beanFactory.containsBean(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME)) {
|
||||
|
||||
try {
|
||||
this.messageHandlerMethodFactory.setMessageConverter(getBeanFactory().getBean(
|
||||
IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME,
|
||||
MessageConverter.class));
|
||||
if (this.canProcessMessageList) {
|
||||
this.messageHandlerMethodFactory.setCustomArgumentResolvers(getBeanFactory().getBean(
|
||||
IntegrationContextUtils.LIST_ARGUMENT_RESOLVERS_BEAN_NAME,
|
||||
HandlerMethodArgumentResolversHolder.class).getResolvers());
|
||||
}
|
||||
else {
|
||||
this.messageHandlerMethodFactory.setCustomArgumentResolvers(getBeanFactory().getBean(
|
||||
IntegrationContextUtils.ARGUMENT_RESOLVERS_BEAN_NAME,
|
||||
HandlerMethodArgumentResolversHolder.class).getResolvers());
|
||||
}
|
||||
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();
|
||||
@@ -551,6 +559,7 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
else {
|
||||
configureLocalMessageHandlerFactory();
|
||||
}
|
||||
|
||||
this.messageHandlerMethodFactory.afterPropertiesSet();
|
||||
prepareEvaluationContext();
|
||||
this.initialized = true;
|
||||
@@ -562,8 +571,7 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
* that don't run in an application context.
|
||||
*/
|
||||
private void configureLocalMessageHandlerFactory() {
|
||||
PayloadExpressionArgumentResolver payloadExpressionArgumentResolver =
|
||||
new PayloadExpressionArgumentResolver();
|
||||
PayloadExpressionArgumentResolver payloadExpressionArgumentResolver = new PayloadExpressionArgumentResolver();
|
||||
payloadExpressionArgumentResolver.setBeanFactory(getBeanFactory());
|
||||
|
||||
PayloadsArgumentResolver payloadsArgumentResolver = new PayloadsArgumentResolver();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
* Copyright 2013-2017 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.
|
||||
@@ -39,10 +39,15 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportResource;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.integration.MessageRejectedException;
|
||||
import org.springframework.integration.annotation.ServiceActivator;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.config.EnableIntegration;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.PollableChannel;
|
||||
import org.springframework.messaging.handler.annotation.Payload;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@@ -56,6 +61,7 @@ import com.jayway.jsonpath.Predicate;
|
||||
/**
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
@ContextConfiguration(classes = JsonPathTests.JsonPathTestsContextConfiguration.class,
|
||||
@@ -207,9 +213,28 @@ public class JsonPathTests {
|
||||
assertNull(this.routerOutput1.receive(10));
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private MessageChannel jsonPathMessageChannel;
|
||||
|
||||
@Test
|
||||
public void testJsonPathOnPayloadAnnotation() {
|
||||
QueueChannel replyChannel = new QueueChannel();
|
||||
|
||||
Message<String> message = MessageBuilder.withPayload(JSON)
|
||||
.setHeader(MessageHeaders.REPLY_CHANNEL, replyChannel)
|
||||
.build();
|
||||
|
||||
this.jsonPathMessageChannel.send(message);
|
||||
|
||||
Message<?> receive = replyChannel.receive(10_000);
|
||||
|
||||
assertNotNull(receive);
|
||||
assertEquals("Nigel Rees", receive.getPayload());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ImportResource("classpath:org/springframework/integration/json/JsonPathTests-context.xml")
|
||||
@EnableIntegration
|
||||
public static class JsonPathTestsContextConfiguration {
|
||||
|
||||
@Bean
|
||||
@@ -217,6 +242,11 @@ public class JsonPathTests {
|
||||
return Filter.filter(Criteria.where("isbn").exists(true).and("category").ne("fiction"));
|
||||
}
|
||||
|
||||
@ServiceActivator(inputChannel = "jsonPathMessageChannel")
|
||||
public String handle(@Payload("#jsonPath(#root, '$.store.book[0].author')") String payload) {
|
||||
return payload;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user