0

i have following problem: I am currently writing a spring boot application that provides a rest endpoint and also constantly evaluates some data stored inside a remote MySql database that i have to reach through a SSH tunnel. I use Jcraft library to create that tunnel and dynamically assign a free port that my data source is using to connect to the database through the tunnel. The port cannot be static.

The data source itself is a Hikari connection pool.

Every once in a while though something happens and i lose my connection to the database. I want to create a failsafe that basicly catches any exceptions related to any issues with the database communication, automatically shuts down the old tunnel + data source and then creates a new tunnel + recreates the data source.

My current approach was as following:

Basicly just recreate the the tunnel is it does not exist anymore and then close the connection pool + restarting it again. After that i set the new data source inside every JdbcTemplate thats autowired inside the DAO's.

My data source configuration bean:

import com.jcraft.jsch.JSchException;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.candidatis.tiertwo.data.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.TimeUnit;

@Slf4j
@Configuration
@Data
public class ConfigDataSource {

HikariDataSource ds;
private SshSession sshSession;
private DaoCustom daoCustom;
private DaoPortals daoPortals;
private DaoBlacklist daoBlacklist;
private DaoDbChecker daoDbChecker;
private DaoPublishing daoPublishing;
private DaoTempJobs daoTempJobs;

public ConfigDataSource(SshSession sshSession){
    this.sshSession = sshSession;
}

@Bean
public HikariDataSource dataSource(){
    ds = new HikariDataSource(getConfig());
    return ds;
}

public void reloadDataSource(){
    log.info("Reloading the Connection pool.");
    if(ds != null && !ds.isClosed()){
        ds.close();
    }
    ds = new HikariDataSource(getConfig());

    this.daoCustom.getJdbcTemplate().setDataSource(ds);
    this.daoPortals.getJdbcTemplate().setDataSource(ds);
    this.daoBlacklist.getJdbcTemplate().setDataSource(ds);;
    this.daoDbChecker.getJdbcTemplate().setDataSource(ds);
    this.daoPublishing.getJdbcTemplate().setDataSource(ds);
    this.daoPublishing.getNamedJdbcTemplate().getJdbcTemplate().setDataSource(ds);
    this.daoTempJobs.getJdbcTemplate().setDataSource(ds);
}

private HikariConfig getConfig(){
    try {
        this.sshSession.createSessionSSH();
    } catch (JSchException e) {
        e.printStackTrace();
        log.error("Could not create SSH session");
    }

    HikariConfig config = new HikariConfig();

    config.setJdbcUrl( Constants.DB_JDBC_URL + this.sshSession.getAssignedPort());
    config.setUsername( Constants.DB_USER );
    config.setPassword( Constants.DB_PASSWORD );

    config.setMaximumPoolSize(2);
    config.setMaxLifetime(TimeUnit.MINUTES.toMillis(5)); // default wait_timeout of MySQL = 28800 seconds = 8 hours -> must be less
    config.setConnectionTimeout(TimeUnit.MINUTES.toMillis(10)); // Maximum number of milliseconds that a client will wait for a connection from the pool. Throws SQLException
    config.setValidationTimeout(TimeUnit.MINUTES.toMillis(8)); // This property controls the maximum amount of time that a connection will be tested for aliveness.
    config.setLeakDetectionThreshold(30000);

    return config;
}

}

The exception handling if anything should happen is basicly just the reloadDataSource method. It creates a new pool using the configuration with the new assigned port and updates all data sources of all JdbcTemplate classes..

And it ALMOST works. I can reload the pool and i can then use SELECT statements on the database to fetch data, however i dont seem to be able to INSERT,UPDATE or DELETE data.

Here a part of my hikariCP log at startup(not reloading):

