From 8292104d20025297282562038b5fa4d8b297ed80 Mon Sep 17 00:00:00 2001 From: wanger26 Date: Sat, 10 Feb 2024 14:51:55 -0500 Subject: [PATCH 1/2] Resolve property placeholders when binding properties to a Map Add call to placeholder resolver to ensure property placeholders are resolved for the `MapBinder` See gh-39507 Signed-off-by: wanger26 --- .../boot/context/properties/bind/MapBinder.java | 5 ++++- .../context/properties/bind/MapBinderTests.java | 13 +++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) 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 1329c7a043a..c33b2ae92e7 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 @@ -62,7 +62,10 @@ class MapBinder extends AggregateBinder> { ConfigurationProperty property = source.getConfigurationProperty(name); if (property != null && !hasDescendants) { getContext().setConfigurationProperty(property); - return getContext().getConverter().convert(property.getValue(), target); + Object result = property.getValue(); + result = getContext().getPlaceholdersResolver().resolvePlaceholders(result); + result = getContext().getConverter().convert(result, target); + return result; } source = source.filter(name::isAncestorOf); } 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 cb03bcebc45..1bbcebf94e1 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 @@ -610,6 +610,19 @@ class MapBinderTests { .containsExactly("127.0.0.1", "127.0.0.2"); } + @Test + void bindToMapWithPlaceholdersShouldResolve() { + DefaultConversionService conversionService = new DefaultConversionService(); + conversionService.addConverter(new MapConverter()); + StandardEnvironment environment = new StandardEnvironment(); + Binder binder = new Binder(this.sources, new PropertySourcesPlaceholdersResolver(environment), conversionService, null, null); + TestPropertySourceUtils.addInlinedPropertiesToEnvironment(environment, "bar=bc"); + this.sources.add(new MockConfigurationPropertySource("foo", "a${bar},${bar}d")); + Map map = binder.bind("foo", STRING_STRING_MAP).get(); + assertThat(map).containsKey("abc"); + assertThat(map).containsKey("bcd"); + } + private Bindable> getMapBindable(Class keyGeneric, ResolvableType valueType) { ResolvableType keyType = ResolvableType.forClass(keyGeneric); return Bindable.of(ResolvableType.forClassWithGenerics(Map.class, keyType, valueType)); From f90f29dd12020d9643da87587242e7086902cba4 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Sun, 11 Feb 2024 15:05:48 -0600 Subject: [PATCH 2/2] Polish "Resolve property placeholders when binding properties to a Map" See gh-39507 --- .../boot/context/properties/bind/MapBinder.java | 5 ++--- .../boot/context/properties/bind/MapBinderTests.java | 5 +++-- 2 files changed, 5 insertions(+), 5 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 c33b2ae92e7..57e6234ee75 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -64,8 +64,7 @@ class MapBinder extends AggregateBinder> { getContext().setConfigurationProperty(property); Object result = property.getValue(); result = getContext().getPlaceholdersResolver().resolvePlaceholders(result); - result = getContext().getConverter().convert(result, target); - return result; + return getContext().getConverter().convert(result, target); } source = source.filter(name::isAncestorOf); } 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 1bbcebf94e1..1a4306298f6 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -615,7 +615,8 @@ class MapBinderTests { DefaultConversionService conversionService = new DefaultConversionService(); conversionService.addConverter(new MapConverter()); StandardEnvironment environment = new StandardEnvironment(); - Binder binder = new Binder(this.sources, new PropertySourcesPlaceholdersResolver(environment), conversionService, null, null); + Binder binder = new Binder(this.sources, new PropertySourcesPlaceholdersResolver(environment), + conversionService, null, null); TestPropertySourceUtils.addInlinedPropertiesToEnvironment(environment, "bar=bc"); this.sources.add(new MockConfigurationPropertySource("foo", "a${bar},${bar}d")); Map map = binder.bind("foo", STRING_STRING_MAP).get();