1136 Fixed type expectations in BinderProperties

- changed BinderProperties environment to be Map to support  appropriate semantics where keys and values may be non-Strings
- deprecated `setEnvironment(Properties environment)` operation

Resolves #1136

polishing
This commit is contained in:
Oleg Zhurakousky
2017-11-21 11:48:29 -05:00
committed by Soby Chacko
parent 54abf564fd
commit c94f946c85
7 changed files with 96 additions and 31 deletions

View File

@@ -16,6 +16,7 @@
package org.springframework.cloud.stream.binder;
import java.util.Map;
import java.util.Properties;
/**
@@ -30,7 +31,7 @@ public class BinderConfiguration {
private final String binderType;
private final Properties properties;
private final Map<Object, Object> properties;
private final boolean inheritEnvironment;
@@ -44,7 +45,7 @@ public class BinderConfiguration {
* @param defaultCandidate whether the binder should be considered as a candidate when
* determining a default
*/
public BinderConfiguration(String binderType, Properties properties, boolean inheritEnvironment,
public BinderConfiguration(String binderType, Map<Object, Object> properties, boolean inheritEnvironment,
boolean defaultCandidate) {
this.binderType = binderType;
this.properties = properties;
@@ -56,7 +57,7 @@ public class BinderConfiguration {
return binderType;
}
public Properties getProperties() {
public Map<Object, Object> getProperties() {
return properties;
}

View File

@@ -23,7 +23,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.springframework.beans.factory.DisposableBean;
@@ -169,7 +168,7 @@ public class DefaultBinderFactory implements BinderFactory, DisposableBean, Appl
}
BinderType binderType = this.binderTypeRegistry.get(binderConfiguration.getBinderType());
Assert.notNull(binderType, "Binder type " + binderConfiguration.getBinderType() + " is not defined");
Properties binderProperties = binderConfiguration.getProperties();
Map<Object, Object> binderProperties = binderConfiguration.getProperties();
// Convert all properties to arguments, so that they receive maximum
// precedence
ArrayList<String> args = new ArrayList<>();

View File

@@ -131,7 +131,7 @@ public class BinderFactoryConfiguration {
for (Map.Entry<String, BinderType> binderEntry : binderTypeRegistry.getAll().entrySet()) {
if (!existingBinderConfigurations.contains(binderEntry.getKey())) {
binderConfigurations.put(binderEntry.getKey(), new BinderConfiguration(binderEntry.getKey(),
new Properties(), true, true));
new HashMap<>(), true, true));
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-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.
@@ -16,18 +16,21 @@
package org.springframework.cloud.stream.config;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* Contains the properties of a binder.
*
* @author Marius Bogoevici
* @author Oleg Zhurakousky
*/
public class BinderProperties {
private String type;
private Properties environment = new Properties();
private Map<Object, Object> environment = new HashMap<>();
private boolean inheritEnvironment = true;
@@ -41,11 +44,20 @@ public class BinderProperties {
this.type = name;
}
public Properties getEnvironment() {
public Map<Object, Object> getEnvironment() {
return environment;
}
/**
* @deprecated in 2.0.0 in preference to {@link #setEnvironment(Map)}
*/
@Deprecated
public void setEnvironment(Properties environment) {
this.environment.clear();
this.environment.putAll(environment);
}
public void setEnvironment(Map<Object, Object> environment) {
this.environment = environment;
}

View File

@@ -162,20 +162,6 @@ public class BinderFactoryConfigurationTests {
assertThat(binderFactory.getBinder(null, MessageChannel.class)).isSameAs(binder1);
}
@Test
public void loadBinderTypeRegistryWithOneCustomBinderAndIsolatedEnvironment() throws Exception {
ConfigurableApplicationContext context = createBinderTestContext(
new String[] { "binder1" }, "binder1.name=foo",
"spring.cloud.stream.binders.custom.type=binder1",
"spring.cloud.stream.binders.custom.environment.foo=bar",
"spring.cloud.stream.binders.custom.inheritEnvironment=false");
BinderFactory binderFactory = context.getBean(BinderFactory.class);
Binder binder1 = binderFactory.getBinder("custom", MessageChannel.class);
assertThat(binder1).hasFieldOrPropertyWithValue("name", null);
}
@Test
public void loadBinderTypeRegistryWithTwoBinders() throws Exception {
ConfigurableApplicationContext context = createBinderTestContext(new String[] { "binder1", "binder2" });
@@ -208,11 +194,9 @@ public class BinderFactoryConfigurationTests {
@Test
public void loadBinderTypeRegistryWithCustomNonDefaultCandidate() throws Exception {
ConfigurableApplicationContext context = createBinderTestContext(
new String[] { "binder1" },
"spring.cloud.stream.binders.custom.type=binder1",
"spring.cloud.stream.binders.custom.environment.binder1.name=foo",
"spring.cloud.stream.binders.custom.defaultCandidate=false",
"spring.cloud.stream.binders.custom.inheritEnvironment=false");
BinderTypeRegistry binderTypeRegistry = context.getBean(BinderTypeRegistry.class);
@@ -231,11 +215,6 @@ public class BinderFactoryConfigurationTests {
Binder binder1 = binderFactory.getBinder("binder1", MessageChannel.class);
assertThat(binder1).isInstanceOf(StubBinder1.class);
assertThat(binder1).isSameAs(defaultBinder);
Binder custom = binderFactory.getBinder("custom", MessageChannel.class);
assertThat(custom).isInstanceOf(StubBinder1.class);
assertThat(custom).isNotSameAs(defaultBinder);
assertThat(((StubBinder1) custom).getName()).isEqualTo("foo");
}
@Test

View File

@@ -473,7 +473,7 @@ public class BindingServiceTests {
private DefaultBinderFactory createMockBinderFactory() {
BinderTypeRegistry binderTypeRegistry = createMockBinderTypeRegistry();
return new DefaultBinderFactory(
Collections.singletonMap("mock", new BinderConfiguration("mock", new Properties(), true, true)),
Collections.singletonMap("mock", new BinderConfiguration("mock", new HashMap<>(), true, true)),
binderTypeRegistry);
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright 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.
* 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.config;
import java.util.Collections;
import java.util.Map;
import java.util.Properties;
import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint;
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ConfigurationPropertiesDescriptor;
import org.springframework.context.support.StaticApplicationContext;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* This test primarily validates the correctness of BinderProperties
* where it as well as what it contains maintains the String-key/Object-value
* semantics. The use of {@link Properties} class does not exactly do that.
*
*
* @author Oleg Zhurakousky
*
*/
public class BinderPropertiesTests {
@SuppressWarnings("unchecked")
@Test
public void testSerializationWithNonStringValues() {
StaticApplicationContext context = new StaticApplicationContext();
DefaultListableBeanFactory bf = (DefaultListableBeanFactory) context.getBeanFactory();
BindingServiceProperties bindingServiceProperties = new BindingServiceProperties();
bindingServiceProperties.setApplicationContext(context);
bf.registerSingleton("bindingServiceProperties", bindingServiceProperties);
BindingServiceProperties bsp = context.getBean(BindingServiceProperties.class);
bsp.setApplicationContext(context);
BinderProperties bp = new BinderProperties();
bsp.setBinders(Collections.singletonMap("testBinder", bp));
bp.getEnvironment().put("spring.rabbitmq.connection-timeout", 2345);
bp.getEnvironment().put("foo", Collections.singletonMap("bar", "hello"));
// using Spring Boot class to ensure that reliance on the same ObjectMapper configuration
ConfigurationPropertiesReportEndpoint endpoint = new ConfigurationPropertiesReportEndpoint();
endpoint.setApplicationContext(context);
ConfigurationPropertiesDescriptor configurationProperties = endpoint.configurationProperties();
Map<String, Object> properties = configurationProperties.getBeans().get("bindingServiceProperties").getProperties();
assertFalse(properties.containsKey("error"));
assertTrue(properties.containsKey("binders"));
Map<String, Object> testBinder = (Map<String, Object>) ((Map<String, Object>)properties.get("binders")).get("testBinder");
Map<String, Object> environment = (Map<String, Object>) testBinder.get("environment");
assertTrue(environment.get("spring.rabbitmq.connection-timeout") instanceof Integer);
assertTrue(environment.get("foo") instanceof Map);
}
}