diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/HandlerMethodArgumentResolversHolder.java b/spring-integration-core/src/main/java/org/springframework/integration/config/HandlerMethodArgumentResolversHolder.java index 1a1b20a514..8c60ca975a 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/HandlerMethodArgumentResolversHolder.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/HandlerMethodArgumentResolversHolder.java @@ -26,6 +26,7 @@ import org.springframework.messaging.handler.invocation.HandlerMethodArgumentRes * A holder for the configured argument resolvers. * * @author Gary Russell + * * @since 5.0 * */ diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationRegistrar.java b/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationRegistrar.java index 2e9f678bf8..386be13322 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationRegistrar.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationRegistrar.java @@ -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 registriesProcessed = new HashSet(); + private static final Set 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 }). */ @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 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 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) { diff --git a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java index dab26de847..0e9ac1fc1f 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java @@ -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"; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/support/CollectionArgumentResolver.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/support/CollectionArgumentResolver.java index 04c1358b6e..cf8ab5d8f0 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/handler/support/CollectionArgumentResolver.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/support/CollectionArgumentResolver.java @@ -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>, " + "payload is: " + value.getClass()); + Collection> messages = (Collection>) value; parameter.increaseNestingLevel(); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/util/MessagingMethodInvokerHelper.java b/spring-integration-core/src/main/java/org/springframework/integration/util/MessagingMethodInvokerHelper.java index a44543b9ea..0811c564ff 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/util/MessagingMethodInvokerHelper.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/util/MessagingMethodInvokerHelper.java @@ -130,14 +130,14 @@ public class MessagingMethodInvokerHelper 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 extends AbstractExpressionEvaluator @SuppressWarnings("unused") private static final Collection> 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 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 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 extends AbstractExpressionEvaluator public MessagingMethodInvokerHelper(Object targetObject, Class annotationType, boolean canProcessMessageList) { + this(targetObject, annotationType, null, canProcessMessageList); } public MessagingMethodInvokerHelper(Object targetObject, Class annotationType, Class expectedType, boolean canProcessMessageList) { + this(targetObject, annotationType, (String) null, expectedType, canProcessMessageList); } + private MessagingMethodInvokerHelper(Object targetObject, Class 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 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 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 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> messages, Map headers) throws Exception { @@ -333,48 +381,6 @@ public class MessagingMethodInvokerHelper extends AbstractExpressionEvaluator * Private constructors for internal use */ - private MessagingMethodInvokerHelper(Object targetObject, Class 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 annotationType, String methodName, Class expectedType, boolean canProcessMessageList) { this.annotationType = annotationType; @@ -517,8 +523,8 @@ public class MessagingMethodInvokerHelper 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 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 extends AbstractExpressionEvaluator else { configureLocalMessageHandlerFactory(); } + this.messageHandlerMethodFactory.afterPropertiesSet(); prepareEvaluationContext(); this.initialized = true; @@ -562,8 +571,7 @@ public class MessagingMethodInvokerHelper 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(); diff --git a/spring-integration-core/src/test/java/org/springframework/integration/json/JsonPathTests.java b/spring-integration-core/src/test/java/org/springframework/integration/json/JsonPathTests.java index 2598a901eb..705e2e4f63 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/json/JsonPathTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/json/JsonPathTests.java @@ -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 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; + } + } }