Consider the following app:

package com.example.demo;

import javax.sql.DataSource;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;

@SpringBootApplication
public class CustomDatasourceApplication {

    public static void main(String[] args) {
        SpringApplication.run(CustomDatasourceApplication.class, "--app.datasource.schema=classpath:does-not-exist.sql");
    }

    @Bean
    @Primary
    @ConfigurationProperties("app.datasource")
    public DataSourceProperties dataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @ConfigurationProperties("app.datasource")
    public DataSource dataSource() {
        return dataSourceProperties().initializeDataSourceBuilder().build();
    }

}

Running it results in the following exception being thrown:

Caused by: org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException: Property spring.datasource.schema with value 'class path resource [does-not-exist.sql]' is invalid: The specified resource does not exist.
    at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.getResources(DataSourceInitializer.java:169) ~[spring-boot-autoconfigure-2.0.3.RELEASE.jar:2.0.3.RELEASE]
    at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.getScripts(DataSourceInitializer.java:151) ~[spring-boot-autoconfigure-2.0.3.RELEASE.jar:2.0.3.RELEASE]
    at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.createSchema(DataSourceInitializer.java:95) ~[spring-boot-autoconfigure-2.0.3.RELEASE.jar:2.0.3.RELEASE]
    at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker.afterPropertiesSet(DataSourceInitializerInvoker.java:64) ~[spring-boot-autoconfigure-2.0.3.RELEASE.jar:2.0.3.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1767) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1704) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
    ... 27 common frames omitted

The property name is incorrect. It is spring.datasource.schema but should be app.datasource.schema. We need to know the prefix that's been used to bind the DataSourceProperties that we're working with.

Comment From: snicoll

That probably largely reduces the interest of InvalidConfigurationPropertyValueException unless we find a way to detect to which prefix it was bound. I don't see an easy way to do that from that context.

Comment From: wilkinsona

The only thing that I could think of was for something (the binding post-processor?) to keep a map of the beans that have bean bound and the prefix that was used. We could then ask for the prefix for the DataSourceProperties that are being used. I'm not sure it's worth it though…

Comment From: mbhave

It also means we don't get the failure analysis.

Comment From: snicoll

It also means we don't get the failure analysis.

I am not sure I got that. Or do you mean that the failure analysis shows the wrong prefix?

Comment From: mbhave

From what I could tell there would be no failure analysis when the property name is wrong.

Comment From: mbhave

We discussed this on the call and decided that we could move the validation up to a @PostConstruct on DataSourceProperties and throw the InvalidConfigurationPropertyValueException there for an invalid property. The bind handlers would then kick in and handle the exception.

Comment From: mbhave

This solution isn't great since it jumps through a few different exceptions. We should probably put this on hold till #14880 is done.

Comment From: mbhave

Although that might mean that this doesn't end up in 2.0.x

Comment From: wilkinsona

This doesn't happen any more in 2.5 due to the script-based initialization being decoupled from DataSource auto-configuration and moving into the spring-boot module. This means that the initializer is completely unaware of where it's settings came from and the possibility that they may have some from some @ConfigurationProperties. As a result, a more general IllegalStateException is now thrown when no scripts are found at a configured location.

If we want to keep the old behaviour and make it more accurate, we could allow a callback to be configured or a method to be sub-classed on AbstractScriptDatabaseInitializer that handles missing scripts. The default could throw an IllegalStateException while R2dbcInitializationConfiguration and both DataSourceInitializationConfigurations could provide something that throws an InvalidConfigurationPropertyValueException pointing to the appropriate spring.sql.init or spring.datasource property.

We don't have this sort of behaviour in many other places so I'm skeptical that it warrants adding complexity to the API of AbstractScriptDatabaseInitializer. Flagging for team attention to see what everyone else thinks.

Comment From: snicoll

Yeah, I thought that adding this exception would be generally useful but it turned out that we don't have many practical case of it, especially considering we're trying to rationalize and let folks use the lower-level API for advanced use case. So +1 to that.

Comment From: wilkinsona

Thanks, @snicoll. I'll close this one then.