From 1d5549ff0171ff6ee0b574d94f615910865c342c Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Wed, 13 Jul 2016 15:27:01 -0700 Subject: [PATCH] Merge complex types from multiple source correctly Update PropertySourcesPropertyValues so that source detection logic for collection values also considers complex types. Prior to this commit properties of the following form were processed correctly: PropertySource-A list[0]=x PropertySource-B list[0]=y list[1]=z But properties of the form were not: PropertySource-A list[0].name=x PropertySource-B list[0].name=y list[1].name=z Fixes gh-4313 See gh-2611 --- .../bind/PropertySourcesPropertyValues.java | 3 +- .../PropertySourcesPropertyValuesTests.java | 48 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/PropertySourcesPropertyValues.java b/spring-boot/src/main/java/org/springframework/boot/bind/PropertySourcesPropertyValues.java index ec660bf713..132ba8bd2d 100644 --- a/spring-boot/src/main/java/org/springframework/boot/bind/PropertySourcesPropertyValues.java +++ b/spring-boot/src/main/java/org/springframework/boot/bind/PropertySourcesPropertyValues.java @@ -43,7 +43,8 @@ import org.springframework.validation.DataBinder; */ public class PropertySourcesPropertyValues implements PropertyValues { - private static final Pattern COLLECTION_PROPERTY = Pattern.compile("\\[(\\d+)\\]"); + private static final Pattern COLLECTION_PROPERTY = Pattern + .compile("\\[(\\d+)\\](\\.\\S+)?"); private final PropertySources propertySources; diff --git a/spring-boot/src/test/java/org/springframework/boot/bind/PropertySourcesPropertyValuesTests.java b/spring-boot/src/test/java/org/springframework/boot/bind/PropertySourcesPropertyValuesTests.java index 9cbac1d4ff..c84e12115b 100644 --- a/spring-boot/src/test/java/org/springframework/boot/bind/PropertySourcesPropertyValuesTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/bind/PropertySourcesPropertyValuesTests.java @@ -40,6 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author Dave Syer * @author Phillip Webb + * @author Stephane Nicoll */ public class PropertySourcesPropertyValuesTests { @@ -222,10 +223,33 @@ public class PropertySourcesPropertyValuesTests { assertThat(target.getList()).containsExactly("f0"); } + @Test + public void testFirstCollectionPropertyWinsNestedAttributes() throws Exception { + ListTestBean target = new ListTestBean(); + DataBinder binder = new DataBinder(target); + Map first = new LinkedHashMap(); + first.put("list[0].description", "another description"); + Map second = new LinkedHashMap(); + second.put("list[0].name", "first name"); + second.put("list[0].description", "first description"); + second.put("list[1].name", "second name"); + second.put("list[1].description", "second description"); + this.propertySources.addFirst(new MapPropertySource("s", second)); + this.propertySources.addFirst(new MapPropertySource("f", first)); + binder.bind(new PropertySourcesPropertyValues(this.propertySources)); + target.getList(); + assertThat(target.getList()).hasSize(1); + assertThat(target.getList().get(0).getDescription()) + .isEqualTo("another description"); + assertThat(target.getList().get(0).getName()).isNull(); + } + public static class TestBean { private String name; + private String description; + public String getName() { return this.name; } @@ -233,6 +257,15 @@ public class PropertySourcesPropertyValuesTests { public void setName(String name) { this.name = name; } + + public String getDescription() { + return this.description; + } + + public void setDescription(String description) { + this.description = description; + } + } public static class FooBean { @@ -260,6 +293,21 @@ public class PropertySourcesPropertyValuesTests { public void setList(List list) { this.list = list; } + + } + + public static class ListTestBean { + + private List list = new ArrayList(); + + public List getList() { + return this.list; + } + + public void setList(List list) { + this.list = list; + } + } }