The fact: @ConfigurationProperties class can be @Validated. Another fact: You can set default values to some fields of @ConfigurationProperties class.

What I want is to have an ability to set default values using some sophisticated logic, that will use result of binding, but before validation will be triggered.

For example, I have two properties:

    @NotEmpty
    private String bucketName;

    @NotEmpty
    @URL
    private String imageUrlPrefix;

If bucketName is set, but imageUrlPrefix is not set, then I want imageUrlPrefix to be a predefined URL where bucketName is part of this URL.

Like this:

    public void onAfterBind() {
        if (imageUrlPrefix == null && bucketName != null) {
            imageUrlPrefix = String.format("https://%s.storage.googleapis.com/", bucketName);
        }
    }

I tried do this in @PostConstruct, but validation triggers earlier and throws an exception because imageUrlPrefix can't be empty. And my code has no chance to run.

I found a solution in using ConfigurationPropertiesBindHandlerAdvisor and AbstractBindHandler. What I done:

I created interface:

public interface ConfigurationPropertiesBindingCustomizer {

    void onAfterBind();

}

And @Configuration:

@Configuration
public class ConfigurationPropertiesBindingCustomizerConfiguration {

    @Bean
    ConfigurationPropertiesBindHandlerAdvisor customConfigurationPropertiesBindHandlerAdvisor() {
        return parentBindHandler -> new AbstractBindHandler(parentBindHandler) {
            @Override
            public void onFinish(ConfigurationPropertyName name, Bindable<?> target, BindContext context, Object result) throws Exception {
                if (result instanceof ConfigurationPropertiesBindingCustomizer) {
                    ConfigurationPropertiesBindingCustomizer props = (ConfigurationPropertiesBindingCustomizer) result;
                    props.onAfterBind();
                }
                parentBindHandler.onFinish(name, target, context, result);
            }
        };
    }

}

Now, my @ConfigurationProperties class can implement this interface and run custom logic in onAfterBind().

It's dirty solution as my naming of things is bad and I think it's not generic enough to propose it as is, but maybe you all can think about it and come up with something similar that will allow to run some custom code after binding, but before validation?

Comment From: bclozel

We've discussed this enhancement request as a team, and we don't think we should promote an approach where complex logic is performed at that level - we should keep configuration properties for binding and validation and avoid such patterns.

We think that this logic is better performed at the configuration level.

Thanks!