From 1f3b6ed344d395d41e5b7c6f8ad44ae8031af342 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Wed, 19 Sep 2018 10:41:32 +0200 Subject: [PATCH] GH-1484 common strategy for extended binding properties Resolves #1484 --- .../BinderSpecificPropertiesProvider.java | 31 ++++++++++++++ .../stream/binder/ConsumerProperties.java | 2 +- .../binder/ExtendedBindingProperties.java | 9 ++--- .../cloud/stream/binding/BindingService.java | 40 ++++++++----------- .../stream/utils/FooBindingProperties.java | 4 +- 5 files changed, 55 insertions(+), 31 deletions(-) create mode 100644 spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/BinderSpecificPropertiesProvider.java diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/BinderSpecificPropertiesProvider.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/BinderSpecificPropertiesProvider.java new file mode 100644 index 000000000..878f25a96 --- /dev/null +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/BinderSpecificPropertiesProvider.java @@ -0,0 +1,31 @@ +/* + * Copyright 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.stream.binder; + +/** + * + * @author Oleg Zhurakousky + * + * @since 2.1 + * + */ +public interface BinderSpecificPropertiesProvider { + + Object getConsumer(); + + Object getProducer(); +} diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/ConsumerProperties.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/ConsumerProperties.java index ba5a40b82..e373ebc49 100644 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/ConsumerProperties.java +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/ConsumerProperties.java @@ -35,7 +35,7 @@ import org.springframework.cloud.stream.config.MergableProperties; * @author Oleg Zhurakousky */ @JsonInclude(JsonInclude.Include.NON_DEFAULT) -public class ConsumerProperties implements MergableProperties{ +public class ConsumerProperties implements MergableProperties { /** * The concurrency setting of the consumer. Default: 1. diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/ExtendedBindingProperties.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/ExtendedBindingProperties.java index 6e1728026..d3537e4ad 100644 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/ExtendedBindingProperties.java +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/ExtendedBindingProperties.java @@ -47,13 +47,12 @@ public interface ExtendedBindingProperties { /** * - * Extended properties class against which default extended producer and consumer properties - * are resolved. It is expected that this class has two properties - one called producer - * and another called consumer that contains the extended properties for producer and - * consumer respectively. + * Extended properties class which should be a subclass of {@link BinderSpecificPropertiesProvider} + * against which default extended producer and consumer properties + * are resolved. * * @return extended properties class that contains extended producer/consumer properties * @since 2.1.0 */ - Class getExtendedPropertiesEntryClass(); + Class getExtendedPropertiesEntryClass(); } diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/BindingService.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/BindingService.java index 2544d14b8..c24579c82 100644 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/BindingService.java +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/BindingService.java @@ -16,7 +16,6 @@ package org.springframework.cloud.stream.binding; -import java.lang.reflect.Field; import java.sql.Date; import java.util.ArrayList; import java.util.Collection; @@ -35,6 +34,7 @@ import org.springframework.boot.context.properties.bind.PropertySourcesPlacehold import org.springframework.boot.context.properties.source.ConfigurationPropertySources; import org.springframework.cloud.stream.binder.Binder; import org.springframework.cloud.stream.binder.BinderFactory; +import org.springframework.cloud.stream.binder.BinderSpecificPropertiesProvider; import org.springframework.cloud.stream.binder.Binding; import org.springframework.cloud.stream.binder.ConsumerProperties; import org.springframework.cloud.stream.binder.ExtendedConsumerProperties; @@ -51,7 +51,6 @@ import org.springframework.context.ConfigurableApplicationContext; import org.springframework.integration.support.utils.IntegrationUtils; import org.springframework.scheduling.TaskScheduler; import org.springframework.util.CollectionUtils; -import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import org.springframework.validation.DataBinder; import org.springframework.validation.beanvalidation.CustomValidatorBean; @@ -122,7 +121,7 @@ public class BindingService implements ApplicationContextAware { if (MergableProperties.class.isAssignableFrom(extendedConsumerProperties.getExtension().getClass())) { handleExtendedDefaultProperties((ExtendedPropertiesBinder) binder, - (MergableProperties) extendedConsumerProperties.getExtension(), "consumer"); + (MergableProperties) extendedConsumerProperties.getExtension(), false); } consumerProperties = extendedConsumerProperties; @@ -247,7 +246,7 @@ public class BindingService implements ApplicationContextAware { if (MergableProperties.class.isAssignableFrom(extendedProducerProperties.getExtension().getClass())) { handleExtendedDefaultProperties((ExtendedPropertiesBinder) binder, - (MergableProperties) extendedProducerProperties.getExtension(), "producer"); + (MergableProperties) extendedProducerProperties.getExtension(), true); } producerProperties = extendedProducerProperties; } @@ -257,26 +256,21 @@ public class BindingService implements ApplicationContextAware { return binding; } - private void handleExtendedDefaultProperties(ExtendedPropertiesBinder binder, MergableProperties extendedProperties, String filedName) { + private void handleExtendedDefaultProperties(ExtendedPropertiesBinder binder, MergableProperties extendedProperties, boolean producer) { String defaultsPrefix = binder.getDefaultsPrefix(); - Class extendedPropertiesEntryClass = binder.getExtendedPropertiesEntryClass(); - if (defaultsPrefix != null && extendedPropertiesEntryClass != null) { + if (defaultsPrefix != null) { + Class extendedPropertiesEntryClass = binder.getExtendedPropertiesEntryClass(); + if (BinderSpecificPropertiesProvider.class.isAssignableFrom(extendedPropertiesEntryClass)) { + org.springframework.boot.context.properties.bind.Binder extendedPropertiesResolverBinder = + new org.springframework.boot.context.properties.bind.Binder(ConfigurationPropertySources.get(applicationContext.getEnvironment()), + new PropertySourcesPlaceholdersResolver(applicationContext.getEnvironment()), + IntegrationUtils.getConversionService(this.applicationContext.getBeanFactory()), null); + BinderSpecificPropertiesProvider defaultProperties = BeanUtils.instantiateClass(extendedPropertiesEntryClass); + extendedPropertiesResolverBinder.bind(defaultsPrefix, Bindable.ofInstance(defaultProperties)); - org.springframework.boot.context.properties.bind.Binder extendedPropertiesResolverBinder = - new org.springframework.boot.context.properties.bind.Binder(ConfigurationPropertySources.get(applicationContext.getEnvironment()), - new PropertySourcesPlaceholdersResolver(applicationContext.getEnvironment()), - IntegrationUtils.getConversionService(this.applicationContext.getBeanFactory()), null); - Object defaultProperties = BeanUtils.instantiateClass(extendedPropertiesEntryClass); - extendedPropertiesResolverBinder.bind(defaultsPrefix, Bindable.ofInstance(defaultProperties)); - - Field extendedPropertyField = ReflectionUtils.findField(defaultProperties.getClass(), filedName); - if (extendedPropertyField != null) { - extendedPropertyField.setAccessible(true); - Object extendedProducerObject = ReflectionUtils.getField(extendedPropertyField, defaultProperties); - if (extendedProducerObject != null) { - ((MergableProperties)extendedProducerObject).merge(extendedProperties); - } + Object binderExtendedProperties = producer ? defaultProperties.getProducer() : defaultProperties.getConsumer(); + ((MergableProperties)binderExtendedProperties).merge(extendedProperties); } } } @@ -287,9 +281,7 @@ public class BindingService implements ApplicationContextAware { if (binder instanceof ExtendedPropertiesBinder) { return ((ExtendedPropertiesBinder) binder).getExtendedProducerProperties(outputName); } - else { - return null; - } + return null; } public Binding doBindProducer(T output, String bindingTarget, Binder binder, diff --git a/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/utils/FooBindingProperties.java b/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/utils/FooBindingProperties.java index 30fd3ef9f..10f9c8a7c 100644 --- a/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/utils/FooBindingProperties.java +++ b/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/utils/FooBindingProperties.java @@ -16,10 +16,12 @@ package org.springframework.cloud.stream.utils; +import org.springframework.cloud.stream.binder.BinderSpecificPropertiesProvider; + /** * @author Soby Chacko */ -public class FooBindingProperties { +public class FooBindingProperties implements BinderSpecificPropertiesProvider { private FooExtendedProducerProperties producer = new FooExtendedProducerProperties();