From 6c064531ab7eb98f9db694d818ee0d0dc1d207c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Prante?= Date: Mon, 25 Mar 2024 17:09:36 +0100 Subject: [PATCH] use thread context class loader --- gradle.properties | 2 +- .../org/xbib/jdbc/connection/pool/Pool.java | 41 ++++++--- .../xbib/jdbc/connection/pool/PoolConfig.java | 91 +++++++++++-------- .../connection/pool/PoolEntryCreator.java | 3 +- .../pool/util/DefaultThreadFactory.java | 8 +- .../pool/util/DriverDataSource.java | 28 ++++-- .../pool/util/LoggingOutputStream.java | 26 ++++++ .../io/pool/jdbc/HouseKeeperCleanupTest.java | 6 +- .../xbib/jdbc/mariadb/test/MariaDBTest.java | 6 +- .../org/xbib/jdbc/query/util/DebugSql.java | 29 ++---- settings.gradle | 11 +-- 11 files changed, 157 insertions(+), 94 deletions(-) create mode 100644 jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/util/LoggingOutputStream.java diff --git a/gradle.properties b/gradle.properties index 111dc5c..1308a44 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ group = org.xbib name = database -version = 2.0.2 +version = 2.0.3 diff --git a/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/Pool.java b/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/Pool.java index ed78aec..ef5670c 100644 --- a/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/Pool.java +++ b/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/Pool.java @@ -118,7 +118,8 @@ public class Pool implements BagStateListener { * * @param config the config */ - public Pool(PoolConfig config) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { + public Pool(PoolConfig config) throws ClassNotFoundException, + NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { config.validate(); this.config = config; logger.log(Level.INFO, () -> "starting new pool: " + config.getPoolName()); @@ -146,18 +147,26 @@ public class Pool implements BagStateListener { checkFailFast(initializationTimeout); } ThreadFactory threadFactory = config.getThreadFactory(); + ClassLoader contextClassLoader = config.getContextClassLoader(); int maxPoolSize = config.getMaximumPoolSize(); LinkedBlockingQueue addConnectionQueue = new LinkedBlockingQueue<>(maxPoolSize); this.addConnectionQueueReadOnlyView = Collections.unmodifiableCollection(addConnectionQueue); this.addConnectionExecutor = createThreadPoolExecutor(addConnectionQueue, - poolName + " connection adder", threadFactory, new ThreadPoolExecutor.DiscardOldestPolicy()); + poolName + " connection adder", + threadFactory, + contextClassLoader, + new ThreadPoolExecutor.DiscardOldestPolicy()); this.closeConnectionExecutor = createThreadPoolExecutor(maxPoolSize, - poolName + " connection closer", threadFactory, new ThreadPoolExecutor.CallerRunsPolicy()); + poolName + " connection closer", + threadFactory, + contextClassLoader, + new ThreadPoolExecutor.CallerRunsPolicy()); this.leakTaskFactory = new ProxyLeakTaskFactory(config.getLeakDetectionThreshold(), houseKeepingExecutorService); this.houseKeeperTask = houseKeepingExecutorService.scheduleWithFixedDelay(new HouseKeeper(this), 100L, config.getHousekeepingPeriodMs(), TimeUnit.MILLISECONDS); if (Boolean.getBoolean("org.xbib.jdbc.connection.pool.blockUntilFilled") && config.getInitializationFailTimeout() > 1) { - addConnectionExecutor.setCorePoolSize(Math.min(16, Runtime.getRuntime().availableProcessors())); - addConnectionExecutor.setMaximumPoolSize(Math.min(16, Runtime.getRuntime().availableProcessors())); + int procs = Math.min(16, Runtime.getRuntime().availableProcessors()); + addConnectionExecutor.setCorePoolSize(procs); + addConnectionExecutor.setMaximumPoolSize(procs); final long startTime = ClockSource.currentTime(); while (ClockSource.elapsedMillis(startTime) < config.getInitializationFailTimeout() && getTotalConnections() < config.getMinimumIdle()) { quietlySleep(TimeUnit.MILLISECONDS.toMillis(100)); @@ -305,8 +314,11 @@ public class Pool implements BagStateListener { addConnectionExecutor.awaitTermination(getLoginTimeout(), TimeUnit.SECONDS); destroyHouseKeepingExecutorService(); bag.close(); - final ExecutorService assassinExecutor = createThreadPoolExecutor(config.getMaximumPoolSize(), poolName + " connection assassinator", - config.getThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy()); + final ExecutorService assassinExecutor = createThreadPoolExecutor(config.getMaximumPoolSize(), + poolName + " connection assassinator", + config.getThreadFactory(), + config.getContextClassLoader(), + new ThreadPoolExecutor.CallerRunsPolicy()); try { final long start = ClockSource.currentTime(); do { @@ -415,6 +427,7 @@ public class Pool implements BagStateListener { if (ds == null) { String dsClassName = config.getDataSourceClassName(); if (dsClassName != null) { + // we must use the system class loader Class clazz = Class.forName(dsClassName, true, ClassLoader.getSystemClassLoader()); ds = (DataSource) clazz.getDeclaredConstructor().newInstance(); } else if (url != null) { @@ -816,7 +829,8 @@ public class Pool implements BagStateListener { private ScheduledExecutorService initializeHouseKeepingExecutorService() { if (config.getScheduledExecutor() == null) { ThreadFactory threadFactory = Optional.ofNullable(config.getThreadFactory()).orElseGet(() -> - new DefaultThreadFactory(poolName + "-housekeeper", true)); + new DefaultThreadFactory(poolName + "-housekeeper", + Thread.currentThread().getContextClassLoader(), true)); ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1, threadFactory, new ThreadPoolExecutor.DiscardPolicy()); @@ -869,16 +883,18 @@ public class Pool implements BagStateListener { * * @param queueSize the queue size * @param threadName the thread name - * @param threadFactory an optional ThreadFactory + * @param threadFactory an optional ThreadFactory, if null, a DefaultThreadFactory will be used + * @param contextClassLoader the context class loader if the thread factory is null * @param policy the RejectedExecutionHandler policy * @return a ThreadPoolExecutor */ private ThreadPoolExecutor createThreadPoolExecutor(int queueSize, String threadName, ThreadFactory threadFactory, + ClassLoader contextClassLoader, RejectedExecutionHandler policy) { if (threadFactory == null) { - threadFactory = new DefaultThreadFactory(threadName, true); + threadFactory = new DefaultThreadFactory(threadName, contextClassLoader, true); } LinkedBlockingQueue queue = new LinkedBlockingQueue<>(queueSize); ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, @@ -899,9 +915,10 @@ public class Pool implements BagStateListener { private ThreadPoolExecutor createThreadPoolExecutor(BlockingQueue queue, String threadName, ThreadFactory threadFactory, + ClassLoader contextClassLoader, RejectedExecutionHandler policy) { if (threadFactory == null) { - threadFactory = new DefaultThreadFactory(threadName, true); + threadFactory = new DefaultThreadFactory(threadName, contextClassLoader, true); } ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 5, TimeUnit.SECONDS, queue, threadFactory, policy); @@ -977,7 +994,7 @@ public class Pool implements BagStateListener { * * @return true if we should create a connection, false if the need has disappeared */ - synchronized boolean shouldCreateAnotherConnection() { + public synchronized boolean shouldCreateAnotherConnection() { return getTotalConnections() < config.getMaximumPoolSize() && (bag.getWaitingThreadCount() > 0 || getIdleConnections() < config.getMinimumIdle()); } diff --git a/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/PoolConfig.java b/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/PoolConfig.java index b094205..bf5c48d 100644 --- a/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/PoolConfig.java +++ b/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/PoolConfig.java @@ -1,5 +1,6 @@ package org.xbib.jdbc.connection.pool; +import java.lang.reflect.InvocationTargetException; import java.sql.Connection; import java.util.Properties; import java.util.concurrent.ScheduledExecutorService; @@ -74,6 +75,8 @@ public class PoolConfig { private ThreadFactory threadFactory; + private ClassLoader contextClassLoader; + private ScheduledExecutorService scheduledExecutor; /** @@ -298,21 +301,21 @@ public class PoolConfig { } /** - * Get the name of the JDBC {@link DataSource} class used to create Connections. + * Set the fully qualified class name of the JDBC {@link DataSource} that will be used create Connections. * - * @return the fully qualified name of the JDBC {@link DataSource} class + * @param className the fully qualified name of the JDBC {@link DataSource} class */ - public String getDataSourceClassName() { - return dataSourceClassName; + public void setDataSourceClassName(String className) { + this.dataSourceClassName = className; } /** - * Set the fully qualified class name of the JDBC {@link DataSource} that will be used create Connections. + * Get the name of the JDBC {@link DataSource} class used to create Connections. * - * @param className the fully qualified name of the JDBC {@link DataSource} class + * @return the fully qualified name of the JDBC {@link DataSource} class */ - public void setDataSourceClassName(String className) { - this.dataSourceClassName = className; + public String getDataSourceClassName() { + return dataSourceClassName; } public Properties getProperties() { @@ -324,23 +327,47 @@ public class PoolConfig { } public void setDriverClassName(String driverClassName) { - Class driverClass = attemptFromContextLoader(driverClassName); + Class driverClass = null; + ClassLoader threadContextClassLoader = Thread.currentThread().getContextClassLoader(); + if (threadContextClassLoader != null) { + try { + driverClass = threadContextClassLoader.loadClass(driverClassName); + if (driverClass != null) { + logger.log(Level.FINE, () -> "driver class found in thread context class loader:" + driverClassName); + } + } catch (ClassNotFoundException e) { + logger.log(Level.FINE, () -> "failed to load driver class from thread context class loader" + driverClassName); + } + } try { if (driverClass == null) { - driverClass = this.getClass().getClassLoader().loadClass(driverClassName); - logger.log(Level.FINE, () -> "driver class found in the PoolConfig class classloader: " + driverClassName + " " + this.getClass().getClassLoader()); + driverClass = getClass().getClassLoader().loadClass(driverClassName); + if (driverClass != null) { + logger.log(Level.FINE, () -> "driver class found in the class classloader: " + driverClassName); + } } } catch (ClassNotFoundException e) { - logger.log(Level.SEVERE, "failed to load driver class from PoolConfig class classloader: " + driverClassName + " " + this.getClass().getClassLoader()); + logger.log(Level.FINE, () -> "failed to load driver class from class classloader: " + driverClassName); + } + try { + if (driverClass == null) { + driverClass = ClassLoader.getSystemClassLoader().loadClass(driverClassName); + if (driverClass != null) { + logger.log(Level.FINE, () -> "driver class found in the system class classloader: " + driverClassName); + + } + } + } catch (ClassNotFoundException e) { + logger.log(Level.SEVERE, () -> "failed to load driver class from system class classloader: " + driverClassName); } if (driverClass == null) { - throw new RuntimeException("failed to load driver class " + driverClassName + " in either of PoolConfig class loader or Thread context classloader"); + throw new IllegalStateException("failed to load driver class " + driverClassName); } try { driverClass.getConstructor().newInstance(); this.driverClassName = driverClassName; - } catch (Exception e) { - throw new RuntimeException("Failed to instantiate class " + driverClassName, e); + } catch (InstantiationException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + throw new IllegalStateException("failed to instantiate class " + driverClassName, e); } } @@ -549,6 +576,15 @@ public class PoolConfig { return housekeepingPeriodMs; } + /** + * Set the thread factory to be used to create threads. + * + * @param threadFactory the thread factory (setting to null causes the default thread factory to be used) + */ + public void setThreadFactory(ThreadFactory threadFactory) { + this.threadFactory = threadFactory; + } + /** * Get the thread factory used to create threads. * @@ -558,29 +594,12 @@ public class PoolConfig { return threadFactory; } - /** - * Set the thread factory to be used to create threads. - * - * @param threadFactory the thread factory (setting to null causes the default thread factory to be used) - */ - public void setThreadFactory(ThreadFactory threadFactory) { - this.threadFactory = threadFactory; + public void setContextClassLoader(ClassLoader contextClassLoader) { + this.contextClassLoader = contextClassLoader; } - private Class attemptFromContextLoader(String driverClassName) { - ClassLoader threadContextClassLoader = Thread.currentThread().getContextClassLoader(); - if (threadContextClassLoader != null) { - try { - Class driverClass = threadContextClassLoader.loadClass(driverClassName); - logger.log(Level.FINE, "Driver class found in Thread context class loader:" + - driverClassName + " " + threadContextClassLoader); - return driverClass; - } catch (ClassNotFoundException e) { - logger.log(Level.FINE, "Driver class not found in Thread context class loader, trying classloader: " + - driverClassName + " " + threadContextClassLoader + " " + this.getClass().getClassLoader()); - } - } - return null; + public ClassLoader getContextClassLoader() { + return contextClassLoader != null ? contextClassLoader : Thread.currentThread().getContextClassLoader(); } @SuppressWarnings("StatementWithEmptyBody") diff --git a/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/PoolEntryCreator.java b/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/PoolEntryCreator.java index 758758f..ad360bb 100644 --- a/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/PoolEntryCreator.java +++ b/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/PoolEntryCreator.java @@ -31,7 +31,8 @@ public class PoolEntryCreator implements Callable { final PoolEntry poolEntry = pool.createPoolEntry(); if (poolEntry != null) { pool.bag.add(poolEntry); - logger.log(Level.FINE, () -> MessageFormat.format("{0}: added connection {1} ", pool.poolName, poolEntry.getConnection())); + logger.log(Level.FINE, () -> MessageFormat.format("{0}: added connection {1} ", + pool.poolName, poolEntry.getConnection())); if (loggingPrefix != null) { pool.logPoolState(loggingPrefix); } diff --git a/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/util/DefaultThreadFactory.java b/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/util/DefaultThreadFactory.java index 5e5f49d..5dd88b6 100644 --- a/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/util/DefaultThreadFactory.java +++ b/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/util/DefaultThreadFactory.java @@ -6,10 +6,15 @@ public class DefaultThreadFactory implements ThreadFactory { private final String threadName; + private final ClassLoader contextClassLoader; + private final boolean daemon; - public DefaultThreadFactory(String threadName, boolean daemon) { + public DefaultThreadFactory(String threadName, + ClassLoader contextClassLoader, + boolean daemon) { this.threadName = threadName; + this.contextClassLoader = contextClassLoader; this.daemon = daemon; } @@ -17,6 +22,7 @@ public class DefaultThreadFactory implements ThreadFactory { public Thread newThread(Runnable r) { Thread thread = new Thread(r, threadName); thread.setDaemon(daemon); + thread.setContextClassLoader(contextClassLoader); return thread; } } diff --git a/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/util/DriverDataSource.java b/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/util/DriverDataSource.java index f0257ea..87a8e83 100644 --- a/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/util/DriverDataSource.java +++ b/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/util/DriverDataSource.java @@ -17,16 +17,21 @@ public class DriverDataSource implements DataSource { private static final Logger logger = Logger.getLogger(DriverDataSource.class.getName()); + static { + DriverManager.setLogWriter(new PrintWriter(new LoggingOutputStream(logger))); + DriverManager.drivers().forEach(d -> logger.log(Level.INFO, "found driver " + d)); + } + private static final String PASSWORD = "password"; private static final String USER = "user"; private static final String AUTOCOMMIT = "autocommit"; - private String jdbcUrl; - private final Properties driverProperties; + private String jdbcUrl; + private Driver driver; public DriverDataSource(String jdbcUrl, @@ -39,7 +44,9 @@ public class DriverDataSource implements DataSource { for (Entry entry : properties.entrySet()) { driverProperties.setProperty(entry.getKey().toString(), entry.getValue().toString()); } - logger.log(Level.INFO, "DriverManager looking for JDBC URL " + jdbcUrl); + if (jdbcUrl != null) { + logger.log(Level.INFO, () -> "DriverManager looking for JDBC URL " + jdbcUrl); + } if (username != null) { setUser(username); } @@ -85,16 +92,17 @@ public class DriverDataSource implements DataSource { } } } - final String sanitizedUrl = jdbcUrl.replaceAll("([?&;][^&#;=]*[pP]assword=)[^&#;]*", "$1"); - try { - if (driver == null) { + if (driver == null && jdbcUrl != null) { + final String sanitizedUrl = jdbcUrl.replaceAll("([?&;][^&#;=]*[pP]assword=)[^&#;]*", "$1"); + try { driver = DriverManager.getDriver(jdbcUrl); logger.log(Level.FINE, "Loaded driver with class name for jdbcUrl " + driver.getClass().getName() + " " + sanitizedUrl); - } else if (!driver.acceptsURL(jdbcUrl)) { - throw new RuntimeException("Driver " + driverClassName + " claims to not accept jdbcUrl " + sanitizedUrl); + if (!driver.acceptsURL(sanitizedUrl)) { + throw new RuntimeException("Driver " + driverClassName + " claims to not accept jdbcUrl " + sanitizedUrl); + } + } catch (SQLException e) { + throw new RuntimeException("Failed to get driver instance for jdbcUrl " + sanitizedUrl, e); } - } catch (SQLException e) { - throw new RuntimeException("Failed to get driver instance for jdbcUrl " + sanitizedUrl, e); } } diff --git a/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/util/LoggingOutputStream.java b/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/util/LoggingOutputStream.java new file mode 100644 index 0000000..5d5d349 --- /dev/null +++ b/jdbc-connection-pool/src/main/java/org/xbib/jdbc/connection/pool/util/LoggingOutputStream.java @@ -0,0 +1,26 @@ +package org.xbib.jdbc.connection.pool.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class LoggingOutputStream extends ByteArrayOutputStream { + + private final Logger logger; + + public LoggingOutputStream(Logger logger) { + super(); + this.logger = logger; + } + + @Override + public void flush() throws IOException { + super.flush(); + String s = new String(buf, 0, count); + if (!s.isEmpty()) { + logger.log(Level.FINE, s); + } + reset(); + } +} diff --git a/jdbc-connection-pool/src/test/java/org/xbib/io/pool/jdbc/HouseKeeperCleanupTest.java b/jdbc-connection-pool/src/test/java/org/xbib/io/pool/jdbc/HouseKeeperCleanupTest.java index af21255..52aedc8 100644 --- a/jdbc-connection-pool/src/test/java/org/xbib/io/pool/jdbc/HouseKeeperCleanupTest.java +++ b/jdbc-connection-pool/src/test/java/org/xbib/io/pool/jdbc/HouseKeeperCleanupTest.java @@ -17,8 +17,10 @@ public class HouseKeeperCleanupTest { private ScheduledThreadPoolExecutor executor; @BeforeEach - public void before() throws Exception { - ThreadFactory threadFactory = new DefaultThreadFactory("global-housekeeper", true); + public void before() { + ThreadFactory threadFactory = new DefaultThreadFactory("global-housekeeper", + Thread.currentThread().getContextClassLoader(), + true); executor = new ScheduledThreadPoolExecutor(1, threadFactory, new ThreadPoolExecutor.DiscardPolicy()); executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); diff --git a/jdbc-mariadb/src/test/java/org/xbib/jdbc/mariadb/test/MariaDBTest.java b/jdbc-mariadb/src/test/java/org/xbib/jdbc/mariadb/test/MariaDBTest.java index 9681b9b..725e8cf 100644 --- a/jdbc-mariadb/src/test/java/org/xbib/jdbc/mariadb/test/MariaDBTest.java +++ b/jdbc-mariadb/src/test/java/org/xbib/jdbc/mariadb/test/MariaDBTest.java @@ -27,7 +27,6 @@ public class MariaDBTest extends CommonTest { static MariaDBContainer mariaDBContainer; static { - // mariadb 10.3.6 mariaDBContainer = new MariaDBContainer<>("mariadb") .withDatabaseName("testDB") .withUsername("testUser") @@ -45,7 +44,7 @@ public class MariaDBTest extends CommonTest { } @Override - protected DatabaseProvider createDatabaseProvider(OptionsOverride options) throws Exception { + protected DatabaseProvider createDatabaseProvider(OptionsOverride options) { Config config = ConfigSupplier.of() .property("database.url", mariaDBContainer.getJdbcUrl()) .property("database.user", "testUser") @@ -95,12 +94,14 @@ public class MariaDBTest extends CommonTest { } @Disabled("MariaDB temporarily disabled") + @Test @Override public void intervals() { super.intervals(); } @Disabled("MariaDB temporarily disabled") + @Test @Override public void metadataColumnTypes() { super.metadataColumnTypes(); @@ -251,5 +252,4 @@ public class MariaDBTest extends CommonTest { + " str_varchar, str_fixed, str_lob, bin_blob, boolean_flag, date_millis, local_date from dbtest2 order by 1") .queryMany(SqlArgs::readRow)); } - } diff --git a/jdbc-query/src/main/java/org/xbib/jdbc/query/util/DebugSql.java b/jdbc-query/src/main/java/org/xbib/jdbc/query/util/DebugSql.java index 1b3daf8..e2921fd 100644 --- a/jdbc-query/src/main/java/org/xbib/jdbc/query/util/DebugSql.java +++ b/jdbc-query/src/main/java/org/xbib/jdbc/query/util/DebugSql.java @@ -18,13 +18,8 @@ import java.util.logging.Logger; * to prevent SQL injection or any other bad things. */ public class DebugSql { - public static final String PARAM_SQL_SEPARATOR = "\tParamSql:\t"; - public static String printDebugOnlySqlString(String sql, Object[] args, Options options) { - StringBuilder buf = new StringBuilder(); - printSql(buf, sql, args, false, true, options); - return buf.toString(); - } + public static final String PARAM_SQL_SEPARATOR = "\tParamSql:\t"; public static void printSql(StringBuilder buf, String sql, Object[] args, Options options) { printSql(buf, sql, args, true, options.isLogParameters(), options); @@ -65,8 +60,7 @@ public class DebugSql { for (int i = 0; i < argsToPrint.length; i++) { buf.append(removeTabs(sqlParts[i])); Object argToPrint = argsToPrint[i]; - if (argToPrint instanceof String) { - String argToPrintString = (String) argToPrint; + if (argToPrint instanceof String argToPrintString) { int maxLength = options.maxStringLengthParam(); if (argToPrintString.length() > maxLength && maxLength > 0) { buf.append("'").append(argToPrintString, 0, maxLength).append("...'"); @@ -77,16 +71,12 @@ public class DebugSql { } } else if (argToPrint instanceof SqlNull || argToPrint == null) { buf.append("null"); - } else if (argToPrint instanceof java.sql.Timestamp) { - java.sql.Timestamp timestamp = (java.sql.Timestamp) argToPrint; + } else if (argToPrint instanceof java.sql.Timestamp timestamp) { LocalDateTime localDateTime = timestamp.toLocalDateTime(); buf.append(localDateTime.toString()); - //buf.append(options.flavor().dateAsSqlFunction((Timestamp) argToPrint, options.calendarForTimestamps())); - } else if (argToPrint instanceof java.sql.Date) { - java.sql.Date date = (java.sql.Date) argToPrint; + } else if (argToPrint instanceof java.sql.Date date) { LocalDate localDate = date.toLocalDate(); buf.append(localDate.toString()); - //buf.append(options.flavor().localDateAsSqlFunction((java.sql.Date) argToPrint)); } else if (argToPrint instanceof Number) { buf.append(argToPrint); } else if (argToPrint instanceof Boolean) { @@ -144,25 +134,22 @@ public class DebugSql { } public static void logSuccess(String sqlType, Logger log, Metric metric, String sql, Object[] args, Options options) { - if (log.isLoggable(Level.FINE)) { - String msg = logMiddle('\t', sqlType, metric, null, sql, args, options); - log.fine(msg); + if (log.isLoggable(Level.FINEST)) { + log.log(Level.FINEST, () -> logMiddle('\t', sqlType, metric, null, sql, args, options)); } } public static void logWarning(String sqlType, Logger log, Metric metric, String errorCode, String sql, Object[] args, Options options, Throwable t) { if (log.isLoggable(Level.WARNING)) { - String msg = logMiddle(' ', sqlType, metric, errorCode, sql, args, options); - log.log(Level.WARNING, msg, t); + log.log(Level.WARNING, logMiddle(' ', sqlType, metric, errorCode, sql, args, options), t); } } public static void logError(String sqlType, Logger log, Metric metric, String errorCode, String sql, Object[] args, Options options, Throwable t) { if (log.isLoggable(Level.SEVERE)) { - String msg = logMiddle(' ', sqlType, metric, errorCode, sql, args, options); - log.log(Level.SEVERE, msg, t); + log.log(Level.SEVERE, logMiddle(' ', sqlType, metric, errorCode, sql, args, options), t); } } diff --git a/settings.gradle b/settings.gradle index 241719f..20de53e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,12 +2,12 @@ dependencyResolutionManagement { versionCatalogs { libs { version('gradle', '8.5') - library('mariadb', 'org.mariadb.jdbc', 'mariadb-java-client').version('3.1.3') - library('oracle', 'com.oracle.database.jdbc','ojdbc11').version('23.2.0.0') - library('postgresql', 'org.postgresql', 'postgresql').version('42.6.0') + library('mariadb', 'org.mariadb.jdbc', 'mariadb-java-client').version('3.3.3') + library('oracle', 'com.oracle.database.jdbc', 'ojdbc11').version('23.3.0.23.09') + library('postgresql', 'org.postgresql', 'postgresql').version('42.7.3') } testLibs { - version('junit', '5.10.1') + version('junit', '5.10.2') version('testcontainers', '1.19.1') library('junit-jupiter-api', 'org.junit.jupiter', 'junit-jupiter-api').versionRef('junit') library('junit-jupiter-params', 'org.junit.jupiter', 'junit-jupiter-params').versionRef('junit') @@ -18,9 +18,6 @@ dependencyResolutionManagement { library('derby', 'org.apache.derby', 'derby').version('10.16.1.1') library('hsqldb', 'org.hsqldb', 'hsqldb').version('2.7.1') library('h2', 'com.h2database', 'h2').version('2.1.214') - library('mariadb', 'org.mariadb.jdbc', 'mariadb-java-client').version('3.1.3') - library('oracle', 'com.oracle.database.jdbc','ojdbc11').version('23.2.0.0') - library('postgresql', 'org.postgresql', 'postgresql').version('42.6.0') library('mockito-core', 'org.mockito', 'mockito-core').version('5.3.1') library('testcontainers', 'org.testcontainers', 'testcontainers').versionRef('testcontainers') library('testcontainers-junit-jupiter', 'org.testcontainers', 'junit-jupiter').versionRef('testcontainers')