2021-03-31 13:18:05.051 DEBUG 471740 --- [  restartedMain] com.zaxxer.hikari.util.DriverDataSource  : Loaded driver with class name com.mysql.cj.jdbc.Driver for jdbcUrl=jdbc:mysql://localhost:41749
2021-03-31 13:18:05.566 DEBUG 471740 --- [  restartedMain] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Added connection com.mysql.cj.jdbc.ConnectionImpl@647dd875
2021-03-31 13:18:05.566  INFO 471740 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2021-03-31 13:18:05.666 DEBUG 471740 --- [l-1 housekeeper] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Pool stats (total=1, active=1, idle=0, waiting=0)
2021-03-31 13:18:05.714 DEBUG 471740 --- [onnection adder] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Added connection com.mysql.cj.jdbc.ConnectionImpl@1c9d2fe4
2021-03-31 13:18:05.714 DEBUG 471740 --- [onnection adder] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - After adding stats (total=2, active=1, idle=1, waiting=0)

..and here again after the reload:

2021-03-31 13:18:24.808  INFO 471740 --- [  restartedMain] n.c.tiertwo.config.ConfigDataSource      : Reloading the Connection pool.
2021-03-31 13:18:24.808  INFO 471740 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2021-03-31 13:18:24.809 DEBUG 471740 --- [  restartedMain] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Before shutdown stats (total=2, active=0, idle=2, waiting=0)
2021-03-31 13:18:24.809 DEBUG 471740 --- [nnection closer] com.zaxxer.hikari.pool.PoolBase          : HikariPool-1 - Closing connection com.mysql.cj.jdbc.ConnectionImpl@647dd875: (connection evicted)
2021-03-31 13:18:24.812 DEBUG 471740 --- [nnection closer] com.zaxxer.hikari.pool.PoolBase          : HikariPool-1 - Closing connection com.mysql.cj.jdbc.ConnectionImpl@1c9d2fe4: (connection evicted)
2021-03-31 13:18:24.812 DEBUG 471740 --- [  restartedMain] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - After shutdown stats (total=0, active=0, idle=0, waiting=0)
2021-03-31 13:18:24.812  INFO 471740 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
2021-03-31 13:18:34.946  INFO 471740 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Starting...
2021-03-31 13:18:34.946 DEBUG 471740 --- [  restartedMain] com.zaxxer.hikari.util.DriverDataSource  : Loaded driver with class name com.mysql.cj.jdbc.Driver for jdbcUrl=jdbc:mysql://localhost:35177
2021-03-31 13:18:35.691 DEBUG 471740 --- [  restartedMain] com.zaxxer.hikari.pool.HikariPool        : HikariPool-2 - Added connection com.mysql.cj.jdbc.ConnectionImpl@153f9ff2
2021-03-31 13:18:35.692  INFO 471740 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Start completed.
2021-03-31 13:18:35.710  INFO 471740 --- [  restartedMain] n.c.tiertwo.controllers.MainController   : Fetching TempJob Block from database
2021-03-31 13:18:35.792 DEBUG 471740 --- [l-2 housekeeper] com.zaxxer.hikari.pool.HikariPool        : HikariPool-2 - Pool stats (total=1, active=1, idle=0, waiting=0)
2021-03-31 13:18:35.978 DEBUG 471740 --- [onnection adder] com.zaxxer.hikari.pool.HikariPool        : HikariPool-2 - Added connection com.mysql.cj.jdbc.ConnectionImpl@22eb1758
2021-03-31 13:18:35.978 DEBUG 471740 --- [onnection adder] com.zaxxer.hikari.pool.HikariPool        : HikariPool-2 - After adding stats (total=2, active=1, idle=1, waiting=0)

Again: I can use SELECT statements so the pool should actually exist. However on INSERT,DELTE or any other queries i get following errors:

    at org.springframework.jdbc.core.metadata.TableMetaDataProviderFactory.createMetaDataProvider(TableMetaDataProviderFactory.java:86)
    at org.springframework.jdbc.core.metadata.TableMetaDataContext.processMetaData(TableMetaDataContext.java:171)
    at org.springframework.jdbc.core.simple.AbstractJdbcInsert.compileInternal(AbstractJdbcInsert.java:277)
    at org.springframework.jdbc.core.simple.AbstractJdbcInsert.compile(AbstractJdbcInsert.java:261)
    at org.springframework.jdbc.core.simple.AbstractJdbcInsert.checkCompiled(AbstractJdbcInsert.java:309)
    at org.springframework.jdbc.core.simple.AbstractJdbcInsert.doExecuteAndReturnKey(AbstractJdbcInsert.java:368)
    at org.springframework.jdbc.core.simple.SimpleJdbcInsert.executeAndReturnKey(SimpleJdbcInsert.java:127)
    at net.candidatis.tiertwo.data.DaoPublishing.publish(DaoPublishing.java:220)
    at net.candidatis.tiertwo.data.DaoPublishing$$FastClassBySpringCGLIB$$32c38d56.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
    at net.candidatis.tiertwo.data.DaoPublishing$$EnhancerBySpringCGLIB$$bdbc3342.publish(<generated>)
    at net.candidatis.tiertwo.services.Publisher.publish(Publisher.java:150)
    at net.candidatis.tiertwo.services.Publisher.publishEvaluation(Publisher.java:67)
    at net.candidatis.tiertwo.services.Publishing.run(Publishing.java:16)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-1) has been closed.
    at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:363)
    at org.springframework.jdbc.core.metadata.TableMetaDataProviderFactory.createMetaDataProvider(TableMetaDataProviderFactory.java:52)
    ... 25 more
Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-1) has been closed.
    at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:82)
    at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:337)
    ... 26 more
Caused by: java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-1) has been closed.
    at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:96)
    at org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection(DataSourceUtils.java:158)
    at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:116)
    at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:79)
    ... 27 more
org.springframework.dao.DataAccessResourceFailureException: Error retrieving database meta-data; nested exception is org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-1) has been closed.
    at org.springframework.jdbc.core.metadata.TableMetaDataProviderFactory.createMetaDataProvider(TableMetaDataProviderFactory.java:86)
    at org.springframework.jdbc.core.metadata.TableMetaDataContext.processMetaData(TableMetaDataContext.java:171)
    at org.springframework.jdbc.core.simple.AbstractJdbcInsert.compileInternal(AbstractJdbcInsert.java:277)
    at org.springframework.jdbc.core.simple.AbstractJdbcInsert.compile(AbstractJdbcInsert.java:261)
    at org.springframework.jdbc.core.simple.AbstractJdbcInsert.checkCompiled(AbstractJdbcInsert.java:309)
    at org.springframework.jdbc.core.simple.AbstractJdbcInsert.doExecuteAndReturnKey(AbstractJdbcInsert.java:368)
    at org.springframework.jdbc.core.simple.SimpleJdbcInsert.executeAndReturnKey(SimpleJdbcInsert.java:127)
    at net.candidatis.tiertwo.data.DaoPublishing.publish(DaoPublishing.java:220)
    at net.candidatis.tiertwo.data.DaoPublishing$$FastClassBySpringCGLIB$$32c38d56.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
    at net.candidatis.tiertwo.data.DaoPublishing$$EnhancerBySpringCGLIB$$bdbc3342.publish(<generated>)
    at net.candidatis.tiertwo.services.Publisher.publish(Publisher.java:150)
    at net.candidatis.tiertwo.services.Publisher.publishEvaluation(Publisher.java:67)
    at net.candidatis.tiertwo.services.Publishing.run(Publishing.java:16)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-1) has been closed.
    at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:363)
    at org.springframework.jdbc.core.metadata.TableMetaDataProviderFactory.createMetaDataProvider(TableMetaDataProviderFactory.java:52)
    ... 25 more
Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-1) has been closed.
    at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:82)
    at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:337)
    ... 26 more
Caused by: java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-1) has been closed.
    at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:96)
    at org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection(DataSourceUtils.java:158)
    at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:116)
    at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:79)
    ... 27 more
