Version information
Spring-boot: 2.2.6.RELEASE
Reproduction
I have an immutable @ConfigurationProperties
class with nested properties:
package com.example.demo;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.boot.context.properties.bind.DefaultValue;
@ConfigurationProperties
@ConstructorBinding
public class NestedConfigurationProperties {
private final NestedProperties nested;
private final String property;
public NestedConfigurationProperties(
NestedProperties nested,
String property) {
this.nested = nested;
this.property = property;
}
public NestedProperties getNested() {
return nested;
}
public String getProperty() {
return property;
}
public static class NestedProperties {
private final String nestedProperty;
public NestedProperties(@DefaultValue("default_value") String nestedProperty) {
this.nestedProperty = nestedProperty;
}
public String getNestedProperty() {
return nestedProperty;
}
}
}
When I bind the class without specifying a value for the nested property the nested properties holder object is null. A test illustrating my expectations:
package com.example.demo;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
public class PropertiesTest {
@Test
void nestedPropertiesAreNotNull() {
Map<String, String> properties = new HashMap<>();
properties.put("property", "some value");
Binder binder = new Binder(new MapConfigurationPropertySource(properties));
BindResult<NestedConfigurationProperties> bindResult =
binder.bind("", Bindable.of(NestedConfigurationProperties.class));
assertThat(bindResult.get().getNested()).isNotNull();
}
}
Unless I set a value for a nested property (properties.put("nested.nested_property", "some value")
) the NestedConfigurationProperties#nested
field is null.
Expected result
The nested properties object is never null when binding the top-level properties.
Comment From: mbhave
This is a duplicate of #18917. The fix for that will be available in Spring Boot 2.2.7. An empty @DefaultValue
on the constructor parameter indicates the property should never be null even when nothing was bound to it. You can give it a try with the 2.2.7 snapshots.
Comment From: jannis-baratheon
Thanks @mbhave.