If I only set up the data source via spring.datasource values in application.properties, e.g.:
[email protected]
spring.datasource.driverClassName=net.snowflake.client.jdbc.SnowflakeDriver
spring.datasource.jdbcUrl=jdbc:snowflake://xxx.snowflakecomputing.com/?db=mydb&schema=myschema&warehouse=myhouse&role=myrole&private_key_file=mypath&private_key_file_pwd=mypass
it works. The issue is we need to pull the mypass value from a secrets manager at runtime, not embed secrets in the application.properties file.
So we created this class:
@Configuration
public class SnowflakeDbConfig {
@Value("${spring.datasource.jdbcUrl}")
private String urlx;
@Value("${spring.datasource.driverClassName}")
private String driver;
@Bean
@ConfigurationProperties(prefix="spring.datasource")
@Primary
public DataSource primaryDataSource() {
String keyPass = "&private_key_file_pwd=mypass";
log.info("url=" + urlx + keypass);
return DataSourceBuilder.create()
.url(urlx + keypass)
.driverClassName(driver)
.build();
}
}
And changed the jdbcUrl to this in the properties:
spring.datasource.jdbcUrl=jdbc:snowflake://xxx.snowflakecomputing.com/?db=mydb&schema=myschema&warehouse=myhouse&role=myrole&private_key_file=mypath
The problem is that the above does not work.
It turns out that whatever is supplied in .url() is ignored, and only value of spring.datasource.jdbcUrl is used. How can we define this programmatically?
Interestingly this works when the jdbcUrl & driverClassName are defined in properties:
return DataSourceBuilder.create()
.driverClassName(driver)
.build();
But this does not:
return DataSourceBuilder.create()
.build();
as it complains the driver class is missing.
Spring Boot 3.4, Java 21.
1 Answer 1
M. Deinum was correct, it seems you can't use ConfigurationProperties when you override a DataSource method unfortunately. You have to use "Value" manually.
@Configuration
public class SnowflakeDbConfig {
@Value("${spring.datasource.jdbcUrl}")
private String urlx;
@Value("${spring.datasource.driverClassName}")
private String driver;
@Value ("${spring.datasource.username}")
private String username;
@Bean
@Primary
public DataSource primaryDataSource() {
String keyPass = "&private_key_file_pwd=mypass";
return DataSourceBuilder.create()
.url(urlx + keypass)
.username(username)
.driverClassName(driver)
.build();
}
}
The problem is that now things defined in the properties such as:
spring.datasource.hikari.connectionTimeout=600000
spring.datasource.hikari.maximumPoolSize=5
spring.datasource.hikari.poolName=my-schedule
spring.datasource.hikari.maxLifeTime=590000
spring.datasource.hikari.connectionTestQuery: SELECT 1
Are not being picked up, as there is no way to associated different hikari properties with the primary or secondary datasource if we use a method do build the datasource and we can't use
@ConfigurationProperties(prefix="spring.datasource.primary")
or similar.
Comments
Explore related questions
See similar questions with these tags.
primaryDataSourceis called? Maybe config class is not scanned by Spring Boot. Try adding logging statements to be sure.@ConfigurationProperties(prefix="spring.datasource")which will bind it to the Hikari property and override your setting. Why aren't you just making your secrets part of the environment that way you can use property replacement in your URL.