Spring boot reset datasource on the fly

16.3k views Asked by At

I am trying to update datasource in Spring Boot when the DB property like DB name, password or hostname changes in the spring configuration file or custom DB property file. When the property changes the application has to update by its own by listening changes to property.

I was using Spring actuator to /restart beans once the DB configuration is changed. But user has to explicitly make a post request to restart. This step has to be avoided by listening to the changes and update datasource.

Can you tell me the best way to do this in Spring boot?

3

There are 3 answers

4
vishnukumar On BEST ANSWER

Found a way to update datasource on-the-fly,

I have given external spring config file which contains DB properties to the application and then refreshed the properties using @RefreshScope for the datasource bean.

A thread monitors the file changes and makes a call to actuator refresh() method.

database.properties

dburl=jdbc://localhost:5432/dbname
dbusername=user1
dbpassword=userpwd

Creating datasource,

@RefreshScope
public class DBPropRefresh {
  @Value("${dburl}")
  private String dbUrl;

  @Value("${dbusername}")
  private String dbUserName;

  @Value("${dbpassword}")
  private String dbPassword;

  @Bean
  @RefreshScope
  public DataSource getDatasource() {
    return new DatasourceBuilder().create().url(dbUrl).username(dbUserName).password(dbPassword);
  }
}

Giving external config file to the application,

java -jar myapplication.jar --spring.config.location=database.properties

I have created a Java thread class to monitor database.properties file changes. Followed https://dzone.com/articles/how-watch-file-system-changes When there are changes then it makes call to refreshEndPoint.refresh().

In pom.xml,

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
  <version>1.5.6.RELEASE</version>
</dependency>
0
pokemzok On

In my project I used multitenancy . Basically I defined several datasources in properties like this:

primary.datasource.url=jdbc:postgresql://localhost:5432/db_name?currentSchema=schema_name
primary.datasource.username=user
primary.datasource.password=password
primary.datasource.driverClassName=org.postgresql.Driver
primary.datasource.driver-class-name=org.postgresql.Driver

secondary.datasource.url=jdbc:postgresql://localhost:5432/other_db?currentSchema=schema
secondary.datasource.username=user
secondary.datasource.password=password
secondary.datasource.driverClassName=org.postgresql.Driver
secondary.datasource.driver-class-name=org.postgresql.Driver

default.datasource.url=jdbc:postgresql://localhost:5432/default_db?currentSchema=public
default.datasource.username=user
default.datasource.password=password
default.datasource.driverClassName=org.postgresql.Driver
default.datasource.driver-class-name=org.postgresql.Driver

then in configuration class defined multiple datasources:

@Bean
@Primary
@ConfigurationProperties(prefix="primary.datasource")
public DataSource primaryDataSource() {
    return DataSourceBuilder.create().build();
}

@Bean
@ConfigurationProperties(prefix="secondary.datasource")
public DataSource secondaryDataSource() {
    return DataSourceBuilder.create().build();
}

@Bean
@ConfigurationProperties(prefix="default.datasource")
public DataSource defaultDataSource(){
    return DataSourceBuilder.create().build();
}

and configured multitenancy basing on this and this article.
Pros:

  • Easy tenant switch which could be triggered manually or even configured to be triggered on some specific header in request (filters).
  • Could be cofigured to switch between schemas or databases.
  • Happens dynamically ( you don't have to restart your beans )

Cons:

  • You have to define all db possibilities in property file.
  • You have to turn off schema validation because it will go nuts.
5
Karthik R On

You can use Spring's Dynamic Data Source routing and check if it helps? It's a very old technique and might come handy, if that serves your purpose.

But please note that - this is data source routing and not new data source configuration.

https://spring.io/blog/2007/01/23/dynamic-datasource-routing/