From 8053e39996585255621ca0b4e25b70a7874e6599 Mon Sep 17 00:00:00 2001 From: Yanming Zhou Date: Tue, 24 Sep 2024 01:25:09 +0800 Subject: [PATCH] Create SQLExceptionOverride instance when exceptionOverrideClassName loaded (#2133) Before this commit, exceptionOverrideClass may be loaded by different ClassLoader, and two instances are created but only the latter one is used. This commit make sure the class will only loaded once and only one instance is created. Fix GH-2124 Fix GH-2171 --- .../java/com/zaxxer/hikari/HikariConfig.java | 38 ++++++++++++++++--- .../java/com/zaxxer/hikari/pool/PoolBase.java | 2 +- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/zaxxer/hikari/HikariConfig.java b/src/main/java/com/zaxxer/hikari/HikariConfig.java index cff7fb0a2..13cdacccd 100644 --- a/src/main/java/com/zaxxer/hikari/HikariConfig.java +++ b/src/main/java/com/zaxxer/hikari/HikariConfig.java @@ -80,6 +80,7 @@ public class HikariConfig implements HikariConfigMXBean private String dataSourceJndiName; private String driverClassName; private String exceptionOverrideClassName; + private SQLExceptionOverride exceptionOverride; private String jdbcUrl; private String poolName; private String schema; @@ -913,8 +914,12 @@ public void setExceptionOverrideClassName(String exceptionOverrideClassName) throw new RuntimeException("Failed to load SQLExceptionOverride class " + exceptionOverrideClassName + " in either of HikariConfig class loader or Thread context classloader"); } + if (!SQLExceptionOverride.class.isAssignableFrom(overrideClass)) { + throw new RuntimeException("Loaded SQLExceptionOverride class " + exceptionOverrideClassName + " does not implement " + SQLExceptionOverride.class.getName()); + } + try { - overrideClass.getConstructor().newInstance(); + this.exceptionOverride = (SQLExceptionOverride) overrideClass.getConstructor().newInstance(); this.exceptionOverrideClassName = exceptionOverrideClassName; } catch (Exception e) { @@ -922,6 +927,29 @@ public void setExceptionOverrideClassName(String exceptionOverrideClassName) } } + + /** + * Get the SQLExceptionOverride instance created by {@link #setExceptionOverrideClassName(String)}. + * + * @return the SQLExceptionOverride instance, or null if {@link #setExceptionOverrideClassName(String)} is not called + * @see SQLExceptionOverride + */ + public SQLExceptionOverride getExceptionOverride() + { + return this.exceptionOverride; + } + + /** + * Set the user supplied SQLExceptionOverride instance. + * + * @param exceptionOverride the user supplied SQLExceptionOverride instance + * @see SQLExceptionOverride + */ + public void setExceptionOverride(SQLExceptionOverride exceptionOverride) { + checkIfSealed(); + this.exceptionOverride = exceptionOverride; + } + /** * Set the default transaction isolation level. The specified value is the * constant name from the Connection class, eg. @@ -990,15 +1018,15 @@ public void copyStateTo(HikariConfig other) // Private methods // *********************************************************************** - private Class attemptFromContextLoader(final String driverClassName) { + private Class attemptFromContextLoader(final String className) { final var threadContextClassLoader = Thread.currentThread().getContextClassLoader(); if (threadContextClassLoader != null) { try { - final var driverClass = threadContextClassLoader.loadClass(driverClassName); - LOGGER.debug("Driver class {} found in Thread context class loader {}", driverClassName, threadContextClassLoader); + final var driverClass = threadContextClassLoader.loadClass(className); + LOGGER.debug("Class {} found in Thread context class loader {}", className, threadContextClassLoader); return driverClass; } catch (ClassNotFoundException e) { - LOGGER.debug("Driver class {} not found in Thread context class loader {}, trying classloader {}", + LOGGER.debug("Class {} not found in Thread context class loader {}, trying classloader {}", driverClassName, threadContextClassLoader, this.getClass().getClassLoader()); } } diff --git a/src/main/java/com/zaxxer/hikari/pool/PoolBase.java b/src/main/java/com/zaxxer/hikari/pool/PoolBase.java index 0867db5dd..6ce3b616d 100644 --- a/src/main/java/com/zaxxer/hikari/pool/PoolBase.java +++ b/src/main/java/com/zaxxer/hikari/pool/PoolBase.java @@ -98,7 +98,7 @@ abstract class PoolBase this.schema = config.getSchema(); this.isReadOnly = config.isReadOnly(); this.isAutoCommit = config.isAutoCommit(); - this.exceptionOverride = UtilityElf.createInstance(config.getExceptionOverrideClassName(), SQLExceptionOverride.class); + this.exceptionOverride = config.getExceptionOverride(); this.transactionIsolation = UtilityElf.getTransactionIsolation(config.getTransactionIsolation()); this.isQueryTimeoutSupported = UNINITIALIZED;