diff --git a/hikaricp-java6/src/main/java/com/zaxxer/hikari/HikariConfig.java b/hikaricp-java6/src/main/java/com/zaxxer/hikari/HikariConfig.java index 781e66a8..e4ffee90 100644 --- a/hikaricp-java6/src/main/java/com/zaxxer/hikari/HikariConfig.java +++ b/hikaricp-java6/src/main/java/com/zaxxer/hikari/HikariConfig.java @@ -78,7 +78,6 @@ public class HikariConfig implements HikariConfigMBean private boolean isAutoCommit; private boolean isReadOnly; private boolean isInitializationFailFast; - private boolean isJdbc4connectionTest; private boolean isIsolateInternalQueries; private boolean isRegisterMbeans; private DataSource dataSource; @@ -102,7 +101,6 @@ public class HikariConfig implements HikariConfigMBean connectionTimeout = CONNECTION_TIMEOUT; idleTimeout = IDLE_TIMEOUT; isAutoCommit = true; - isJdbc4connectionTest = true; isInitializationFailFast = true; minIdle = -1; maxPoolSize = 10; @@ -423,14 +421,16 @@ public class HikariConfig implements HikariConfigMBean this.isIsolateInternalQueries = isolate; } + @Deprecated public boolean isJdbc4ConnectionTest() { - return isJdbc4connectionTest; + return false; } + @Deprecated public void setJdbc4ConnectionTest(boolean useIsValid) { - this.isJdbc4connectionTest = useIsValid; + // ignored deprecated property } /** @@ -663,14 +663,6 @@ public class HikariConfig implements HikariConfigMBean logger.warn("both dataSource and dataSourceClassName are specified, ignoring dataSourceClassName"); } - if (connectionTestQuery != null) { - isJdbc4connectionTest = false; - } - else if (!isJdbc4connectionTest) { - logger.error("Either jdbc4ConnectionTest must be enabled or a connectionTestQuery must be specified"); - throw new IllegalStateException("Either jdbc4ConnectionTest must be enabled or a connectionTestQuery must be specified"); - } - if (transactionIsolationName != null) { PoolUtilities.getTransactionIsolation(transactionIsolationName); } diff --git a/hikaricp-java6/src/main/java/com/zaxxer/hikari/pool/HikariPool.java b/hikaricp-java6/src/main/java/com/zaxxer/hikari/pool/HikariPool.java index e93e4eaa..e2158de2 100644 --- a/hikaricp-java6/src/main/java/com/zaxxer/hikari/pool/HikariPool.java +++ b/hikaricp-java6/src/main/java/com/zaxxer/hikari/pool/HikariPool.java @@ -24,6 +24,7 @@ import static com.zaxxer.hikari.util.PoolUtilities.createInstance; import static com.zaxxer.hikari.util.PoolUtilities.createThreadPoolExecutor; import static com.zaxxer.hikari.util.PoolUtilities.elapsedTimeMs; import static com.zaxxer.hikari.util.PoolUtilities.executeSqlAutoCommit; +import static com.zaxxer.hikari.util.PoolUtilities.isJdbc40Compliant; import static com.zaxxer.hikari.util.PoolUtilities.isJdbc41Compliant; import static com.zaxxer.hikari.util.PoolUtilities.quietlyCloseConnection; import static com.zaxxer.hikari.util.PoolUtilities.quietlySleep; @@ -92,13 +93,13 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener private final String password; private final boolean isRecordMetrics; private final boolean isRegisteredMbeans; - private final boolean isJdbc4ConnectionTest; private final boolean isIsolateInternalQueries; private final long leakDetectionThreshold; private volatile boolean isShutdown; private volatile long connectionTimeout; private volatile boolean isUseNetworkTimeout; + private volatile boolean isUseJdbc4Validation; /** * Construct a HikariPool with the specified configuration. @@ -131,7 +132,6 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener this.isReadOnly = configuration.isReadOnly(); this.isAutoCommit = configuration.isAutoCommit(); this.isRegisteredMbeans = configuration.isRegisterMbeans(); - this.isJdbc4ConnectionTest = configuration.isJdbc4ConnectionTest(); this.catalog = configuration.getCatalog(); this.connectionCustomizer = initializeCustomizer(); @@ -414,6 +414,11 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener try { connection = (username == null && password == null) ? dataSource.getConnection() : dataSource.getConnection(username, password); isUseNetworkTimeout = isJdbc41Compliant(connection) && (configuration.getConnectionTimeout() != Integer.MAX_VALUE); + isUseJdbc4Validation = isJdbc40Compliant(connection); + if (!isUseJdbc4Validation && configuration.getConnectionTestQuery() == null) { + LOGGER.error("JDBC4 Connection.isValid() method not supported, connection test query must be configured"); + } + isUseJdbc4Validation &= configuration.getConnectionTestQuery() == null; final boolean timeoutEnabled = (configuration.getConnectionTimeout() != Integer.MAX_VALUE); final long timeoutMs = timeoutEnabled ? Math.max(250L, configuration.getConnectionTimeout()) : 0L; @@ -427,9 +432,7 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener connection.setAutoCommit(isAutoCommit); connection.setTransactionIsolation(transactionIsolation); connection.setReadOnly(isReadOnly); - if (catalog != null) { - connection.setCatalog(catalog); - } + connection.setCatalog(catalog); setNetworkTimeout(houseKeepingExecutorService, connection, networkTimeout, isUseNetworkTimeout); @@ -461,7 +464,7 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener final boolean timeoutEnabled = (configuration.getConnectionTimeout() != Integer.MAX_VALUE); int timeoutSec = timeoutEnabled ? (int) Math.max(1L, TimeUnit.MILLISECONDS.toSeconds(timeoutMs)) : 0; - if (isJdbc4ConnectionTest) { + if (isUseJdbc4Validation) { return connection.isValid(timeoutSec); } diff --git a/hikaricp-java6/src/main/java/com/zaxxer/hikari/util/PoolUtilities.java b/hikaricp-java6/src/main/java/com/zaxxer/hikari/util/PoolUtilities.java index 445004be..6a23342e 100644 --- a/hikaricp-java6/src/main/java/com/zaxxer/hikari/util/PoolUtilities.java +++ b/hikaricp-java6/src/main/java/com/zaxxer/hikari/util/PoolUtilities.java @@ -23,8 +23,10 @@ public final class PoolUtilities { public static final boolean IS_JAVA7; - private static volatile boolean IS_JDBC4; - private static volatile boolean jdbc4checked; + private static volatile boolean IS_JDBC40; + private static volatile boolean IS_JDBC41; + private static volatile boolean jdbc40checked; + private static volatile boolean jdbc41checked; private static volatile boolean queryTimeoutSupported = true; static { @@ -198,6 +200,34 @@ public final class PoolUtilities return executor; } + /** + * Return true if the driver appears to be JDBC 4.0 compliant. + * + * @param connection a Connection to check + * @return true if JDBC 4.1 compliance, false otherwise + * @throws SQLException re-thrown exception from Connection.getNetworkTimeout() + */ + public static boolean isJdbc40Compliant(final Connection connection) throws SQLException + { + if (jdbc40checked) { + return IS_JDBC40; + } + + try { + connection.isValid(100); // This will throw AbstractMethodError or SQLException in the case of a non-JDBC 41 compliant driver + IS_JDBC40 = true; + } + catch (AbstractMethodError e) { + IS_JDBC40 = false; + } + catch (SQLFeatureNotSupportedException e) { + IS_JDBC40 = false; + } + + jdbc40checked = true; + return IS_JDBC40; + } + /** * Return true if the driver appears to be JDBC 4.1 compliant. * @@ -207,23 +237,23 @@ public final class PoolUtilities */ public static boolean isJdbc41Compliant(final Connection connection) throws SQLException { - if (jdbc4checked) { - return IS_JDBC4; + if (jdbc41checked) { + return IS_JDBC41; } try { connection.getNetworkTimeout(); // This will throw AbstractMethodError or SQLException in the case of a non-JDBC 41 compliant driver - IS_JDBC4 = true; + IS_JDBC41 = true; } catch (AbstractMethodError e) { - IS_JDBC4 = false; + IS_JDBC41 = false; } catch (SQLFeatureNotSupportedException e) { - IS_JDBC4 = false; + IS_JDBC41 = false; } - jdbc4checked = true; - return IS_JDBC4; + jdbc41checked = true; + return IS_JDBC41; } /** diff --git a/hikaricp-java6/src/test/java/com/zaxxer/hikari/TestElf.java b/hikaricp-java6/src/test/java/com/zaxxer/hikari/TestElf.java index 0197e9ea..08cf8fd5 100644 --- a/hikaricp-java6/src/test/java/com/zaxxer/hikari/TestElf.java +++ b/hikaricp-java6/src/test/java/com/zaxxer/hikari/TestElf.java @@ -77,13 +77,17 @@ public final class TestElf public static void resetPoolUtilities() { try { - Field field = PoolUtilities.class.getDeclaredField("jdbc4checked"); + Field field = PoolUtilities.class.getDeclaredField("jdbc41checked"); field.setAccessible(true); field.setBoolean(null, false); field = PoolUtilities.class.getDeclaredField("queryTimeoutSupported"); field.setAccessible(true); field.setBoolean(null, true); + + field = PoolUtilities.class.getDeclaredField("jdbc40checked"); + field.setAccessible(true); + field.setBoolean(null, false); } catch (Exception e) { throw new RuntimeException(e); diff --git a/hikaricp-java6/src/test/java/com/zaxxer/hikari/TestValidation.java b/hikaricp-java6/src/test/java/com/zaxxer/hikari/TestValidation.java index c94ba16c..18352d29 100644 --- a/hikaricp-java6/src/test/java/com/zaxxer/hikari/TestValidation.java +++ b/hikaricp-java6/src/test/java/com/zaxxer/hikari/TestValidation.java @@ -251,21 +251,6 @@ public class TestValidation } } - @Test - public void validateMissingTest() - { - try { - HikariConfig config = new HikariConfig(); - config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); - config.setJdbc4ConnectionTest(false); - config.validate(); - Assert.fail(); - } - catch (IllegalStateException ise) { - Assert.assertTrue(ise.getMessage().contains("Either jdbc4ConnectionTest")); - } - } - @Test public void validateInvalidLifetime() { diff --git a/hikaricp/src/main/java/com/zaxxer/hikari/HikariConfig.java b/hikaricp/src/main/java/com/zaxxer/hikari/HikariConfig.java index 8c0d602c..74e45b80 100644 --- a/hikaricp/src/main/java/com/zaxxer/hikari/HikariConfig.java +++ b/hikaricp/src/main/java/com/zaxxer/hikari/HikariConfig.java @@ -78,7 +78,6 @@ public class HikariConfig implements HikariConfigMBean private boolean isAutoCommit; private boolean isReadOnly; private boolean isInitializationFailFast; - private boolean isJdbc4connectionTest; private boolean isIsolateInternalQueries; private boolean isRegisterMbeans; private DataSource dataSource; @@ -102,7 +101,6 @@ public class HikariConfig implements HikariConfigMBean connectionTimeout = CONNECTION_TIMEOUT; idleTimeout = IDLE_TIMEOUT; isAutoCommit = true; - isJdbc4connectionTest = true; isInitializationFailFast = true; minIdle = -1; maxPoolSize = 10; @@ -423,14 +421,16 @@ public class HikariConfig implements HikariConfigMBean this.isIsolateInternalQueries = isolate; } + @Deprecated public boolean isJdbc4ConnectionTest() { - return isJdbc4connectionTest; + return false; } + @Deprecated public void setJdbc4ConnectionTest(boolean useIsValid) { - this.isJdbc4connectionTest = useIsValid; + // ignored deprecated property } /** @@ -663,14 +663,6 @@ public class HikariConfig implements HikariConfigMBean logger.warn("both dataSource and dataSourceClassName are specified, ignoring dataSourceClassName"); } - if (connectionTestQuery != null) { - isJdbc4connectionTest = false; - } - else if (!isJdbc4connectionTest) { - logger.error("Either jdbc4ConnectionTest must be enabled or a connectionTestQuery must be specified"); - throw new IllegalStateException("Either jdbc4ConnectionTest must be enabled or a connectionTestQuery must be specified"); - } - if (transactionIsolationName != null) { PoolUtilities.getTransactionIsolation(transactionIsolationName); } diff --git a/hikaricp/src/main/java/com/zaxxer/hikari/pool/HikariPool.java b/hikaricp/src/main/java/com/zaxxer/hikari/pool/HikariPool.java index 7d60aba2..7537d996 100644 --- a/hikaricp/src/main/java/com/zaxxer/hikari/pool/HikariPool.java +++ b/hikaricp/src/main/java/com/zaxxer/hikari/pool/HikariPool.java @@ -23,6 +23,7 @@ import static com.zaxxer.hikari.util.PoolUtilities.createInstance; import static com.zaxxer.hikari.util.PoolUtilities.createThreadPoolExecutor; import static com.zaxxer.hikari.util.PoolUtilities.elapsedTimeMs; import static com.zaxxer.hikari.util.PoolUtilities.executeSqlAutoCommit; +import static com.zaxxer.hikari.util.PoolUtilities.isJdbc40Compliant; import static com.zaxxer.hikari.util.PoolUtilities.isJdbc41Compliant; import static com.zaxxer.hikari.util.PoolUtilities.quietlyCloseConnection; import static com.zaxxer.hikari.util.PoolUtilities.quietlySleep; @@ -91,13 +92,13 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener private final String password; private final boolean isRecordMetrics; private final boolean isRegisteredMbeans; - private final boolean isJdbc4ConnectionTest; private final boolean isIsolateInternalQueries; private final long leakDetectionThreshold; private volatile boolean isShutdown; private volatile long connectionTimeout; private volatile boolean isUseNetworkTimeout; + private volatile boolean isUseJdbc4Validation; /** * Construct a HikariPool with the specified configuration. @@ -130,7 +131,6 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener this.isReadOnly = configuration.isReadOnly(); this.isAutoCommit = configuration.isAutoCommit(); this.isRegisteredMbeans = configuration.isRegisterMbeans(); - this.isJdbc4ConnectionTest = configuration.isJdbc4ConnectionTest(); this.catalog = configuration.getCatalog(); this.connectionCustomizer = initializeCustomizer(); @@ -397,6 +397,11 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener try { connection = (username == null && password == null) ? dataSource.getConnection() : dataSource.getConnection(username, password); isUseNetworkTimeout = isJdbc41Compliant(connection) && (configuration.getConnectionTimeout() != Integer.MAX_VALUE); + isUseJdbc4Validation = isJdbc40Compliant(connection); + if (!isUseJdbc4Validation && configuration.getConnectionTestQuery() == null) { + LOGGER.error("JDBC4 Connection.isValid() method not supported, connection test query must be configured"); + } + isUseJdbc4Validation &= configuration.getConnectionTestQuery() == null; final boolean timeoutEnabled = (configuration.getConnectionTimeout() != Integer.MAX_VALUE); final long timeoutMs = timeoutEnabled ? Math.max(250L, configuration.getConnectionTimeout()) : 0L; @@ -410,9 +415,7 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener connection.setAutoCommit(isAutoCommit); connection.setTransactionIsolation(transactionIsolation); connection.setReadOnly(isReadOnly); - if (catalog != null) { - connection.setCatalog(catalog); - } + connection.setCatalog(catalog); setNetworkTimeout(houseKeepingExecutorService, connection, networkTimeout, isUseNetworkTimeout); @@ -444,7 +447,7 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener final boolean timeoutEnabled = (configuration.getConnectionTimeout() != Integer.MAX_VALUE); int timeoutSec = timeoutEnabled ? (int) Math.max(1L, TimeUnit.MILLISECONDS.toSeconds(timeoutMs)) : 0; - if (isJdbc4ConnectionTest) { + if (isUseJdbc4Validation) { return connection.isValid(timeoutSec); } diff --git a/hikaricp/src/main/java/com/zaxxer/hikari/util/PoolUtilities.java b/hikaricp/src/main/java/com/zaxxer/hikari/util/PoolUtilities.java index 6d65f099..e1a71304 100644 --- a/hikaricp/src/main/java/com/zaxxer/hikari/util/PoolUtilities.java +++ b/hikaricp/src/main/java/com/zaxxer/hikari/util/PoolUtilities.java @@ -20,8 +20,10 @@ import org.slf4j.Logger; public final class PoolUtilities { - private static volatile boolean IS_JDBC4; - private static volatile boolean jdbc4checked; + private static volatile boolean IS_JDBC40; + private static volatile boolean IS_JDBC41; + private static volatile boolean jdbc40checked; + private static volatile boolean jdbc41checked; private static volatile boolean queryTimeoutSupported = true; /** @@ -180,6 +182,31 @@ public final class PoolUtilities return executor; } + /** + * Return true if the driver appears to be JDBC 4.0 compliant. + * + * @param connection a Connection to check + * @return true if JDBC 4.1 compliance, false otherwise + * @throws SQLException re-thrown exception from Connection.getNetworkTimeout() + */ + public static boolean isJdbc40Compliant(final Connection connection) throws SQLException + { + if (jdbc40checked) { + return IS_JDBC40; + } + + try { + connection.isValid(100); // This will throw AbstractMethodError or SQLException in the case of a non-JDBC 41 compliant driver + IS_JDBC40 = true; + } + catch (AbstractMethodError | SQLFeatureNotSupportedException e) { + IS_JDBC40 = false; + } + + jdbc40checked = true; + return IS_JDBC40; + } + /** * Return true if the driver appears to be JDBC 4.1 compliant. * @@ -189,20 +216,20 @@ public final class PoolUtilities */ public static boolean isJdbc41Compliant(final Connection connection) throws SQLException { - if (jdbc4checked) { - return IS_JDBC4; + if (jdbc41checked) { + return IS_JDBC41; } try { connection.getNetworkTimeout(); // This will throw AbstractMethodError or SQLException in the case of a non-JDBC 41 compliant driver - IS_JDBC4 = true; + IS_JDBC41 = true; } catch (AbstractMethodError | SQLFeatureNotSupportedException e) { - IS_JDBC4 = false; + IS_JDBC41 = false; } - jdbc4checked = true; - return IS_JDBC4; + jdbc41checked = true; + return IS_JDBC41; } /** diff --git a/hikaricp/src/test/java/com/zaxxer/hikari/TestElf.java b/hikaricp/src/test/java/com/zaxxer/hikari/TestElf.java index 0197e9ea..08cf8fd5 100644 --- a/hikaricp/src/test/java/com/zaxxer/hikari/TestElf.java +++ b/hikaricp/src/test/java/com/zaxxer/hikari/TestElf.java @@ -77,13 +77,17 @@ public final class TestElf public static void resetPoolUtilities() { try { - Field field = PoolUtilities.class.getDeclaredField("jdbc4checked"); + Field field = PoolUtilities.class.getDeclaredField("jdbc41checked"); field.setAccessible(true); field.setBoolean(null, false); field = PoolUtilities.class.getDeclaredField("queryTimeoutSupported"); field.setAccessible(true); field.setBoolean(null, true); + + field = PoolUtilities.class.getDeclaredField("jdbc40checked"); + field.setAccessible(true); + field.setBoolean(null, false); } catch (Exception e) { throw new RuntimeException(e); diff --git a/hikaricp/src/test/java/com/zaxxer/hikari/TestValidation.java b/hikaricp/src/test/java/com/zaxxer/hikari/TestValidation.java index c94ba16c..18352d29 100644 --- a/hikaricp/src/test/java/com/zaxxer/hikari/TestValidation.java +++ b/hikaricp/src/test/java/com/zaxxer/hikari/TestValidation.java @@ -251,21 +251,6 @@ public class TestValidation } } - @Test - public void validateMissingTest() - { - try { - HikariConfig config = new HikariConfig(); - config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); - config.setJdbc4ConnectionTest(false); - config.validate(); - Assert.fail(); - } - catch (IllegalStateException ise) { - Assert.assertTrue(ise.getMessage().contains("Either jdbc4ConnectionTest")); - } - } - @Test public void validateInvalidLifetime() {