Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Datasource configuration issue after spring boot 2 migration (Hiraki jdbcUrl is required.) #12758

Closed
ips219 opened this issue Apr 4, 2018 · 4 comments

Comments

@ips219
Copy link

@ips219 ips219 commented Apr 4, 2018

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
@snicoll
Copy link
Member

@snicoll snicoll commented Apr 4, 2018

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.

@ips219
Copy link
Author

@ips219 ips219 commented Apr 4, 2018

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

@kushsharma1001
Copy link

@kushsharma1001 kushsharma1001 commented Sep 23, 2020

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)

@ips219
Copy link
Author

@ips219 ips219 commented Sep 23, 2020

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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants