From 2543657da9007918ccae20df8e29dfe6609d07c3 Mon Sep 17 00:00:00 2001 From: Udo Kohlmeyer Date: Thu, 20 Dec 2018 09:44:55 -0800 Subject: [PATCH] SGF-521 - Configure GatewayReceivers with Annotations. Adds the EnableGatewayReceiver annotation to the SDG Annotation based configuraiton model to configure a GatewayReceiver. --- .../AbstractAnnotationConfigSupport.java | 5 + .../wan/AbstractWANComponentFactoryBean.java | 6 +- .../wan/GatewayReceiverFactoryBean.java | 21 ++ .../wan/annotation/EnableGatewayReceiver.java | 88 +++++++ .../EnableGatewayReceiverConfiguration.java | 213 ++++++++++++++++ .../EnableGatewayReceiverConfigurer.java | 16 ++ ...eEnableGatewayReceiverConfigurerTests.java | 235 ++++++++++++++++++ ...ableGatewayReceiverConfigurationTests.java | 179 +++++++++++++ .../EnableGatewayReceiverPropertiesTests.java | 154 ++++++++++++ 9 files changed, 916 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/springframework/data/gemfire/wan/annotation/EnableGatewayReceiver.java create mode 100644 src/main/java/org/springframework/data/gemfire/wan/annotation/EnableGatewayReceiverConfiguration.java create mode 100644 src/main/java/org/springframework/data/gemfire/wan/annotation/EnableGatewayReceiverConfigurer.java create mode 100644 src/test/java/org/springframework/data/gemfire/config/annotation/EnableEnableGatewayReceiverConfigurerTests.java create mode 100644 src/test/java/org/springframework/data/gemfire/config/annotation/EnableGatewayReceiverConfigurationTests.java create mode 100644 src/test/java/org/springframework/data/gemfire/config/annotation/EnableGatewayReceiverPropertiesTests.java diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/support/AbstractAnnotationConfigSupport.java b/src/main/java/org/springframework/data/gemfire/config/annotation/support/AbstractAnnotationConfigSupport.java index 75d993be..6982ad67 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/support/AbstractAnnotationConfigSupport.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/support/AbstractAnnotationConfigSupport.java @@ -65,6 +65,7 @@ import org.slf4j.LoggerFactory; * all Annotations and configuration classes used to configure Pivotal GemFire/Apache Geode objects with SDG. * * @author John Blum + * @author Udo Kohlmeyer * @see java.lang.ClassLoader * @see org.springframework.beans.factory.BeanClassLoaderAware * @see org.springframework.beans.factory.BeanFactory @@ -769,6 +770,10 @@ public abstract class AbstractAnnotationConfigSupport return String.format("%1$s%2$s", serviceProperty("http."), propertyNameSuffix); } + protected String gatewayReceiverProperty(String propertyNameSuffix) { + return String.format("%1$s%2$s", propertyName("gateway.receiver."), propertyNameSuffix); + } + /** * Returns the fully-qualified {@link String property name}. * diff --git a/src/main/java/org/springframework/data/gemfire/wan/AbstractWANComponentFactoryBean.java b/src/main/java/org/springframework/data/gemfire/wan/AbstractWANComponentFactoryBean.java index f1268664..b598d400 100644 --- a/src/main/java/org/springframework/data/gemfire/wan/AbstractWANComponentFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/wan/AbstractWANComponentFactoryBean.java @@ -40,7 +40,7 @@ import org.springframework.util.StringUtils; public abstract class AbstractWANComponentFactoryBean implements BeanNameAware, DisposableBean, FactoryBean, InitializingBean { - protected final Cache cache; + protected Cache cache; protected final Logger logger = LoggerFactory.getLogger(getClass()); @@ -53,6 +53,10 @@ public abstract class AbstractWANComponentFactoryBean this.cache = cache; } + public void setCache(Cache cache) { + this.cache = cache; + } + @Override public void setBeanName(String beanName) { this.beanName = beanName; diff --git a/src/main/java/org/springframework/data/gemfire/wan/GatewayReceiverFactoryBean.java b/src/main/java/org/springframework/data/gemfire/wan/GatewayReceiverFactoryBean.java index d816a63d..92f57c64 100644 --- a/src/main/java/org/springframework/data/gemfire/wan/GatewayReceiverFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/wan/GatewayReceiverFactoryBean.java @@ -15,14 +15,19 @@ */ package org.springframework.data.gemfire.wan; +import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Optional; import org.apache.geode.cache.Cache; import org.apache.geode.cache.wan.GatewayReceiver; import org.apache.geode.cache.wan.GatewayReceiverFactory; import org.apache.geode.cache.wan.GatewayTransportFilter; import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.gemfire.util.CollectionUtils; +import org.springframework.data.gemfire.wan.annotation.EnableGatewayReceiverConfigurer; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -31,6 +36,7 @@ import org.springframework.util.StringUtils; * * @author David Turanski * @author John Blum + * @author Udo Kohlmeyer * @see org.springframework.context.SmartLifecycle * @see org.springframework.data.gemfire.wan.AbstractWANComponentFactoryBean * @see org.apache.geode.cache.Cache @@ -50,11 +56,15 @@ public class GatewayReceiverFactoryBean extends AbstractWANComponentFactoryBean< private Integer socketBufferSize; private Integer startPort; + @Autowired private List transportFilters; private String bindAddress; private String hostnameForSenders; + @Autowired + private EnableGatewayReceiverConfigurer gatewayReceiverConfigurer; + /** * Constructs an instance of the {@link GatewayReceiverFactoryBean} class initialized with a reference to * the Pivotal GemFire {@link Cache} used to configure and initialize a Pivotal GemFire {@link GatewayReceiver}. @@ -89,6 +99,9 @@ public class GatewayReceiverFactoryBean extends AbstractWANComponentFactoryBean< protected void doInit() throws Exception { GatewayReceiverFactory gatewayReceiverFactory = cache.createGatewayReceiverFactory(); + Optional.of(gatewayReceiverConfigurer) + .ifPresent(gatewayReceiverConfigurer1 -> gatewayReceiverConfigurer1.configure("GatewayReceiver",this)); + if (StringUtils.hasText(bindAddress)) { gatewayReceiverFactory.setBindAddress(bindAddress); } @@ -161,4 +174,12 @@ public class GatewayReceiverFactoryBean extends AbstractWANComponentFactoryBean< public void setTransportFilters(List transportFilters) { this.transportFilters = transportFilters; } + + public Collection getTransportFilters() { + return Collections.unmodifiableList(transportFilters); + } + + public void setGatewayReceiverConfigurer(EnableGatewayReceiverConfigurer gatewayReceiverConfigurer) { + this.gatewayReceiverConfigurer = gatewayReceiverConfigurer; + } } diff --git a/src/main/java/org/springframework/data/gemfire/wan/annotation/EnableGatewayReceiver.java b/src/main/java/org/springframework/data/gemfire/wan/annotation/EnableGatewayReceiver.java new file mode 100644 index 00000000..f5a3d6ce --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/wan/annotation/EnableGatewayReceiver.java @@ -0,0 +1,88 @@ +package org.springframework.data.gemfire.wan.annotation; + +import org.springframework.context.annotation.Import; + +import java.lang.annotation.*; + +/** + * The EnableGatewayReceiver annotation creates a {@link org.apache.geode.cache.wan.GatewayReceiver} + * within GemFire/Geode {@link org.apache.geode.cache.Cache} + * + * @author Udo Kohlmeyer + * @see org.springframework.context.annotation.Configuration + * @see org.springframework.context.annotation.Import + * @see org.apache.geode.cache.wan.GatewayTransportFilter + * @see org.apache.geode.cache.wan.GatewayReceiver + * @see org.apache.geode.cache.Cache + * @since 2.2.0 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +@Documented +@Import(EnableGatewayReceiverConfiguration.class) +@SuppressWarnings("unused") +public @interface EnableGatewayReceiver { + + /** + * A boolean to allow the GatewayReceiver to be created without being started after creation. + * If the manualStart is set to {@literal true} then the system will create the GatewayReceiver but not start it. + * It then becomes the responsibility of the operator to start the GatewayReceiver at a later stage. + * If set to {@literal false} the GatewayReceiver will start automatically after creation. + * Default is {@value EnableGatewayReceiverConfiguration#DEFAULT_MANUAL_START} + */ + boolean manualStart() default EnableGatewayReceiverConfiguration.DEFAULT_MANUAL_START; + + /** + * The starting port number that GatewayReceiver will use when selecting a port to run on. This range of port numbers + * is bounded by the {startPort} and {endPort}. + * Default is {@value EnableGatewayReceiverConfiguration#DEFAULT_START_PORT} + */ + int startPort() default EnableGatewayReceiverConfiguration.DEFAULT_START_PORT; + + /** + * The end port number that GatewayReceiver will use when selecting a port to run on. This range of port numbers + * is bounded by the {startPort} and {endPort}. + * Default is {@value EnableGatewayReceiverConfiguration#DEFAULT_END_PORT} + */ + int endPort() default EnableGatewayReceiverConfiguration.DEFAULT_END_PORT; + + /** + * An integer value in milliseconds representing the maximum time which a {@link org.apache.geode.cache.wan.GatewayReceiver} + * will wait to receive a ping back from a {@link org.apache.geode.cache.wan.GatewaySender} before the {@link org.apache.geode.cache.wan.GatewayReceiver} + * believes the sender to be not available. + * Default value is {@value EnableGatewayReceiverConfiguration#DEFAULT_MAXIMUM_TIME_BETWEEN_PINGS} + */ + int maximumTimeBetweenPings() default EnableGatewayReceiverConfiguration.DEFAULT_MAXIMUM_TIME_BETWEEN_PINGS; + + /** + * The socket buffer size for the {@link org.apache.geode.cache.wan.GatewayReceiver}. This setting is in bytes + * Default value is {@value EnableGatewayReceiverConfiguration#DEFAULT_SOCKET_BUFFER_SIZE} + */ + int socketBufferSize() default EnableGatewayReceiverConfiguration.DEFAULT_SOCKET_BUFFER_SIZE; + + /** + * An in-order list of {@link org.apache.geode.cache.wan.GatewayTransportFilter} to be applied to + * {@link org.apache.geode.cache.wan.GatewayReceiver} + * Default value is {@value {}} + */ + String[] transportFilters() default {}; + + /** + * The IP address or hostname that the {@link org.apache.geode.cache.wan.GatewayReceiver} communication socket will be bound to. + * An empty String will cause the underlying socket to bind to 0.0.0.0 + * Default value is {@value EnableGatewayReceiverConfiguration#DEFAULT_BIND_ADDRESS} + */ + String bindAddress() default EnableGatewayReceiverConfiguration.DEFAULT_BIND_ADDRESS; + + /** + * The hostname or IP Address that the {@link org.apache.geode.cache.wan.GatewaySender} will use to connect and communicate with the + * {@link org.apache.geode.cache.wan.GatewayReceiver}. An empty String will cause the system to expose the hostname + * to the {@link org.apache.geode.cache.wan.GatewaySender}. Generally this property is set when there are multiple + * network interfaces or when they are designated as "internal" or "public" network interfaces. In a cloud environment + * the notion of external and internal network interfaces exist and generally the "externally"/outwardly facing network + * interface is used. + * Default value is {@value EnableGatewayReceiverConfiguration#DEFAULT_HOSTNAME_FOR_SENDERS} + */ + String hostnameForSenders() default EnableGatewayReceiverConfiguration.DEFAULT_HOSTNAME_FOR_SENDERS; +} diff --git a/src/main/java/org/springframework/data/gemfire/wan/annotation/EnableGatewayReceiverConfiguration.java b/src/main/java/org/springframework/data/gemfire/wan/annotation/EnableGatewayReceiverConfiguration.java new file mode 100644 index 00000000..0a800d69 --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/wan/annotation/EnableGatewayReceiverConfiguration.java @@ -0,0 +1,213 @@ +package org.springframework.data.gemfire.wan.annotation; + +import org.apache.geode.cache.wan.GatewayReceiver; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.factory.config.BeanReference; +import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.ManagedList; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport; +import org.springframework.data.gemfire.config.xml.GemfireConstants; +import org.springframework.data.gemfire.wan.GatewayReceiverFactoryBean; + +import java.lang.annotation.Annotation; +import java.util.Arrays; +import java.util.Optional; + +/** + * Spring {@link Configuration} class used to construct, configure and initialize a {@link GatewayReceiver} instance + * in a Spring application context. + * + * @author Udo Kohlmeyer + * @see org.apache.geode.cache.wan.GatewayReceiver + * @see org.springframework.context.annotation.Bean + * @see org.springframework.context.annotation.Configuration + * @see org.springframework.data.gemfire.wan.annotation.EnableGatewayReceiver + * @since 2.2.0 + */ +public class EnableGatewayReceiverConfiguration extends AbstractAnnotationConfigSupport + implements ImportBeanDefinitionRegistrar { + + static final boolean DEFAULT_MANUAL_START = GatewayReceiver.DEFAULT_MANUAL_START; + static final int DEFAULT_START_PORT = GatewayReceiver.DEFAULT_START_PORT; + static final int DEFAULT_END_PORT = GatewayReceiver.DEFAULT_END_PORT; + static final int DEFAULT_MAXIMUM_TIME_BETWEEN_PINGS = GatewayReceiver.DEFAULT_MAXIMUM_TIME_BETWEEN_PINGS; + static final int DEFAULT_SOCKET_BUFFER_SIZE = GatewayReceiver.DEFAULT_SOCKET_BUFFER_SIZE; + static final String DEFAULT_BIND_ADDRESS = GatewayReceiver.DEFAULT_BIND_ADDRESS; + static final String DEFAULT_HOSTNAME_FOR_SENDERS = GatewayReceiver.DEFAULT_HOSTNAME_FOR_SENDERS; + private final String START_PORT_LITERAL = "startPort"; + private final String END_PORT_LITERAL = "END_PORT_LITERAL"; + private final String MANUAL_START_LITERAL = "manualStart"; + private final String MAXIMUM_TIME_BETWEEN_PINGS_LITERAL = "maximumTimeBetweenPings"; + private final String SOCKET_BUFFER_SIZE_LITERAL = "socketBufferSize"; + private final String BIND_ADDRESS_LITERAL = "bindAddress"; + private final String HOSTNAME_FOR_SENDERS_LITERAL = "hostnameForSenders"; + private final String TRANSPORT_FILTERS_LITERAL = "transportFilters"; + + @Override + protected Class getAnnotationType() { + return org.springframework.data.gemfire.wan.annotation.EnableGatewayReceiver.class; + } + + @Override + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { + if (importingClassMetadata.hasAnnotation(getAnnotationTypeName())) { + + AnnotationAttributes enableGatewayReceiverAttributes = + AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(getAnnotationTypeName())); + + registerGatewayReceiverBeanDefinition(enableGatewayReceiverAttributes, registry); + } + } + + /** + * Configures a {@link GatewayReceiver} from the {@link EnableGatewayReceiver} annotation, "spring.data.gemfire.gateway.receiver.*" + * properties and {@link EnableGatewayReceiverConfigurer} + * + * @param enableGatewayReceiverAttributes + * @param registry + */ + private void registerGatewayReceiverBeanDefinition(AnnotationAttributes enableGatewayReceiverAttributes, + BeanDefinitionRegistry registry) { + BeanDefinitionBuilder gatewayReceiverBeanBuilder = + BeanDefinitionBuilder.genericBeanDefinition(GatewayReceiverFactoryBean.class); + + String gatewayReceiverBeanName = "GatewayReceiver"; + + configureBeanFromAnnotatedProperties(enableGatewayReceiverAttributes, gatewayReceiverBeanBuilder, + gatewayReceiverBeanName); + + configureBeanBuilderFromPropertiesOrWithDefaultValues(gatewayReceiverBeanBuilder); + + registerGatewayTransportFilterDependencies(enableGatewayReceiverAttributes, gatewayReceiverBeanBuilder); + + registry.registerBeanDefinition(gatewayReceiverBeanName, gatewayReceiverBeanBuilder.getBeanDefinition()); + } + + /** + * Configures GatewayReceiver {@link BeanDefinitionBuilder} using value populated on {@link EnableGatewayReceiver}. + * If no values are provided, values are set to defaults + * + * @param enableGatewayReceiverAttributes + * @param gatewayReceiverBeanBuilder + * @param gatewayReceiverBeanName + */ + private void configureBeanFromAnnotatedProperties(AnnotationAttributes enableGatewayReceiverAttributes, + BeanDefinitionBuilder gatewayReceiverBeanBuilder, String gatewayReceiverBeanName) { + gatewayReceiverBeanBuilder.addConstructorArgReference(GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME); + + gatewayReceiverBeanBuilder.addPropertyValue("beanName", gatewayReceiverBeanName); + + gatewayReceiverBeanBuilder.addPropertyReference("cache", GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME); + + setPropertyValueIfNotDefault(gatewayReceiverBeanBuilder, START_PORT_LITERAL, + enableGatewayReceiverAttributes.getNumber(START_PORT_LITERAL), DEFAULT_START_PORT); + + setPropertyValueIfNotDefault(gatewayReceiverBeanBuilder, END_PORT_LITERAL, + enableGatewayReceiverAttributes.getNumber(END_PORT_LITERAL), DEFAULT_END_PORT); + + setPropertyValueIfNotDefault(gatewayReceiverBeanBuilder, MANUAL_START_LITERAL, + enableGatewayReceiverAttributes.getBoolean(MANUAL_START_LITERAL), DEFAULT_MANUAL_START); + + setPropertyValueIfNotDefault(gatewayReceiverBeanBuilder, MAXIMUM_TIME_BETWEEN_PINGS_LITERAL, + enableGatewayReceiverAttributes.getNumber(MAXIMUM_TIME_BETWEEN_PINGS_LITERAL), + DEFAULT_MAXIMUM_TIME_BETWEEN_PINGS); + + setPropertyValueIfNotDefault(gatewayReceiverBeanBuilder, SOCKET_BUFFER_SIZE_LITERAL, + enableGatewayReceiverAttributes.getNumber(SOCKET_BUFFER_SIZE_LITERAL), DEFAULT_SOCKET_BUFFER_SIZE); + + setPropertyValueIfNotDefault(gatewayReceiverBeanBuilder, BIND_ADDRESS_LITERAL, + enableGatewayReceiverAttributes.getString(BIND_ADDRESS_LITERAL), DEFAULT_BIND_ADDRESS); + + setPropertyValueIfNotDefault(gatewayReceiverBeanBuilder, HOSTNAME_FOR_SENDERS_LITERAL, + enableGatewayReceiverAttributes.getString(HOSTNAME_FOR_SENDERS_LITERAL), DEFAULT_HOSTNAME_FOR_SENDERS); + + setPropertyValueIfNotDefault(gatewayReceiverBeanBuilder, TRANSPORT_FILTERS_LITERAL, + resolveTransportBeanReferences(enableGatewayReceiverAttributes.getStringArray(TRANSPORT_FILTERS_LITERAL)), + new ManagedList()); + } + + /** + * Configures GatewayReceiver {@link BeanDefinitionBuilder} using properties, defined under "spring.data.gemfire.gateway.receiver.*" + * + * @param gatewayReceiverBeanBuilder + */ + private void configureBeanBuilderFromPropertiesOrWithDefaultValues( + BeanDefinitionBuilder gatewayReceiverBeanBuilder) { + MutablePropertyValues beanPropertyValues = gatewayReceiverBeanBuilder.getRawBeanDefinition() + .getPropertyValues(); + configureFromProperties(gatewayReceiverBeanBuilder, START_PORT_LITERAL, + (Integer) beanPropertyValues.getPropertyValue(START_PORT_LITERAL).getValue()); + configureFromProperties(gatewayReceiverBeanBuilder, END_PORT_LITERAL, + (Integer) beanPropertyValues.getPropertyValue(END_PORT_LITERAL).getValue()); + configureFromProperties(gatewayReceiverBeanBuilder, MANUAL_START_LITERAL, + (Boolean) beanPropertyValues.getPropertyValue(MANUAL_START_LITERAL).getValue()); + configureFromProperties(gatewayReceiverBeanBuilder, MAXIMUM_TIME_BETWEEN_PINGS_LITERAL, + (Integer) beanPropertyValues.getPropertyValue(MAXIMUM_TIME_BETWEEN_PINGS_LITERAL).getValue()); + configureFromProperties(gatewayReceiverBeanBuilder, SOCKET_BUFFER_SIZE_LITERAL, + (Integer) beanPropertyValues.getPropertyValue(SOCKET_BUFFER_SIZE_LITERAL).getValue()); + configureFromProperties(gatewayReceiverBeanBuilder, BIND_ADDRESS_LITERAL, + (String) beanPropertyValues.getPropertyValue(BIND_ADDRESS_LITERAL).getValue()); + configureFromProperties(gatewayReceiverBeanBuilder, HOSTNAME_FOR_SENDERS_LITERAL, + (String) beanPropertyValues.getPropertyValue(HOSTNAME_FOR_SENDERS_LITERAL).getValue()); + + String[] filters = resolveProperty(gatewayReceiverProperty(TRANSPORT_FILTERS_LITERAL), String[].class); + Optional.ofNullable(filters) + .ifPresent(transportFilters -> + { + ManagedList beanReferences = resolveTransportBeanReferences(transportFilters); + gatewayReceiverBeanBuilder.addPropertyValue(TRANSPORT_FILTERS_LITERAL, beanReferences); + }); + } + + private void configureFromProperties(BeanDefinitionBuilder gatewayReceiverBeanBuilder, String propertyName, + Integer annotatedPropertyValue) { + Integer propertyValue = resolveProperty(gatewayReceiverProperty(propertyName), annotatedPropertyValue); + gatewayReceiverBeanBuilder.addPropertyValue(propertyName, propertyValue); + } + + + private void configureFromProperties(BeanDefinitionBuilder gatewayReceiverBeanBuilder, String propertyName, + String annotatedPropertyValue) { + String propertyValue = resolveProperty(gatewayReceiverProperty(propertyName), annotatedPropertyValue); + gatewayReceiverBeanBuilder.addPropertyValue(propertyName, propertyValue); + } + + private void configureFromProperties(BeanDefinitionBuilder gatewayReceiverBeanBuilder, String propertyName, + Boolean annotatedPropertyValue) { + Boolean propertyValue = resolveProperty(gatewayReceiverProperty(propertyName), annotatedPropertyValue); + gatewayReceiverBeanBuilder.addPropertyValue(propertyName, propertyValue); + } + + private ManagedList resolveTransportBeanReferences(String[] transportFilters) { + ManagedList transportFilterBeanReferences = new ManagedList<>(); + + Optional.ofNullable(transportFilters).ifPresent(transportFilterBeanNames -> + Arrays.stream(transportFilterBeanNames) + .map(RuntimeBeanReference::new) + .forEach(transportFilterBeanReferences::add)); + + return transportFilterBeanReferences; + } + + private void registerGatewayTransportFilterDependencies(AnnotationAttributes annotationAttributes, + BeanDefinitionBuilder gatewayReceiverBeanBuilder) { + String[] transportFilters = (String[]) annotationAttributes.get(TRANSPORT_FILTERS_LITERAL); + Optional.ofNullable(transportFilters).ifPresent( + transportFilerBeanNames -> Arrays.stream(transportFilerBeanNames) + .forEach(gatewayReceiverBeanBuilder::addDependsOn)); + } + + /* (non-Javadoc) */ + private BeanDefinitionBuilder setPropertyValueIfNotDefault(BeanDefinitionBuilder beanDefinitionBuilder, + String propertyName, T value, T defaultValue) { + + return (value != null) ? + beanDefinitionBuilder.addPropertyValue(propertyName, value) + : beanDefinitionBuilder.addPropertyValue(propertyName, defaultValue); + } +} diff --git a/src/main/java/org/springframework/data/gemfire/wan/annotation/EnableGatewayReceiverConfigurer.java b/src/main/java/org/springframework/data/gemfire/wan/annotation/EnableGatewayReceiverConfigurer.java new file mode 100644 index 00000000..7036a2b7 --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/wan/annotation/EnableGatewayReceiverConfigurer.java @@ -0,0 +1,16 @@ +package org.springframework.data.gemfire.wan.annotation; + +import org.springframework.data.gemfire.wan.GatewayReceiverFactoryBean; + +public interface EnableGatewayReceiverConfigurer { + /** + * Configuration callback method providing a reference to a {@link GatewayReceiverFactoryBean} used to construct, + * configure and initialize an instance of {@link org.apache.geode.cache.wan.GatewayReceiver}. + * + * @param beanName name of the {@link org.apache.geode.cache.wan.GatewayReceiver} bean declared in the Spring application context. + * @param bean reference to the {@link GatewayReceiverFactoryBean}. + * @see org.springframework.data.gemfire.wan.GatewayReceiverFactoryBean + * @see org.apache.geode.cache.wan.GatewayReceiver + */ + void configure(String beanName, GatewayReceiverFactoryBean bean); +} diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableEnableGatewayReceiverConfigurerTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableEnableGatewayReceiverConfigurerTests.java new file mode 100644 index 00000000..1b182422 --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableEnableGatewayReceiverConfigurerTests.java @@ -0,0 +1,235 @@ +package org.springframework.data.gemfire.config.annotation; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Arrays; +import java.util.Optional; + +import org.apache.geode.cache.wan.GatewayReceiver; +import org.apache.geode.cache.wan.GatewayTransportFilter; +import org.junit.After; +import org.junit.Test; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertySource; +import org.springframework.data.gemfire.wan.GatewayReceiverFactoryBean; +import org.springframework.data.gemfire.wan.annotation.EnableGatewayReceiver; +import org.springframework.data.gemfire.wan.annotation.EnableGatewayReceiverConfiguration; +import org.springframework.data.gemfire.wan.annotation.EnableGatewayReceiverConfigurer; +import org.springframework.mock.env.MockPropertySource; + +/** + * Tests for {@link org.springframework.data.gemfire.wan.annotation.EnableGatewayReceiver}. + * + * @author Udo Kohlmeyer + * @see org.junit.Test + * @see org.mockito.Mockito + * @see org.apache.geode.cache.server.CacheServer + * @see org.springframework.context.annotation.Configuration + * @see org.springframework.test.context.ContextConfiguration + * @see org.springframework.test.context.junit4.SpringRunner + * @see org.springframework.data.gemfire.wan.GatewayReceiverFactoryBean + * @see EnableGatewayReceiverConfigurer + * @see EnableGatewayReceiverConfiguration + * @since 2.2.0 + */ +public class EnableEnableGatewayReceiverConfigurerTests { + + private ConfigurableApplicationContext applicationContext; + + @After + public void tearDown() { + Optional.ofNullable(this.applicationContext).ifPresent(ConfigurableApplicationContext::close); + } + + private ConfigurableApplicationContext newApplicationContext(PropertySource testPropertySource, + Class... annotatedClasses) { + + AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); + + MutablePropertySources propertySources = applicationContext.getEnvironment().getPropertySources(); + + propertySources.addFirst(testPropertySource); + + applicationContext.registerShutdownHook(); + applicationContext.register(annotatedClasses); + applicationContext.refresh(); + + return applicationContext; + } + + @Test + public void gatewayReceiverConfigurerConfiguration() { + + MockPropertySource testPropertySource = new MockPropertySource(); + + this.applicationContext = newApplicationContext(testPropertySource, + EnableEnableGatewayReceiverConfigurerTests.TestConfigurationWithProperties.class); + + assertThat(this.applicationContext).isNotNull(); + assertThat(this.applicationContext.containsBean("GatewayReceiver")).isTrue(); + GatewayReceiver gatewayReceiver = this.applicationContext.getBean("GatewayReceiver", GatewayReceiver.class); + + assertThat(gatewayReceiver.getStartPort()).isEqualTo(23000); + assertThat(gatewayReceiver.getEndPort()).isEqualTo(25000); + assertThat(gatewayReceiver.getBindAddress()).isEqualTo("127.0.0.1"); + assertThat(gatewayReceiver.getHostnameForSenders()).isEqualTo("testHostNameReceiverForSender"); + assertThat(gatewayReceiver.getMaximumTimeBetweenPings()).isEqualTo(1234567); + assertThat(gatewayReceiver.getSocketBufferSize()).isEqualTo(987654); + assertThat(gatewayReceiver.isManualStart()).isEqualTo(false); + assertThat(gatewayReceiver.getGatewayTransportFilters().size()).isEqualTo(1); + assertThat( + ((TestGatewayTransportFilter) gatewayReceiver.getGatewayTransportFilters().get(0)).name) + .isEqualTo("transportBean1"); + + } + + @Test + public void gatewayReceiverConfigurerWithPropertiesConfiguration() { + + MockPropertySource testPropertySource = new MockPropertySource() + .withProperty("spring.data.gemfire.gateway.receiver.bindAddress", "123.123.123.123") + .withProperty("spring.data.gemfire.gateway.receiver.hostnameForSenders", "testHostName") + .withProperty("spring.data.gemfire.gateway.receiver.startPort", 16000) + .withProperty("spring.data.gemfire.gateway.receiver.endPort", 17000) + .withProperty("spring.data.gemfire.gateway.receiver.maximumTimeBetweenPings", 30000) + .withProperty("spring.data.gemfire.gateway.receiver.socketBufferSize", 32768) + .withProperty("spring.data.gemfire.gateway.receiver.manualStart", true) + .withProperty("spring.data.gemfire.gateway.receiver.transportFilters", "transportBean1,transportBean2"); + + this.applicationContext = newApplicationContext(testPropertySource, + EnableEnableGatewayReceiverConfigurerTests.TestConfigurationWithProperties.class); + + assertThat(this.applicationContext).isNotNull(); + assertThat(this.applicationContext.containsBean("GatewayReceiver")).isTrue(); + GatewayReceiver gatewayReceiver = this.applicationContext.getBean("GatewayReceiver", GatewayReceiver.class); + + assertThat(gatewayReceiver.getStartPort()).isEqualTo(23000); + assertThat(gatewayReceiver.getEndPort()).isEqualTo(25000); + assertThat(gatewayReceiver.getBindAddress()).isEqualTo("127.0.0.1"); + assertThat(gatewayReceiver.getHostnameForSenders()).isEqualTo("testHostNameReceiverForSender"); + assertThat(gatewayReceiver.getMaximumTimeBetweenPings()).isEqualTo(1234567); + assertThat(gatewayReceiver.getSocketBufferSize()).isEqualTo(987654); + assertThat(gatewayReceiver.isManualStart()).isEqualTo(false); + assertThat(gatewayReceiver.getGatewayTransportFilters().size()).isEqualTo(1); + assertThat( + ((TestGatewayTransportFilter) gatewayReceiver.getGatewayTransportFilters().get(0)).name) + .isEqualTo("transportBean1"); + + } + + @Test + public void gatewayReceiverConfigurerWithPropertiesAndAnnotationConfiguration() { + + MockPropertySource testPropertySource = new MockPropertySource() + .withProperty("spring.data.gemfire.gateway.receiver.hostnameForSenders", "testHostName") + .withProperty("spring.data.gemfire.gateway.receiver.maximumTimeBetweenPings", 30000) + .withProperty("spring.data.gemfire.gateway.receiver.socketBufferSize", 32768) + .withProperty("spring.data.gemfire.gateway.receiver.manualStart", true) + .withProperty("spring.data.gemfire.gateway.receiver.transportFilters", "transportBean2,transportBean1"); + + this.applicationContext = newApplicationContext(testPropertySource, + EnableEnableGatewayReceiverConfigurerTests.TestConfiguration.class); + + assertThat(this.applicationContext).isNotNull(); + assertThat(this.applicationContext.containsBean("GatewayReceiver")).isTrue(); + GatewayReceiver gatewayReceiver = this.applicationContext.getBean("GatewayReceiver", GatewayReceiver.class); + + assertThat(gatewayReceiver.getStartPort()).isEqualTo(10000); + assertThat(gatewayReceiver.getEndPort()).isEqualTo(11000); + assertThat(gatewayReceiver.getBindAddress()).isEqualTo("127.0.0.1"); + assertThat(gatewayReceiver.getHostnameForSenders()).isEqualTo("testHostNameReceiverForSender"); + assertThat(gatewayReceiver.getMaximumTimeBetweenPings()).isEqualTo(1234567); + assertThat(gatewayReceiver.getSocketBufferSize()).isEqualTo(32768); + assertThat(gatewayReceiver.isManualStart()).isEqualTo(true); + assertThat(gatewayReceiver.getGatewayTransportFilters().size()).isEqualTo(2); + assertThat( + ((TestGatewayTransportFilter) gatewayReceiver.getGatewayTransportFilters().get(0)).name) + .isEqualTo("transportBean2"); + assertThat( + ((TestGatewayTransportFilter) gatewayReceiver.getGatewayTransportFilters().get(1)).name) + .isEqualTo("transportBean1"); + + } + + @Configuration + @CacheServerApplication + @EnableGatewayReceiver + static class TestConfigurationWithProperties { + + @Bean("transportBean1") + GatewayTransportFilter createGatewayTransportBean1() { + return new EnableEnableGatewayReceiverConfigurerTests.TestGatewayTransportFilter("transportBean1"); + } + + @Bean("transportBean2") + GatewayTransportFilter createGatewayTransportBean2() { + return new EnableEnableGatewayReceiverConfigurerTests.TestGatewayTransportFilter("transportBean2"); + } + + @Bean("gatewayConfigurer") + EnableGatewayReceiverConfigurer gatewayReceiverConfigurer() { + return (String beanName, GatewayReceiverFactoryBean bean) -> { + bean.setBindAddress("127.0.0.1"); + bean.setEndPort(25000); + bean.setStartPort(23000); + bean.setHostnameForSenders("testHostNameReceiverForSender"); + bean.setManualStart(false); + bean.setMaximumTimeBetweenPings(1234567); + bean.setSocketBufferSize(987654); + bean.setTransportFilters(Arrays.asList(createGatewayTransportBean1())); + }; + } + } + + @Configuration + @CacheServerApplication + @EnableGatewayReceiver(manualStart = false, startPort = 10000, endPort = 11000, maximumTimeBetweenPings = 1000, + socketBufferSize = 16384, bindAddress = "localhost",transportFilters = {"transportBean1", "transportBean2"}, + hostnameForSenders = "hostnameLocalhost") + static class TestConfiguration { + + @Bean("transportBean1") + GatewayTransportFilter createGatewayTransportBean1() { + return new EnableEnableGatewayReceiverConfigurerTests.TestGatewayTransportFilter("transportBean1"); + } + + @Bean("transportBean2") + GatewayTransportFilter createGatewayTransportBean2() { + return new EnableEnableGatewayReceiverConfigurerTests.TestGatewayTransportFilter("transportBean2"); + } + + @Bean("gatewayConfigurer") + EnableGatewayReceiverConfigurer gatewayReceiverConfigurer() { + return (String beanName, GatewayReceiverFactoryBean bean) -> { + bean.setBindAddress("127.0.0.1"); + bean.setHostnameForSenders("testHostNameReceiverForSender"); + bean.setMaximumTimeBetweenPings(1234567); + }; + } + } + + private static class TestGatewayTransportFilter implements GatewayTransportFilter { + + private String name; + + public TestGatewayTransportFilter(String name) { + this.name = name; + } + + @Override + public InputStream getInputStream(InputStream inputStream) { + return null; + } + + @Override + public OutputStream getOutputStream(OutputStream outputStream) { + return null; + } + } +} diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableGatewayReceiverConfigurationTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableGatewayReceiverConfigurationTests.java new file mode 100644 index 00000000..e5f3a9be --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableGatewayReceiverConfigurationTests.java @@ -0,0 +1,179 @@ +package org.springframework.data.gemfire.config.annotation; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.geode.cache.wan.GatewayReceiver; +import org.apache.geode.cache.wan.GatewayTransportFilter; +import org.junit.After; +import org.junit.Test; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.data.gemfire.wan.GatewayReceiverFactoryBean; +import org.springframework.data.gemfire.wan.annotation.EnableGatewayReceiver; +import org.springframework.data.gemfire.wan.annotation.EnableGatewayReceiverConfiguration; +import org.springframework.data.gemfire.wan.annotation.EnableGatewayReceiverConfigurer; + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.*; + +/** + * Tests for {@link org.springframework.data.gemfire.wan.annotation.EnableGatewayReceiver}. + * + * @author Udo Kohlmeyer + * @see org.junit.Test + * @see org.mockito.Mockito + * @see org.apache.geode.cache.server.CacheServer + * @see org.springframework.context.annotation.Configuration + * @see org.springframework.test.context.ContextConfiguration + * @see org.springframework.test.context.junit4.SpringRunner + * @see org.springframework.data.gemfire.wan.GatewayReceiverFactoryBean + * @see EnableGatewayReceiverConfigurer + * @see EnableGatewayReceiverConfiguration + * @since 2.2.0 + */ +public class EnableGatewayReceiverConfigurationTests { + + private ConfigurableApplicationContext applicationContext; + + @After + public void shutdown() + { + Optional.ofNullable(this.applicationContext).ifPresent(ConfigurableApplicationContext::close); + } + + @Configuration + @CacheServerApplication + @EnableGatewayReceiver(manualStart = false, startPort = 10000, endPort = 11000, maximumTimeBetweenPings = 1000, + socketBufferSize = 16384, bindAddress = "localhost",transportFilters = {"transportBean1", "transportBean2"}, + hostnameForSenders = "hostnameLocalhost") + static class TestConfigurationWithOrder { + + @Bean("transportBean1") + @Order(1) + GatewayTransportFilter createGatewayTransportBean1() { + return new TestGatewayTransportFilter("transportBean1"); + } + + @Bean("transportBean2") + @Order(2) + GatewayTransportFilter createGatewayTransportBean2() { + return new TestGatewayTransportFilter("transportBean2"); + } + + @Bean("gatewayConfigurer") + EnableGatewayReceiverConfigurer gatewayReceiverConfigurer() { + return new TestGatewayReceiverConfigurer(); + } + } + + @Configuration + @CacheServerApplication + @EnableGatewayReceiver(manualStart = false, startPort = 12000, endPort = 13000, maximumTimeBetweenPings = 5000, + socketBufferSize = 32768, transportFilters = {"transportBean1", "transportBean2"}, bindAddress = "localhost", + hostnameForSenders = "hostnameLocalhost") + static class TestConfigurationFromAnnotation { + + @Bean("transportBean1") + GatewayTransportFilter createGatewayTransportBean1() { + return new TestGatewayTransportFilter("transportBean1"); + } + + @Bean("transportBean2") + GatewayTransportFilter createGatewayTransportBean2() { + return new TestGatewayTransportFilter("transportBean2"); + } + + @Bean("gatewayConfigurer") + EnableGatewayReceiverConfigurer gatewayReceiverConfigurer() { + return new TestGatewayReceiverConfigurer(); + } + } + + @Test + public void annotationConfiguredGatewayTransportFiltersOrdered() { + this.applicationContext = newApplicationContext(TestConfigurationFromAnnotation.class); + TestGatewayReceiverConfigurer gatewayReceiverConfigurer = (TestGatewayReceiverConfigurer) this.applicationContext.getBean( + EnableGatewayReceiverConfigurer.class); + + GatewayReceiver gatewayReceiver = this.applicationContext.getBean("GatewayReceiver",GatewayReceiver.class); + + assertThat(gatewayReceiver.getStartPort()).isEqualTo(12000); + assertThat(gatewayReceiver.getEndPort()).isEqualTo(13000); + assertThat(gatewayReceiver.getBindAddress()).isEqualTo("localhost"); + assertThat(gatewayReceiver.getHostnameForSenders()).isEqualTo("hostnameLocalhost"); + assertThat(gatewayReceiver.getMaximumTimeBetweenPings()).isEqualTo(5000); + assertThat(gatewayReceiver.getSocketBufferSize()).isEqualTo(32768); + assertThat(gatewayReceiver.isManualStart()).isEqualTo(false); + assertThat(gatewayReceiver.getGatewayTransportFilters().size()).isEqualTo(2); + assertThat(((EnableGatewayReceiverConfigurationTests.TestGatewayTransportFilter)gatewayReceiver.getGatewayTransportFilters().get(0)).name).isEqualTo("transportBean1"); + assertThat(((EnableGatewayReceiverConfigurationTests.TestGatewayTransportFilter)gatewayReceiver.getGatewayTransportFilters().get(1)).name).isEqualTo("transportBean2"); + assertThat(gatewayReceiverConfigurer.beanNames.toArray()).isEqualTo(new String[]{"transportBean1", "transportBean2"}); + } + + @Test + public void beanConfiguredGatewayTransportFiltersOrdered() { + this.applicationContext = newApplicationContext(TestConfigurationWithOrder.class); + TestGatewayReceiverConfigurer gatewayReceiverConfigurer = (TestGatewayReceiverConfigurer) this.applicationContext.getBean( + EnableGatewayReceiverConfigurer.class); + + GatewayReceiver gatewayReceiver = this.applicationContext.getBean("GatewayReceiver",GatewayReceiver.class); + + assertThat(gatewayReceiver.getStartPort()).isEqualTo(10000); + assertThat(gatewayReceiver.getEndPort()).isEqualTo(11000); + assertThat(gatewayReceiver.getBindAddress()).isEqualTo("localhost"); + assertThat(gatewayReceiver.getHostnameForSenders()).isEqualTo("hostnameLocalhost"); + assertThat(gatewayReceiver.getMaximumTimeBetweenPings()).isEqualTo(1000); + assertThat(gatewayReceiver.getSocketBufferSize()).isEqualTo(16384); + assertThat(gatewayReceiver.isManualStart()).isEqualTo(false); + assertThat(gatewayReceiver.getGatewayTransportFilters().size()).isEqualTo(2); + assertThat(((EnableGatewayReceiverConfigurationTests.TestGatewayTransportFilter)gatewayReceiver.getGatewayTransportFilters().get(0)).name).isEqualTo("transportBean1"); + assertThat(((EnableGatewayReceiverConfigurationTests.TestGatewayTransportFilter)gatewayReceiver.getGatewayTransportFilters().get(1)).name).isEqualTo("transportBean2"); + assertThat(gatewayReceiverConfigurer.beanNames.toArray()).isEqualTo(new String[]{"transportBean1", "transportBean2"}); + } + + private static class TestGatewayReceiverConfigurer implements EnableGatewayReceiverConfigurer, Iterable { + + private final List beanNames = new ArrayList<>(); + + @Override + public Iterator iterator() { + return Collections.unmodifiableList(this.beanNames).iterator(); + } + + @Override + public void configure(String beanName, GatewayReceiverFactoryBean bean) { + bean.getTransportFilters().stream().forEach(o -> beanNames.add(((TestGatewayTransportFilter) o).name)); + } + } + + private static class TestGatewayTransportFilter implements GatewayTransportFilter { + private String name; + + public TestGatewayTransportFilter(String name) { + this.name = name; + } + + @Override + public InputStream getInputStream(InputStream inputStream) { + return null; + } + + @Override + public OutputStream getOutputStream(OutputStream outputStream) { + return null; + } + } + + private ConfigurableApplicationContext newApplicationContext(Class... annotatedClasses) { + + ConfigurableApplicationContext applicationContext = new AnnotationConfigApplicationContext(annotatedClasses); + + applicationContext.registerShutdownHook(); + + return applicationContext; + } +} diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/EnableGatewayReceiverPropertiesTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableGatewayReceiverPropertiesTests.java new file mode 100644 index 00000000..88d8af20 --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/EnableGatewayReceiverPropertiesTests.java @@ -0,0 +1,154 @@ +package org.springframework.data.gemfire.config.annotation; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; + +import org.apache.geode.cache.wan.GatewayReceiver; +import org.apache.geode.cache.wan.GatewayTransportFilter; +import org.junit.After; +import org.junit.Test; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertySource; +import org.springframework.data.gemfire.wan.GatewayReceiverFactoryBean; +import org.springframework.data.gemfire.wan.annotation.EnableGatewayReceiver; +import org.springframework.data.gemfire.wan.annotation.EnableGatewayReceiverConfiguration; +import org.springframework.data.gemfire.wan.annotation.EnableGatewayReceiverConfigurer; +import org.springframework.mock.env.MockPropertySource; + +/** + * Tests for {@link org.springframework.data.gemfire.wan.annotation.EnableGatewayReceiver}. + * + * @author Udo Kohlmeyer + * @see org.junit.Test + * @see org.mockito.Mockito + * @see org.apache.geode.cache.server.CacheServer + * @see org.springframework.context.annotation.Configuration + * @see org.springframework.test.context.ContextConfiguration + * @see org.springframework.test.context.junit4.SpringRunner + * @see org.springframework.data.gemfire.wan.GatewayReceiverFactoryBean + * @see EnableGatewayReceiverConfigurer + * @see EnableGatewayReceiverConfiguration + * @since 2.2.0 + */ +public class EnableGatewayReceiverPropertiesTests { + + private ConfigurableApplicationContext applicationContext; + + @After + public void tearDown() { + Optional.ofNullable(this.applicationContext).ifPresent(ConfigurableApplicationContext::close); + } + + private ConfigurableApplicationContext newApplicationContext(PropertySource testPropertySource, + Class... annotatedClasses) { + + AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); + + MutablePropertySources propertySources = applicationContext.getEnvironment().getPropertySources(); + + propertySources.addFirst(testPropertySource); + + applicationContext.registerShutdownHook(); + applicationContext.register(annotatedClasses); + applicationContext.refresh(); + + return applicationContext; + } + + @Test + public void gatewayReceiverPropertiesConfiguration() { + + MockPropertySource testPropertySource = new MockPropertySource() + .withProperty("spring.data.gemfire.gateway.receiver.bindAddress", "123.123.123.123") + .withProperty("spring.data.gemfire.gateway.receiver.hostnameForSenders", "testHostName") + .withProperty("spring.data.gemfire.gateway.receiver.startPort", 16000) + .withProperty("spring.data.gemfire.gateway.receiver.endPort", 17000) + .withProperty("spring.data.gemfire.gateway.receiver.maximumTimeBetweenPings", 30000) + .withProperty("spring.data.gemfire.gateway.receiver.socketBufferSize", 32768) + .withProperty("spring.data.gemfire.gateway.receiver.manualStart", true) + .withProperty("spring.data.gemfire.gateway.receiver.transportFilters", "transportBean2,transportBean1"); + + this.applicationContext = newApplicationContext(testPropertySource, EnableGatewayReceiverPropertiesTests.TestConfigurationWithProperties.class); + + assertThat(this.applicationContext).isNotNull(); + assertThat(this.applicationContext.containsBean("GatewayReceiver")).isTrue(); + GatewayReceiver gatewayReceiver = this.applicationContext.getBean("GatewayReceiver",GatewayReceiver.class); + + assertThat(gatewayReceiver.getStartPort()).isEqualTo(16000); + assertThat(gatewayReceiver.getEndPort()).isEqualTo(17000); + assertThat(gatewayReceiver.getBindAddress()).isEqualTo("123.123.123.123"); + assertThat(gatewayReceiver.getHostnameForSenders()).isEqualTo("testHostName"); + assertThat(gatewayReceiver.getMaximumTimeBetweenPings()).isEqualTo(30000); + assertThat(gatewayReceiver.getSocketBufferSize()).isEqualTo(32768); + assertThat(gatewayReceiver.isManualStart()).isEqualTo(true); + assertThat(gatewayReceiver.getGatewayTransportFilters().size()).isEqualTo(2); + assertThat(((TestGatewayTransportFilter)gatewayReceiver.getGatewayTransportFilters().get(0)).name).isEqualTo("transportBean2"); + assertThat(((TestGatewayTransportFilter)gatewayReceiver.getGatewayTransportFilters().get(1)).name).isEqualTo("transportBean1"); + + } + + @Configuration + @CacheServerApplication + @EnableGatewayReceiver + static class TestConfigurationWithProperties{ + + @Bean("transportBean1") + GatewayTransportFilter createGatewayTransportBean1() { + return new EnableGatewayReceiverPropertiesTests.TestGatewayTransportFilter("transportBean1"); + } + + @Bean("transportBean2") + GatewayTransportFilter createGatewayTransportBean2() { + return new EnableGatewayReceiverPropertiesTests.TestGatewayTransportFilter("transportBean2"); + } + + @Bean("gatewayConfigurer") + EnableGatewayReceiverConfigurer gatewayReceiverConfigurer() { + return new EnableGatewayReceiverPropertiesTests.TestGatewayReceiverConfigurer(); + } + } + + private static class TestGatewayTransportFilter implements GatewayTransportFilter { + private String name; + + public TestGatewayTransportFilter(String name) { + this.name = name; + } + + @Override + public InputStream getInputStream(InputStream inputStream) { + return null; + } + + @Override + public OutputStream getOutputStream(OutputStream outputStream) { + return null; + } + } + + private static class TestGatewayReceiverConfigurer implements EnableGatewayReceiverConfigurer, Iterable { + + private final List beanNames = new ArrayList<>(); + + @Override + public Iterator iterator() { + return Collections.unmodifiableList(this.beanNames).iterator(); + } + + @Override + public void configure(String beanName, GatewayReceiverFactoryBean bean) { + bean.getTransportFilters().stream().forEach(o -> beanNames.add(((EnableGatewayReceiverPropertiesTests.TestGatewayTransportFilter) o).name)); + } + } +}