diff --git a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java index 6966e530..b8cd7ba9 100644 --- a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java +++ b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java @@ -482,9 +482,20 @@ public final class HikariPool extends PoolBase implements HikariPoolMXBean, IBag return poolEntry; } - catch (Exception e) { + catch (SQLException e) { + if (poolState == POOL_NORMAL) { // we check POOL_NORMAL to avoid a flood of messages if shutdown() is running concurrently + LOGGER.debug("{} - Cannot acquire connection from data source", poolName, e); + } + return null; + } + catch (Throwable e) { if (poolState == POOL_NORMAL) { // we check POOL_NORMAL to avoid a flood of messages if shutdown() is running concurrently - LOGGER.debug("{} - Cannot acquire connection from data source", poolName, (e instanceof ConnectionSetupException ? e.getCause() : e)); + LOGGER.error("{} - Error thrown while acquiring connection from data source", poolName, (e instanceof ConnectionSetupException ? e.getCause() : e)); + if (e instanceof ConnectionSetupException) { + lastConnectionFailure.set(e); + } else { + lastConnectionFailure.set(new ConnectionSetupException(e)); + } } return null; } diff --git a/src/main/java/com/zaxxer/hikari/pool/PoolBase.java b/src/main/java/com/zaxxer/hikari/pool/PoolBase.java index f7cfba68..34a39846 100644 --- a/src/main/java/com/zaxxer/hikari/pool/PoolBase.java +++ b/src/main/java/com/zaxxer/hikari/pool/PoolBase.java @@ -58,6 +58,7 @@ abstract class PoolBase protected volatile String catalog; protected final String poolName; + protected final AtomicReference lastConnectionFailure; long connectionTimeout; long validationTimeout; @@ -81,7 +82,6 @@ abstract class PoolBase private final boolean isUseJdbc4Validation; private final boolean isIsolateInternalQueries; - private final AtomicReference lastConnectionFailure; private volatile boolean isValidChecked; diff --git a/src/test/java/com/zaxxer/hikari/pool/TestConnections.java b/src/test/java/com/zaxxer/hikari/pool/TestConnections.java index e8a486b0..dec9a169 100644 --- a/src/test/java/com/zaxxer/hikari/pool/TestConnections.java +++ b/src/test/java/com/zaxxer/hikari/pool/TestConnections.java @@ -584,6 +584,51 @@ public class TestConnections } } + @Test + public void testDataSourceRaisesErrorWhileInitializationTestQuery() throws SQLException + { + StubDataSourceWithErrorSwitch stubDataSource = new StubDataSourceWithErrorSwitch(); + stubDataSource.setErrorOnConnection(true); + + HikariConfig config = newHikariConfig(); + config.setMinimumIdle(1); + config.setConnectionTestQuery("VALUES 1"); + config.setDataSource(stubDataSource); + + try (HikariDataSource ds = new HikariDataSource(config); + Connection ignored = ds.getConnection()) { + fail("Initialization should have failed"); + } + catch (PoolInitializationException e) { + // passed + } + } + + @Test + public void testDataSourceRaisesErrorAfterInitializationTestQuery() + { + StubDataSourceWithErrorSwitch stubDataSource = new StubDataSourceWithErrorSwitch(); + + HikariConfig config = newHikariConfig(); + config.setMinimumIdle(0); + config.setMaximumPoolSize(2); + config.setConnectionTimeout(TimeUnit.SECONDS.toMillis(3)); + config.setConnectionTestQuery("VALUES 1"); + config.setInitializationFailTimeout(TimeUnit.SECONDS.toMillis(2)); + config.setDataSource(stubDataSource); + + try (HikariDataSource ds = new HikariDataSource(config)) { + // this will make datasource throws Error, which will become uncaught + stubDataSource.setErrorOnConnection(true); + try (Connection ignored = ds.getConnection()) { + fail("SQLException should occur!"); + } catch (SQLException e) { + // request will get timed-out + assertTrue(e.getMessage().contains("request timed out")); + } + } + } + @Test public void testPopulationSlowAcquisition() throws InterruptedException, SQLException { @@ -646,4 +691,23 @@ public class TestConnections fail("Failed to obtain connection"); } } + + class StubDataSourceWithErrorSwitch extends StubDataSource { + private boolean errorOnConnection = false; + + /** {@inheritDoc} */ + @Override + public Connection getConnection() throws SQLException { + if (!errorOnConnection) { + return new StubConnection(); + } + + throw new Error("Bad thing happens on datasource."); + } + + public void setErrorOnConnection(boolean errorOnConnection) { + this.errorOnConnection = errorOnConnection; + } + } + }