From d61724aadae4823e080972446618b652dfc4fc09 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Mon, 7 Dec 2020 18:51:42 -0600 Subject: [PATCH] Add @Name support for Kotlin value object binding Fixes gh-24379 --- .../context/properties/bind/ValueObjectBinder.java | 8 +++++++- .../bind/KotlinConstructorParametersBinderTests.kt | 12 ++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/ValueObjectBinder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/ValueObjectBinder.java index 6ff230ac4f1..bbaa646941e 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/ValueObjectBinder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/ValueObjectBinder.java @@ -48,6 +48,7 @@ import org.springframework.util.Assert; * @author Madhura Bhave * @author Stephane Nicoll * @author Phillip Webb + * @author Scott Frederick */ class ValueObjectBinder implements DataObjectBinder { @@ -202,7 +203,7 @@ class ValueObjectBinder implements DataObjectBinder { List parameters = kotlinConstructor.getParameters(); List result = new ArrayList<>(parameters.size()); for (KParameter parameter : parameters) { - String name = parameter.getName(); + String name = getParameterName(parameter); ResolvableType parameterType = ResolvableType .forType(ReflectJvmMapping.getJavaType(parameter.getType()), type); Annotation[] annotations = parameter.getAnnotations().toArray(new Annotation[0]); @@ -211,6 +212,11 @@ class ValueObjectBinder implements DataObjectBinder { return Collections.unmodifiableList(result); } + private String getParameterName(KParameter parameter) { + return parameter.getAnnotations().stream().filter(Name.class::isInstance).findFirst().map(Name.class::cast) + .map(Name::value).orElse(parameter.getName()); + } + @Override List getConstructorParameters() { return this.constructorParameters; diff --git a/spring-boot-project/spring-boot/src/test/kotlin/org/springframework/boot/context/properties/bind/KotlinConstructorParametersBinderTests.kt b/spring-boot-project/spring-boot/src/test/kotlin/org/springframework/boot/context/properties/bind/KotlinConstructorParametersBinderTests.kt index 36dade59979..71326c7c956 100644 --- a/spring-boot-project/spring-boot/src/test/kotlin/org/springframework/boot/context/properties/bind/KotlinConstructorParametersBinderTests.kt +++ b/spring-boot-project/spring-boot/src/test/kotlin/org/springframework/boot/context/properties/bind/KotlinConstructorParametersBinderTests.kt @@ -10,6 +10,7 @@ import org.springframework.core.ResolvableType * Tests for `ConstructorParametersBinder`. * * @author Stephane Nicoll + * @author Scott Frederick */ class KotlinConstructorParametersBinderTests { @@ -187,6 +188,15 @@ class KotlinConstructorParametersBinderTests { assertThat(bean.value.get("bar")).isEqualTo("baz"); } + @Test + fun `Bind to named constructor parameter`() { + val source = MockConfigurationPropertySource() + source.put("foo.string-value", "test") + val binder = Binder(source) + val bean = binder.bind("foo", Bindable.of(ExampleNamedParameterBean::class.java)).get() + assertThat(bean.stringDataValue).isEqualTo("test") + } + class ExampleValueBean(val intValue: Int?, val longValue: Long?, val booleanValue: Boolean?, val stringValue: String?, val enumValue: ExampleEnum?) @@ -228,6 +238,8 @@ class KotlinConstructorParametersBinderTests { val stringValue: String = "my data", val enumValue: ExampleEnum = ExampleEnum.BAR_BAZ) + data class ExampleNamedParameterBean(@Name("stringValue") val stringDataValue: String) + data class GenericValue( val value: T )