Spring boot reset datasource on the fly

主宰稳场 提交于 2019-12-04 04:59:15
vishnukumar

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>

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/

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.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!