Skip to content

How to solve `dataSource or dataSourceClassName or jdbcUrl is required` when connecting to multiple datasources using Spring Boot

Problem

When accessing multiple datasources using Spring Boot’s JdbcTemplate, you might encounter the following error:

Terminal window
Caused by: java.lang.IllegalArgumentException: dataSource or dataSourceClassName or jdbcUrl is required.
at com.zaxxer.hikari.HikariConfig.validate(HikariConfig.java:1004) ~[HikariCP-3.4.5.jar:na]

This error occurs because HikariCP requires specific properties to be set for each datasource.

Environment

  • Postgresql 10.15+
  • MySQL 5.7+
  • Spring Boot 2.3+
  • JDK 1.8+

Debug

Debug #1: The build.gradle of the app

The app is built using Gradle. Here is the relevant part of the build.gradle file:

build.gradle
plugins {
id 'org.springframework.boot'
id 'io.spring.dependency-management'
id 'java'
}
group 'com.bswen.app4'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
runtimeOnly 'mysql:mysql-connector-java'
runtimeOnly 'org.postgresql:postgresql'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}

Debug #2: The MultipleDBConfig class

To connect to multiple datasources, a @Configuration class is required:

MultipleDBConfig.java
package com.bswen.app4;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
@Configuration
public class MultipleDBConfig {
@Bean(name = "mysqlDb")
@ConfigurationProperties(prefix = "spring.ds-mysql")
public DataSource mysqlDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "mysqlJdbcTemplate")
public JdbcTemplate jdbcTemplate(@Qualifier("mysqlDb") DataSource dsMySQL) {
return new JdbcTemplate(dsMySQL);
}
@Bean(name = "postgresDb")
@ConfigurationProperties(prefix = "spring.ds-postgresql")
public DataSource postgresDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "postgresJdbcTemplate")
public JdbcTemplate postgresJdbcTemplate(@Qualifier("postgresDb")
DataSource dsPostgres) {
return new JdbcTemplate(dsPostgres);
}
}

Debug #3: The application.properties file

The connection properties for the datasources are defined in application.properties:

application.properties
spring.ds-postgresql.url =jdbc:postgresql://47.1.2.7:5432/bswendb
spring.ds-postgresql.username =bswen
spring.ds-postgresql.password =123456
spring.ds-mysql.url = jdbc:mysql://47.1.2.7:3306/bswen2
spring.ds-mysql.username = bswen
spring.ds-mysql.password = 123456

Debug #4: The JDBC client

The JDBC client queries data from the multiple datasources:

MultipleDBJDBCRunner.java
package com.bswen.app4;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.CommandLineRunner;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class MultipleDBJDBCRunner implements CommandLineRunner {
private static final Logger log = LoggerFactory.getLogger(MultipleDBJDBCRunner.class);
@Autowired @Qualifier("mysqlJdbcTemplate")
JdbcTemplate mysqlJdbcTemplate;
@Autowired @Qualifier("postgresJdbcTemplate")
JdbcTemplate postgresJdbcTemplate;
@Override
public void run(String... args) throws Exception {
log.info("Querying for users from mysql:");
mysqlJdbcTemplate.query(
"SELECT id, name, emailid, phoneno,location FROM usermaster", new Object[] { },
(rs, rowNum) -> new UserMaster(
rs.getInt("id"),
rs.getString("name"),
rs.getString("emailid"),
rs.getString("phoneno"),
rs.getString("location"))
).forEach(customer -> log.info(customer.toString()));
log.info("Querying for users from postgresql:");
postgresJdbcTemplate.query(
"SELECT id, name, emailid, phoneno,location FROM usermaster", new Object[] { },
(rs, rowNum) -> new UserMaster(
rs.getInt("id"),
rs.getString("name"),
rs.getString("emailid"),
rs.getString("phoneno"),
rs.getString("location"))
).forEach(customer -> log.info(customer.toString()));
}
}

Reason

According to the Spring Boot documentation, when using HikariCP, the jdbc-url property must be used instead of url.

Solution

Edit your application.properties to use jdbc-url:

application.properties
spring.ds-postgresql.jdbc-url =jdbc:postgresql://47.1.2.7:5432/bswendb
spring.ds-postgresql.username =bswen
spring.ds-postgresql.password =123456
spring.ds-mysql.jdbc-url = jdbc:mysql://47.1.2.7:3306/bswen2
spring.ds-mysql.username = bswen
spring.ds-mysql.password = 123456

After making this change, re-run the Spring Boot application. The error should be resolved, and the application should connect to both datasources successfully.

All the code is available on GitHub. You can download the example code here.

Final Words + More Resources

My intention with this article was to help others who might be considering solving such a problem. So I hope that’s been the case here. If you still have any questions, don’t hesitate to ask me by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!