org.springframework.dao.DataAccessResourceFailureException: Error retrieving database meta-data; nested exception is org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-1) has been closed.
    at org.springframework.jdbc.core.metadata.TableMetaDataProviderFactory.createMetaDataProvider(TableMetaDataProviderFactory.java:86)
    at org.springframework.jdbc.core.metadata.TableMetaDataContext.processMetaData(TableMetaDataContext.java:171)
    at org.springframework.jdbc.core.simple.AbstractJdbcInsert.compileInternal(AbstractJdbcInsert.java:277)
    at org.springframework.jdbc.core.simple.AbstractJdbcInsert.compile(AbstractJdbcInsert.java:261)
    at org.springframework.jdbc.core.simple.AbstractJdbcInsert.checkCompiled(AbstractJdbcInsert.java:309)
    at org.springframework.jdbc.core.simple.AbstractJdbcInsert.doExecuteAndReturnKey(AbstractJdbcInsert.java:368)
    at org.springframework.jdbc.core.simple.SimpleJdbcInsert.executeAndReturnKey(SimpleJdbcInsert.java:127)
    at net.candidatis.tiertwo.data.DaoPublishing.publish(DaoPublishing.java:220)
    at net.candidatis.tiertwo.data.DaoPublishing$$FastClassBySpringCGLIB$$32c38d56.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
    at net.candidatis.tiertwo.data.DaoPublishing$$EnhancerBySpringCGLIB$$bdbc3342.publish(<generated>)
    at net.candidatis.tiertwo.services.Publisher.publish(Publisher.java:150)
    at net.candidatis.tiertwo.services.Publisher.publish(Publisher.java:171)
    at net.candidatis.tiertwo.services.Publisher.publishEvaluation(Publisher.java:67)
    at net.candidatis.tiertwo.services.Publishing.run(Publishing.java:16)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-1) has been closed.
    at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:363)
    at org.springframework.jdbc.core.metadata.TableMetaDataProviderFactory.createMetaDataProvider(TableMetaDataProviderFactory.java:52)
    ... 26 more
Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-1) has been closed.
    at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:82)
    at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:337)
    ... 27 more
Caused by: java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-1) has been closed.
    at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:96)
    at org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection(DataSourceUtils.java:158)
    at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:116)
    at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:79)
    ... 28 more
org.springframework.dao.DataAccessResourceFailureException: Error retrieving database meta-data; nested exception is org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-1) has been closed.
    at org.springframework.jdbc.core.metadata.TableMetaDataProviderFactory.createMetaDataProvider(TableMetaDataProviderFactory.java:86)
    at org.springframework.jdbc.core.metadata.TableMetaDataContext.processMetaData(TableMetaDataContext.java:171)
    at org.springframework.jdbc.core.simple.AbstractJdbcInsert.compileInternal(AbstractJdbcInsert.java:277)
    at org.springframework.jdbc.core.simple.AbstractJdbcInsert.compile(AbstractJdbcInsert.java:261)
    at org.springframework.jdbc.core.simple.AbstractJdbcInsert.checkCompiled(AbstractJdbcInsert.java:309)
    at org.springframework.jdbc.core.simple.AbstractJdbcInsert.doExecuteAndReturnKey(AbstractJdbcInsert.java:368)
    at org.springframework.jdbc.core.simple.SimpleJdbcInsert.executeAndReturnKey(SimpleJdbcInsert.java:127)
    at net.candidatis.tiertwo.data.DaoPublishing.publish(DaoPublishing.java:220)
    at net.candidatis.tiertwo.data.DaoPublishing$$FastClassBySpringCGLIB$$32c38d56.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
    at net.candidatis.tiertwo.data.DaoPublishing$$EnhancerBySpringCGLIB$$bdbc3342.publish(<generated>)
    at net.candidatis.tiertwo.services.Publisher.publish(Publisher.java:150)
    at net.candidatis.tiertwo.services.Publisher.publish(Publisher.java:171)
    at net.candidatis.tiertwo.services.Publisher.publishEvaluation(Publisher.java:67)
    at net.candidatis.tiertwo.services.Publishing.run(Publishing.java:16)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-1) has been closed.
    at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:363)
    at org.springframework.jdbc.core.metadata.TableMetaDataProviderFactory.createMetaDataProvider(TableMetaDataProviderFactory.java:52)
    ... 26 more
Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-1) has been closed.
    at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:82)
    at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:337)
    ... 27 more
