From 1831f3be1632410ca32d2ead28460b65c4b5e4ab Mon Sep 17 00:00:00 2001 From: Madhura Bhave Date: Tue, 24 Jul 2018 17:22:45 -0700 Subject: [PATCH] Fix NPE when Collection contains unbound children Fixes gh-13636 --- .../bind/IndexedElementsBinder.java | 7 +++--- .../bind/CollectionBinderTests.java | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/IndexedElementsBinder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/IndexedElementsBinder.java index 1a9e6476c73..2ed0022c182 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/IndexedElementsBinder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/IndexedElementsBinder.java @@ -128,9 +128,10 @@ abstract class IndexedElementsBinder extends AggregateBinder { } for (ConfigurationPropertyName name : (IterableConfigurationPropertySource) source .filter(root::isAncestorOf)) { - name = name.chop(root.getNumberOfElements() + 1); - if (name.isLastElementIndexed()) { - String key = name.getLastElement(Form.UNIFORM); + ConfigurationPropertyName choppedName = name + .chop(root.getNumberOfElements() + 1); + if (choppedName.isLastElementIndexed()) { + String key = choppedName.getLastElement(Form.UNIFORM); ConfigurationProperty value = source.getConfigurationProperty(name); children.add(key, value); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/CollectionBinderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/CollectionBinderTests.java index cd057173ef6..43e9712e35b 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/CollectionBinderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/CollectionBinderTests.java @@ -134,6 +134,29 @@ public class CollectionBinderTests { } } + @Test + public void bindToNonScalarCollectionWhenNonSequentialShouldThrowException() { + MockConfigurationPropertySource source = new MockConfigurationPropertySource(); + source.put("foo[0].value", "1"); + source.put("foo[1].value", "2"); + source.put("foo[4].value", "4"); + this.sources.add(source); + try { + Bindable> target = Bindable.listOf(JavaBean.class); + this.binder.bind("foo", target); + fail("No exception thrown"); + } + catch (BindException ex) { + ex.printStackTrace(); + Set unbound = ((UnboundConfigurationPropertiesException) ex + .getCause()).getUnboundProperties(); + assertThat(unbound).hasSize(1); + ConfigurationProperty property = unbound.iterator().next(); + assertThat(property.getName().toString()).isEqualTo("foo[4].value"); + assertThat(property.getValue()).isEqualTo("4"); + } + } + @Test public void bindToCollectionWhenNonIterableShouldReturnPopulatedCollection() { MockConfigurationPropertySource source = new MockConfigurationPropertySource();