diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BindingServiceConfiguration.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BindingServiceConfiguration.java index 4233803ba..b98cb11e2 100644 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BindingServiceConfiguration.java +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BindingServiceConfiguration.java @@ -16,7 +16,6 @@ package org.springframework.cloud.stream.config; -import java.beans.Introspector; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -32,7 +31,6 @@ import org.springframework.cloud.stream.binder.BinderFactory; import org.springframework.cloud.stream.binding.AbstractBindingTargetFactory; import org.springframework.cloud.stream.binding.Bindable; import org.springframework.cloud.stream.binding.BinderAwareChannelResolver; -import org.springframework.cloud.stream.binding.BinderAwareRouterBeanPostProcessor; import org.springframework.cloud.stream.binding.BindingService; import org.springframework.cloud.stream.binding.CompositeMessageChannelConfigurer; import org.springframework.cloud.stream.binding.ContextStartAfterRefreshListener; @@ -51,15 +49,12 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Role; -import org.springframework.expression.PropertyAccessor; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.channel.PublishSubscribeChannel; import org.springframework.integration.config.HandlerMethodArgumentResolversHolder; -import org.springframework.integration.config.IntegrationEvaluationContextFactoryBean; import org.springframework.integration.context.IntegrationContextUtils; import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; import org.springframework.integration.handler.BridgeHandler; -import org.springframework.integration.json.JsonPropertyAccessor; import org.springframework.integration.router.AbstractMappingMessageRouter; import org.springframework.lang.Nullable; import org.springframework.messaging.MessageChannel; @@ -68,7 +63,6 @@ import org.springframework.messaging.core.DestinationResolver; import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory; import org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory; import org.springframework.scheduling.TaskScheduler; -import org.springframework.tuple.spel.TuplePropertyAccessor; import org.springframework.util.CollectionUtils; /** @@ -83,7 +77,6 @@ import org.springframework.util.CollectionUtils; * @author Artem Bilan * @author Oleg Zhurakousky */ -@SuppressWarnings("deprecation") @Configuration @EnableConfigurationProperties({ BindingServiceProperties.class, SpringIntegrationProperties.class }) @Import(ContentTypeConfiguration.class) @@ -216,27 +209,12 @@ public class BindingServiceConfiguration { @Bean @ConditionalOnMissingBean - public BinderAwareRouterBeanPostProcessor binderAwareRouterBeanPostProcessor(@Autowired(required=false) AbstractMappingMessageRouter[] routers, + @SuppressWarnings("deprecation") + public org.springframework.cloud.stream.binding.BinderAwareRouterBeanPostProcessor binderAwareRouterBeanPostProcessor( + @Autowired(required=false) AbstractMappingMessageRouter[] routers, @Autowired(required=false)DestinationResolver channelResolver) { - return new BinderAwareRouterBeanPostProcessor(routers, channelResolver); - } - @Bean - public InitializingBean propertyAccessorInjector(IntegrationEvaluationContextFactoryBean[] iecfbs) { - return new InitializingBean() { - @Override - public void afterPropertiesSet() throws Exception { - TuplePropertyAccessor tpa = new TuplePropertyAccessor(); - JsonPropertyAccessor jpa = new JsonPropertyAccessor(); - if (iecfbs != null) { - for (IntegrationEvaluationContextFactoryBean iecfb : iecfbs) { - Map factoryBeanAccessors = iecfb.getPropertyAccessors(); - factoryBeanAccessors.put(Introspector.decapitalize(tpa.getClass().getSimpleName()), tpa); - factoryBeanAccessors.put(Introspector.decapitalize(jpa.getClass().getSimpleName()), jpa); - } - } - } - }; + return new org.springframework.cloud.stream.binding.BinderAwareRouterBeanPostProcessor(routers, channelResolver); } @Bean @@ -254,4 +232,5 @@ public class BindingServiceConfiguration { } }; } + } diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/SpelExpressionConverterConfiguration.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/SpelExpressionConverterConfiguration.java index 699f1a861..b3ffcd45b 100644 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/SpelExpressionConverterConfiguration.java +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/SpelExpressionConverterConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2015-2018 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. @@ -16,6 +16,8 @@ package org.springframework.cloud.stream.config; +import java.beans.Introspector; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.config.BeanDefinition; @@ -32,16 +34,36 @@ import org.springframework.expression.spel.standard.SpelExpression; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.integration.config.IntegrationConverter; import org.springframework.integration.context.IntegrationContextUtils; +import org.springframework.integration.expression.SpelPropertyAccessorRegistrar; +import org.springframework.integration.json.JsonPropertyAccessor; +import org.springframework.tuple.spel.TuplePropertyAccessor; /** * Adds a Converter from String to SpEL Expression in the context. * * @author Eric Bottard + * @author Artem Bilan */ @Configuration @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public class SpelExpressionConverterConfiguration { + /** + * Provide a {@link SpelPropertyAccessorRegistrar} supplied + * with the {@link JsonPropertyAccessor} and {@link TuplePropertyAccessor}. + * This bean is used to customize an + * {@link org.springframework.integration.config.IntegrationEvaluationContextFactoryBean}. + * for additional {@link org.springframework.expression.PropertyAccessor}s. + * @return the SpelPropertyAccessorRegistrar bean + * @see org.springframework.integration.config.IntegrationEvaluationContextFactoryBean + */ + @Bean + public static SpelPropertyAccessorRegistrar spelPropertyAccessorRegistrar() { + return new SpelPropertyAccessorRegistrar() + .add(Introspector.decapitalize(JsonPropertyAccessor.class.getSimpleName()), new JsonPropertyAccessor()) + .add(Introspector.decapitalize(TuplePropertyAccessor.class.getSimpleName()), new TuplePropertyAccessor()); + } + @Bean @ConfigurationPropertiesBinding @IntegrationConverter diff --git a/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/config/SpelExpressionConverterConfigurationTests.java b/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/config/SpelExpressionConverterConfigurationTests.java index 462cf18aa..c00e2b629 100644 --- a/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/config/SpelExpressionConverterConfigurationTests.java +++ b/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/config/SpelExpressionConverterConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 the original author or authors. + * Copyright 2015-2018 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. @@ -16,9 +16,16 @@ package org.springframework.cloud.stream.config; +import java.util.List; + +import javax.annotation.PostConstruct; + import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -26,9 +33,15 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.stream.annotation.EnableBinding; import org.springframework.cloud.stream.utils.MockBinderRegistryConfiguration; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; +import org.springframework.expression.PropertyAccessor; +import org.springframework.integration.expression.ExpressionUtils; +import org.springframework.integration.json.JsonPropertyAccessor; +import org.springframework.integration.test.util.TestUtils; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -37,6 +50,7 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for SpelExpressionConverterConfiguration. * * @author Eric Bottard + * @author Artem Bilan */ @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = SpelExpressionConverterConfigurationTests.Config.class, properties = "expression: a.b") @@ -45,9 +59,28 @@ public class SpelExpressionConverterConfigurationTests { @Autowired private Pojo pojo; + @Autowired + private EvaluationContext evaluationContext; + + @Autowired + private Config config; + + @Test + @SuppressWarnings("unchecked") public void converterCorrectlyInstalled() { - assertThat(pojo.getExpression().getValue("{\"a\": {\"b\": 5}}").toString()).isEqualTo("5"); + Expression expression = pojo.getExpression(); + assertThat(expression.getValue("{\"a\": {\"b\": 5}}").toString()).isEqualTo("5"); + + List propertyAccessors = + TestUtils.getPropertyValue(this.evaluationContext, "propertyAccessors", List.class); + + assertThat(propertyAccessors).hasAtLeastOneElementOfType(JsonPropertyAccessor.class); + + propertyAccessors = + TestUtils.getPropertyValue(this.config.evaluationContext, "propertyAccessors", List.class); + + assertThat(propertyAccessors).hasAtLeastOneElementOfType(JsonPropertyAccessor.class); } @ConfigurationProperties @@ -69,7 +102,26 @@ public class SpelExpressionConverterConfigurationTests { @EnableAutoConfiguration @Import(MockBinderRegistryConfiguration.class) @EnableConfigurationProperties(Pojo.class) - public static class Config { + public static class Config implements BeanFactoryAware { + + private BeanFactory beanFactory; + + private EvaluationContext evaluationContext; + + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = beanFactory; + } + + @Bean + public EvaluationContext evaluationContext() { + return ExpressionUtils.createStandardEvaluationContext(this.beanFactory); + } + + @PostConstruct + public void setup() { + this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(this.beanFactory); + } }