Skip to content

Commit

Permalink
Create SQLExceptionOverride instance when exceptionOverrideClassName …
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
quaff authored Sep 23, 2024
1 parent 82c82ad commit 8053e39
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 6 deletions.
38 changes: 33 additions & 5 deletions src/main/java/com/zaxxer/hikari/HikariConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -913,15 +914,42 @@ 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) {
throw new RuntimeException("Failed to instantiate class " + exceptionOverrideClassName, e);
}
}


/**
* 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 <code>Connection</code> class, eg.
Expand Down Expand Up @@ -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());
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/zaxxer/hikari/pool/PoolBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 8053e39

Please sign in to comment.