From b7f7e3ba3e4ae1312909b78147da5b133ba0ba7d Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Mon, 5 Mar 2018 14:42:34 -0500 Subject: [PATCH] GH-1273 Added map flattening for binder configuration properties - this ensures that properties are passed to child AC in an appropriate format (i.e., --foo.bar.baz=goo) - changed BinderProperties.environment to be a Map Resolves #1273 Resolves #1276 polish --- .../stream/binder/BinderConfiguration.java | 9 ++++---- .../stream/binder/DefaultBinderFactory.java | 21 +++++++++++++++++-- .../cloud/stream/config/BinderProperties.java | 9 ++++---- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/BinderConfiguration.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/BinderConfiguration.java index 2153bbc6e..5d31d578f 100644 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/BinderConfiguration.java +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/BinderConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2016 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. @@ -26,12 +26,13 @@ import java.util.Properties; * systems of the same type. * * @author Marius Bogoevici + * @author Oleg Zhurakousky */ public class BinderConfiguration { private final String binderType; - private final Map properties; + private final Map properties; private final boolean inheritEnvironment; @@ -45,7 +46,7 @@ public class BinderConfiguration { * @param defaultCandidate whether the binder should be considered as a candidate when * determining a default */ - public BinderConfiguration(String binderType, Map properties, boolean inheritEnvironment, + public BinderConfiguration(String binderType, Map properties, boolean inheritEnvironment, boolean defaultCandidate) { this.binderType = binderType; this.properties = properties; @@ -57,7 +58,7 @@ public class BinderConfiguration { return binderType; } - public Map getProperties() { + public Map getProperties() { return properties; } diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/DefaultBinderFactory.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/DefaultBinderFactory.java index add17fe17..950706eac 100644 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/DefaultBinderFactory.java +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binder/DefaultBinderFactory.java @@ -165,11 +165,14 @@ public class DefaultBinderFactory implements BinderFactory, DisposableBean, Appl Assert.state(binderConfiguration != null, "Unknown binder configuration: " + configurationName); BinderType binderType = this.binderTypeRegistry.get(binderConfiguration.getBinderType()); Assert.notNull(binderType, "Binder type " + binderConfiguration.getBinderType() + " is not defined"); - Map binderProperties = binderConfiguration.getProperties(); + + Map binderProperties = new HashMap<>(); + this.flatten(null, binderConfiguration.getProperties(), binderProperties); + // Convert all properties to arguments, so that they receive maximum // precedence ArrayList args = new ArrayList<>(); - for (Map.Entry property : binderProperties.entrySet()) { + for (Map.Entry property : binderProperties.entrySet()) { args.add(String.format("--%s=%s", property.getKey(), property.getValue())); } // Initialize the domain with a unique name based on the bootstrapping context @@ -211,6 +214,20 @@ public class DefaultBinderFactory implements BinderFactory, DisposableBean, Appl } return (Binder) this.binderInstanceCache.get(configurationName).getKey(); } + + /** + * Ensures that nested properties are flattened (i.e., foo.bar=baz instead of foo={bar=baz}) + */ + @SuppressWarnings("unchecked") + private void flatten(String propertyName, Object value, Map flattenedProperties) { + if (value instanceof Map) { + ((Map) value) + .forEach((k, v) -> flatten((propertyName != null ? propertyName + "." : "") + k, v, flattenedProperties)); + } + else { + flattenedProperties.put(propertyName, value.toString()); + } + } /** * A listener that can be registered with the {@link DefaultBinderFactory} that allows diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BinderProperties.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BinderProperties.java index d6f778da8..479e94719 100644 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BinderProperties.java +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BinderProperties.java @@ -19,6 +19,7 @@ package org.springframework.cloud.stream.config; import java.util.HashMap; import java.util.Map; import java.util.Properties; +import java.util.stream.Collectors; /** * Contains the properties of a binder. @@ -38,7 +39,7 @@ public class BinderProperties { /** * Root for a set of properties that can be used to customize the environment of the binder. */ - private Map environment = new HashMap<>(); + private Map environment = new HashMap<>(); /** * Whether the configuration will inherit the environment of the application itself. Default: true @@ -59,7 +60,7 @@ public class BinderProperties { this.type = name; } - public Map getEnvironment() { + public Map getEnvironment() { return environment; } @@ -69,10 +70,10 @@ public class BinderProperties { @Deprecated public void setEnvironment(Properties environment) { this.environment.clear(); - this.environment.putAll(environment); + this.environment.putAll(environment.entrySet().stream().collect(Collectors.toMap(e -> e.getKey().toString(), e -> e.getValue()))); } - public void setEnvironment(Map environment) { + public void setEnvironment(Map environment) { this.environment = environment; }