Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
*
* @author Phillip Webb
* @author Madhura Bhave
* @author Lasse Wulff
*/
class JavaBeanBinder implements DataObjectBinder {

Expand Down Expand Up @@ -92,7 +93,7 @@ private <T> boolean bind(DataObjectPropertyBinder propertyBinder, Bean<T> bean,

private <T> boolean bind(BeanSupplier<T> beanSupplier, DataObjectPropertyBinder propertyBinder,
BeanProperty property) {
String propertyName = property.getName();
String propertyName = determinePropertyName(property);
ResolvableType type = property.getType();
Supplier<Object> value = property.getValue(beanSupplier);
Annotation[] annotations = property.getAnnotations();
Expand All @@ -110,6 +111,15 @@ else if (value == null || !bound.equals(value.get())) {
return true;
}

private String determinePropertyName(BeanProperty property) {
return Arrays.stream((property.getAnnotations() != null) ? property.getAnnotations() : new Annotation[0])
.filter((annotation) -> annotation.annotationType() == Name.class)
.findFirst()
.map(Name.class::cast)
.map(Name::value)
.orElse(property.getName());
}

/**
* The properties of a bean that may be bound.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@
import java.lang.annotation.Target;

/**
* Annotation that can be used to specify the name when binding to an immutable property.
* This annotation may be required when binding to names that clash with reserved language
* Annotation that can be used to specify the name when binding to a property. This
* annotation may be required when binding to names that clash with reserved language
* keywords.
*
* @author Phillip Webb
* @author Lasse Wulff
* @since 2.4.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@Target({ ElementType.FIELD, ElementType.PARAMETER })
@Documented
public @interface Name {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
* @author Phillip Webb
* @author Madhura Bhave
* @author Andy Wilkinson
* @author Lasse Wulff
*/
class JavaBeanBinderTests {

Expand All @@ -74,6 +75,27 @@ void bindToClassShouldCreateBoundBean() {
assertThat(bean.getEnumValue()).isEqualTo(ExampleEnum.FOO_BAR);
}

@Test
void bindRenamedPropertyToClassBean() {
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
source.put("renamed.public", "alpha");
this.sources.add(source);
ExampleRenamedPropertyBean bean = this.binder.bind("renamed", Bindable.of(ExampleRenamedPropertyBean.class))
.get();
assertThat(bean.getExampleProperty()).isEqualTo("alpha");
}

@Test
void bindRenamedPropertyToRecordBean() {
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
source.put("renamed.class", "alpha");
this.sources.add(source);
ExampleRenamedPropertyRecordBean bean = this.binder
.bind("renamed", Bindable.of(ExampleRenamedPropertyRecordBean.class))
.get();
assertThat(bean.exampleProperty()).isEqualTo("alpha");
}

@Test
void bindToClassWhenHasNoPrefixShouldCreateBoundBean() {
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
Expand Down Expand Up @@ -648,6 +670,24 @@ void setEnumValue(ExampleEnum enumValue) {

}

static class ExampleRenamedPropertyBean {

@Name("public")
private String exampleProperty;

String getExampleProperty() {
return this.exampleProperty;
}

void setExampleProperty(String exampleProperty) {
this.exampleProperty = exampleProperty;
}

}

record ExampleRenamedPropertyRecordBean(@Name("class") String exampleProperty) {
}

static class ExampleDefaultsBean {

private int foo = 123;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ import org.springframework.context.annotation.Import
import org.springframework.test.context.support.TestPropertySourceUtils

import org.assertj.core.api.Assertions.assertThat
import org.springframework.boot.context.properties.bind.Name

/**
* Tests for {@link ConfigurationProperties @ConfigurationProperties}-annotated beans.
*
* @author Madhura Bhave
* @author Lasse Wulff
*/
class KotlinConfigurationPropertiesTests {

Expand Down Expand Up @@ -59,6 +61,22 @@ class KotlinConfigurationPropertiesTests {
assertThat(this.context.getBean(LateInitProperties::class.java).inner.value).isEqualTo("alpha")
}

@Test
fun `renamed property can be bound`() {
this.context.register(EnableRenamedProperties::class.java)
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context, "renamed.fun=beta")
this.context.refresh()
assertThat(this.context.getBean(RenamedProperties::class.java).bar).isEqualTo("beta")
}

@Test
fun `renamed property can be bound to late init attribute`() {
this.context.register(EnableRenamedLateInitProperties::class.java)
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context, "renamed.var=beta")
this.context.refresh()
assertThat(this.context.getBean(RenamedLateInitProperties::class.java).bar).isEqualTo("beta")
}

@Test
fun `type with constructor bound lateinit property with default can be bound`() {
this.context.register(EnableLateInitPropertiesWithDefault::class.java)
Expand All @@ -80,6 +98,21 @@ class KotlinConfigurationPropertiesTests {
@ConfigurationProperties(prefix = "foo")
class BingProperties(@Suppress("UNUSED_PARAMETER") bar: String)

@ConfigurationProperties(prefix = "renamed")
class RenamedProperties(@Name("fun") val bar: String)

@EnableConfigurationProperties(RenamedProperties::class)
class EnableRenamedProperties

@ConfigurationProperties(prefix = "renamed")
class RenamedLateInitProperties{
@Name("var")
lateinit var bar: String
}

@EnableConfigurationProperties(RenamedLateInitProperties::class)
class EnableRenamedLateInitProperties

@EnableConfigurationProperties
class EnableConfigProperties

Expand Down