From 8ce13c765beb8865311f98192473cc2231d8b79b Mon Sep 17 00:00:00 2001 From: Madhura Bhave Date: Fri, 1 Jun 2018 14:34:16 -0700 Subject: [PATCH] Support binding to immutable maps Closes gh-13323 --- .../context/properties/bind/MapBinder.java | 22 ++++++++++++++----- .../properties/bind/MapBinderTests.java | 16 ++++++++++++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java index 7efdf055b4..7cb92a141d 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java @@ -90,22 +90,32 @@ class MapBinder extends AggregateBinder> { if (existingMap == null) { return additional; } - existingMap.putAll(additional); - return copyIfPossible(existingMap); + try { + existingMap.putAll(additional); + return copyIfPossible(existingMap); + } + catch (UnsupportedOperationException ex) { + Map result = createNewMap(additional.getClass(), existingMap); + result.putAll(additional); + return result; + } } private Map copyIfPossible(Map map) { try { - Map result = CollectionFactory.createMap(map.getClass(), - map.size()); - result.putAll(map); - return result; + return createNewMap(map.getClass(), map); } catch (Exception ex) { return map; } } + private Map createNewMap(Class mapClass, Map map) { + Map result = CollectionFactory.createMap(mapClass, map.size()); + result.putAll(map); + return result; + } + private class EntryBinder { private final ConfigurationPropertyName root; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java index 5920a31b3d..e75493c024 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java @@ -615,6 +615,22 @@ public class MapBinderTests { assertThat(result.getItems()).containsExactly(entry("a", "b")); } + @Test + public void bindToImmutableMapShouldReturnPopulatedCollection() { + MockConfigurationPropertySource source = new MockConfigurationPropertySource(); + source.put("foo.values.c", "d"); + source.put("foo.values.e", "f"); + this.sources.add(source); + Map result = this.binder + .bind("foo.values", + STRING_STRING_MAP + .withExistingValue(Collections.singletonMap("a", "b"))) + .get(); + assertThat(result).hasSize(3); + assertThat(result.entrySet()).containsExactly(entry("a", "b"), entry("c", "d"), + entry("e", "f")); + } + private Bindable> getMapBindable(Class keyGeneric, ResolvableType valueType) { ResolvableType keyType = ResolvableType.forClass(keyGeneric);