Caused by: java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-1) has been closed.
    at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:96)
    at org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection(DataSourceUtils.java:158)
    at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:116)
    at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:79)
    ... 28 more

As you can see it is still trying to use the HikariPool #1 when it actually should use the new #2 that i have set previousely.

Any ideas why it is behaving that way ? Could it be that i cannot switch the datasource of the jdbcTemplate that is provided by the Spring container once it is initialized ? If i cannot change it why can i use a SELECT query ? Is there generally a much better way to just globally update the data source for all my DB operations ? I really need to find a solid solution for those database connection issues.

Thanks for anything.

I am thankful for any help.

MajesticOl
  • 311
  • 1
  • 20

2 Answers2

0

See if this answer by @JonBates helps: https://stackoverflow.com/a/64375936/5917837

mantri
  • 3,031
  • 4
  • 16
  • 19
0

We need to reload the datasourcetransactionmanager bean, or set the new datasource for this bean.

@Slf4j
@Configuration
@Data
public class ConfigDataSource {

    private final BeanFactory beanFactory;
    HikariDataSource ds;
    private SshSession sshSession;
    private DaoCustom daoCustom;
    private DaoPortals daoPortals;
    private DaoBlacklist daoBlacklist;
    private DaoDbChecker daoDbChecker;
    private DaoPublishing daoPublishing;
    private DaoTempJobs daoTempJobs;

   public ConfigDataSource(SshSession sshSession){
      this.sshSession = sshSession;
   }

  @Bean
  public HikariDataSource dataSource(){
    ds = new HikariDataSource(getConfig());
    DataSourceTransactionManager dataSourceTransactionManager = beanFactory.getBean(DataSourceTransactionManager.class);
    dataSourceTransactionManager.setDataSource(ds);
    return ds;
  }

  public void reloadDataSource(){
    log.info("Reloading the Connection pool.");
    if(ds != null && !ds.isClosed()){
        ds.close();
    }
    ds = new HikariDataSource(getConfig());

    this.daoCustom.getJdbcTemplate().setDataSource(ds);
    this.daoPortals.getJdbcTemplate().setDataSource(ds);
    this.daoBlacklist.getJdbcTemplate().setDataSource(ds);;
    this.daoDbChecker.getJdbcTemplate().setDataSource(ds);
    this.daoPublishing.getJdbcTemplate().setDataSource(ds);  
  
 this.daoPublishing.getNamedJdbcTemplate().getJdbcTemplate().setDataSource(ds);
    this.daoTempJobs.getJdbcTemplate().setDataSource(ds);
  }

private HikariConfig getConfig(){
    try {
        this.sshSession.createSessionSSH();
    } catch (JSchException e) {
        e.printStackTrace();
        log.error("Could not create SSH session");
    }

    HikariConfig config = new HikariConfig();

    config.setJdbcUrl( Constants.DB_JDBC_URL + this.sshSession.getAssignedPort());
    config.setUsername( Constants.DB_USER );
    config.setPassword( Constants.DB_PASSWORD );

    config.setMaximumPoolSize(2);
    config.setMaxLifetime(TimeUnit.MINUTES.toMillis(5)); // default wait_timeout of MySQL = 28800 seconds = 8 hours -> must be less
    config.setConnectionTimeout(TimeUnit.MINUTES.toMillis(10)); // Maximum number of milliseconds that a client will wait for a connection from the pool. Throws SQLException
    config.setValidationTimeout(TimeUnit.MINUTES.toMillis(8)); // This property controls the maximum amount of time that a connection will be tested for aliveness.
    config.setLeakDetectionThreshold(30000);

    return config;
}

This worked for me, and I was able to perform INSERT, UPDATE, DELETE queries as well along with SELECT queries.

Sai Vamsi
  • 101
  • 5