We have an spring boot application with multiple datasources, configured in properties with different namespaces as:
spring.datasource.DB1.url=jdbc:postgresql://localhost:5432/postgres1
spring.datasource.DB1.username=DB1_USER
spring.datasource.DB1.password=DB2_PASSWORD
spring.datasource.DB1.driver-class-name = org.postgresql.Driver
spring.datasource.DB2.url=jdbc:postgresql://localhost:5432/postgres2
spring.datasource.DB2.username=DB1_USER
spring.datasource.DB2.password=DB2_PASSWORD
spring.datasource.DB2.driver-class-name = org.postgresql.Driver
And in the @Configuration class this databases are initialized as
@Primary
@Bean("DB1")
@ConfigurationProperties(prefix = "spring.datasource.DB1")
public DataSource pricingDatasource() {
return DataSourceBuilder.create().build();
}
@Bean("DB2")
@ConfigurationProperties(prefix = "spring.datasource.DB2")
public DataSource pricingDatasource() {
return DataSourceBuilder.create().build();
}
After switching to Spring boot 2 with the new Hikari default connection pool there is an error in the start up of the application.
Caused by: java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName.
at com.zaxxer.hikari.HikariConfig.validate(HikariConfig.java:1059) ~[classes/:na]
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:109) ~[classes/:na]
at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:385) ~[liquibase-core-3.5.5.jar:na]
After checking documentation it seems that for Hikari connection pool is not neccesary include the driver class name (Maybe including this the refence guide? boot-app-properties ) so we have removed and we get a different error:
Caused by: java.lang.IllegalArgumentException: dataSource or dataSourceClassName or jdbcUrl is required.
at com.zaxxer.hikari.HikariConfig.validate(HikariConfig.java:1063) ~[classes/:na]
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:109) ~[classes/:na]
at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:385) ~[liquibase-core-3.5.5.jar:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1769) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1706) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
... 16 common frames omitted
The problem it seems that with a different namespace in the properties than the default one, the org.springframework.boot.jdbc.DataSourceBuilder is not mapping correctly the standard spring url property to the native hiraki jdbcURL.
This works as workaround (I don´t want to remove the spring standard):
spring.datasource.DB1.url=jdbc:postgresql://localhost:5432/postgres1
spring.datasource.DB1.jdbcUrl=${spring.datasource.DB1.url}
spring.datasource.DB1.username=DB1_USER
spring.datasource.DB1.password=DB2_PASSWORD
spring.datasource.DB1.driver-class-name = org.postgresql.Driver
spring.datasource.DB2.url=jdbc:postgresql://localhost:5432/postgres2
spring.datasource.DB2.jdbcUrl=${spring.datasource.DB2.url}
spring.datasource.DB2.username=DB1_USER
spring.datasource.DB2.password=DB2_PASSWORD
spring.datasource.DB2.driver-class-name = org.postgresql.Driver
Comment From: snicoll
That's not how you should configure custom datasources if you want to simulate what the auto-configuration does. There is a dedicated section in the documentation that shows you how to accomplish this.
DataSourceBuilder can't replace jdbcUrl to url in your code snippet as the binding is done externally (via @ConfigurationProperties)
If you use the technique explained in the documentation, you could also omit the jdbc driver as it is automatically detected.
Comment From: ips219
Many thanks for the clarification. One question en relation with the documentation referenced.
If the datasource can be initialized with a DataSourceProperties bean previously initialized with the @ConfigurationProperties.
Why is it necessary to include the same @ConfigurationProperties in the datasource bean?
BR
Comment From: kushsharma1001
Hi, Were you able to resolve it? I am facing same issue. Can you share the application properties format used for 2 datasources configuration that worked for you? In my case, first datasource is already configured via java code. Now, I need to add another datasource and I am trying to add 2nd datasource in application.properties file. But getting error: org.springframework.boot.context.properties.source.InvalidConfigurationPropertyNameException: Configuration property name 'postgresql.secondDatasource' is not valid.
postgresql.secondDatasource.jdbc-url=jdbc:postgresql://......... postgresql.secondDatasource.username=XXXXX postgresql.secondDatasource.password=XXXXX postgresql.secondDatasource.driverClassName=org.postgresql.Driver
(In my case, both datasources are of postgresql but they are in different servers)
Comment From: ips219
I don't have the exact source code right now...
But I think I did this in configuration class..
@Bean(name = {"dataSourceA"})
@ConfigurationProperties(prefix = "app.datasource.com")
public DataSource comDatasource() {
return DataSourceBuilder.create().build();
}
@Bean(name = {"dataSourceB"})
@ConfigurationProperties(prefix = "app.datasource.fin")
public DataSource finDatasource() {
return DataSourceBuilder.create().build();
}
And then the properties duplicated with the prefix...
app.datasource.com.jdbc-url=jdbc:postgresql://......... app.datasource.com.username=XXXXX app.datasource.com.password=XXXXX app.datasource.com.driverClassName=org.postgresql.Driver
app.datasource.fin.jdbc-url=jdbc:postgresql://......... app.datasource.fin.username=XXXXX app.datasource.fin.password=XXXXX app.datasource.fin.driverClassName=org.postgresql.Driver
So if you need datasource @Autowired you need to add the specific qualifier...
Look out if you plan to used distributed transactions that are not supported by spring by default (https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/jta/JtaTransactionManager.html).