Hi, if I understood #5110 correctly then one should expect optional configuration properties to be assigned.

Find a sample application prepared here: https://github.com/mamachanko/optional-nested-configuration-property

Assuming a config classes like so:

@Component
@ConfigurationProperties(prefix = "config")
@Data
@Validated
class Config {

    @NotBlank
    private String requiredProperty;
    private Optional<String> optionalProperty = Optional.empty();

    @NotNull
    private MoreConfig moreRequiredConfig;
    private Optional<MoreConfig> moreOptionalConfig = Optional.empty();
}

@Data
class MoreConfig {
    private String property;
}

Running w/ full configuration

spring:
  profiles: full
config:
  required-property: this-is-required
  optional-property: this-is-optional
  more-required-config:
    property: this-is-required
  more-optional-config:
    property: this-is-optional
$ ./mvnw clean spring-boot:run -Dspring.profiles.active=full
...
2019-02-19 21:08:16.288  INFO 28484 --- [main] i.g.m.o.ConfigLogger: Config(requiredProperty=this-is-required, optionalProperty=Optional[this-is-optional], moreRequiredConfig=MoreConfig(property=this-is-required), moreOptionalConfig=Optional.empty)
  • The field optionalProperty of type Optional<String> gets assigned as expected.
  • The field moreOptionalConfig of type Optional<MoreConfig> remains Optional.empty. This is not expected. It is expected to be MoreConfig(property=this-is-optional).

Does that make sense?

Comment From: philwebb

Binding to Optional fields currently only works with values that the ConversionService creates, it doesn't work with nested configuration properties and I'm personally not a big fan of using Optional with in fields (see this stackoverflow answer for details of why).

It's possible that we might be able to update the binder to fully support Optional but I'm interested in why you're keen to use it with nested configurations. It feels like it might make properties much harder to access, especially if the nested configurations themselves have optional values. Consider:

if(config.getMoreOptionalConfig().isPresent()) {
    String value = config.getMoreOptionalConfig().get().getSomeNestedProperty().orElse(SOME_DEFAULT);
}

Comment From: snicoll

It should also be noted that I don't think metadata for nested items will be generated in the arrangement above.

Comment From: mamachanko

That is a satisfactory explanation! I understand the reasoning.

This came up not so much because it is needed. But it was in a situation where I tried to convey the possibilities @ConfigurationProperties provides. I was genuinely convinced this would work.

Thanks @philwebb !

Comment From: colltoaction

@philwebb consider that Optional can be used in a functional way like:

String value = config.getMoreOptionalConfig().flatMap(MoreConfig::getSomeNestedProperty).orElse(SOME_DEFAULT);

Comment From: youngm

@philwebb I'd like to see Optional work with nested configuration properties someday. The second most voted answer to the stack overflow you linked to has some valid points: https://stackoverflow.com/a/26328314/1368209

You are perfectly welcome to have your opinion about Optionals. However, there is a large segment of the java development community that has a different opinion and would very much appreciate it if Spring Boot supported it. Thanks.