-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 Mark,
On 8/26/20 11:19, ma...@apache.org wrote: > This is an automated email from the ASF dual-hosted git > repository. > > markt pushed a commit to branch master in repository > https://gitbox.apache.org/repos/asf/tomcat.git > > commit f1c4210470a268ec6830a95ab219f418a7e775fb Author: Mark Thomas > <ma...@apache.org> AuthorDate: Wed Aug 26 16:15:50 2020 +0100 > > Update Commons DBCP to latest It looks like, among other things, this includes the fix for https://issues.apache.org/jira/browse/DBCP-559 If so: hooray! Can you confirm? Thanks, - -chris > --- MERGE.txt | 2 +- > .../apache/tomcat/dbcp/dbcp2/BasicDataSource.java | 187 > +++++++++--------- > .../tomcat/dbcp/dbcp2/BasicDataSourceFactory.java | 11 +- > .../tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java | 29 +++ > .../tomcat/dbcp/dbcp2/DelegatingConnection.java | 4 +- > .../tomcat/dbcp/dbcp2/PoolableConnection.java | 3 + > .../dbcp/dbcp2/PoolableConnectionFactory.java | 14 ++ > .../tomcat/dbcp/dbcp2/PoolingConnection.java | 220 > +++++++++++---------- > .../dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java | 28 +-- > .../dbcp2/datasources/CPDSConnectionFactory.java | 3 +- > .../dbcp2/datasources/InstanceKeyDataSource.java | 8 +- > .../dbcp/dbcp2/datasources/package-info.java | 2 +- > .../dbcp/dbcp2/managed/BasicManagedDataSource.java | 3 +- > .../dbcp2/managed/LocalXAConnectionFactory.java | 21 +- > webapps/docs/changelog.xml | 4 + 15 files > changed, 323 insertions(+), 216 deletions(-) > > diff --git a/MERGE.txt b/MERGE.txt index 79fc82e..b8c152d 100644 > --- a/MERGE.txt +++ b/MERGE.txt @@ -69,4 +69,4 @@ Sub-tree > src/main/java/org/apache/commons/dbcp2 > src/main/resources/org/apache/commons/dbcp2 The SHA1 ID / tag for > the most recent commit to be merged to Tomcat is: > -a363906bf7a039f79c07fa3c68b082a69ae035d7 (2019-12-06) > +6d232e547d5725e419832fc514fc0348aa897e7c (2020-08-11) diff --git > a/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java > b/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java index > 0293e9a..31faa61 100644 --- > a/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java +++ > b/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java @@ -63,17 > +63,6 @@ import > org.apache.tomcat.dbcp.pool2.impl.GenericObjectPoolConfig; */ > public class BasicDataSource implements DataSource, > BasicDataSourceMXBean, MBeanRegistration, AutoCloseable { > > - /** - * @since 2.0 - */ - private class > PaGetConnection implements PrivilegedExceptionAction<Connection> { > - - @Override - public Connection run() throws > SQLException { - return > createDataSource().getConnection(); - } - } - private > static final Log log = LogFactory.getLog(BasicDataSource.class); > > static { @@ -220,6 +209,8 @@ public class BasicDataSource > implements DataSource, BasicDataSourceMXBean, MBean */ private > boolean poolPreparedStatements = false; > > + private boolean clearStatementPoolOnReturn = false; + /** * > <p> * The maximum number of open statements that can be allocated > from the statement pool at the same time, or negative @@ -402,7 > +393,7 @@ public class BasicDataSource implements DataSource, > BasicDataSourceMXBean, MBean * </p> * <p> * Attempts to acquire > connections using {@link #getConnection()} after this method has > been invoked result in - * SQLExceptions. + * > SQLExceptions. To reopen a datasource that has been closed using > this method, use {@link #start()}. * </p> * <p> * This method is > idempotent - i.e., closing an already closed BasicDataSource has no > effect and does not generate @@ -448,7 +439,7 @@ public class > BasicDataSource implements DataSource, BasicDataSourceMXBean, > MBean } > > /** - * Creates a JDBC connection factory for this datasource. > The JDBC driver is loaded using the following algorithm: + * > Creates a JDBC connection factory for this data source. The JDBC > driver is loaded using the following algorithm: * <ol> * <li>If a > Driver instance has been specified via {@link #setDriver(Driver)} > use it</li> * <li>If no Driver instance was specified and {@link > #driverClassName} is specified that class is loaded using the @@ > -471,6 +462,7 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean return > ConnectionFactoryFactory.createConnectionFactory(this, > DriverFactory.createDriver(this)); } > > + /** * Creates a connection pool for this datasource. This method > only exists so subclasses can replace the * implementation class. > @@ -530,7 +522,6 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean if (dataSource != null) { > return dataSource; } - jmxRegister(); > > // create factory which returns raw physical connections @@ -544,10 > +535,8 @@ public class BasicDataSource implements DataSource, > BasicDataSourceMXBean, MBean > poolableConnectionFactory.setPoolStatements(poolPreparedStatements); > > poolableConnectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedSt atements); > success = true; - } catch (final SQLException se) { + > } catch (final SQLException | RuntimeException se) { throw se; - > } catch (final RuntimeException rte) { - throw rte; > } catch (final Exception ex) { throw new SQLException("Error > creating connection factory", ex); } @@ -564,10 +553,8 @@ public > class BasicDataSource implements DataSource, BasicDataSourceMXBean, > MBean newDataSource = createDataSourceInstance(); > newDataSource.setLogWriter(logWriter); success = true; - > } catch (final SQLException se) { + } catch (final > SQLException | RuntimeException se) { throw se; - } > catch (final RuntimeException rte) { - throw rte; } > catch (final Exception ex) { throw new SQLException("Error creating > datasource", ex); } finally { @@ -654,6 +641,7 @@ public class > BasicDataSource implements DataSource, BasicDataSourceMXBean, > MBean connectionFactory.setDefaultSchema(defaultSchema); > connectionFactory.setCacheState(cacheState); > connectionFactory.setPoolStatements(poolPreparedStatements); + > connectionFactory.setClearStatementPoolOnReturn(clearStatementPoolOnRe turn); > > connectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements ); > connectionFactory.setMaxConnLifetimeMillis(maxConnLifetimeMillis); > connectionFactory.setRollbackOnReturn(getRollbackOnReturn()); @@ > -687,10 +675,7 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean * @return The print writer > used by this configuration to log information on abandoned > objects. */ public PrintWriter getAbandonedLogWriter() { - > if (abandonedConfig != null) { - return > abandonedConfig.getLogWriter(); - } - return null; + > return abandonedConfig == null ? null : > abandonedConfig.getLogWriter(); } > > /** @@ -702,10 +687,7 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean */ @Override public > boolean getAbandonedUsageTracking() { - if (abandonedConfig > != null) { - return > abandonedConfig.getUseUsageTracking(); - } - return > false; + return abandonedConfig == null ? false : > abandonedConfig.getUseUsageTracking(); } > > /** @@ -738,7 +720,7 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean @Override public > Connection getConnection() throws SQLException { if > (Utils.IS_SECURITY_ENABLED) { - final > PrivilegedExceptionAction<Connection> action = new > PaGetConnection(); + final > PrivilegedExceptionAction<Connection> action = () -> > createDataSource().getConnection(); try { return > AccessController.doPrivileged(action); } catch (final > PrivilegedActionException e) { @@ -790,10 +772,7 @@ public class > BasicDataSource implements DataSource, BasicDataSourceMXBean, > MBean */ public List<String> getConnectionInitSqls() { final > List<String> result = connectionInitSqls; - if (result == > null) { - return Collections.emptyList(); - } - > return result; + return result == null ? > Collections.emptyList() : result; } > > /** @@ -884,10 +863,7 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean */ public Set<String> > getDisconnectionSqlCodes() { final Set<String> result = > disconnectionSqlCodes; - if (result == null) { - > return Collections.emptySet(); - } - return result; + > return result == null ? Collections.emptySet() : result; } > > /** @@ -1021,10 +997,7 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean */ @Override public > boolean getLogAbandoned() { - if (abandonedConfig != null) > { - return abandonedConfig.getLogAbandoned(); - > } - return false; + return abandonedConfig == null ? > false : abandonedConfig.getLogAbandoned(); } > > /** @@ -1055,8 +1028,7 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean */ @Override public int > getLoginTimeout() throws SQLException { - // This method > isn't supported by the PoolingDataSource returned by the - > // createDataSource + // This method isn't supported by the > PoolingDataSource returned by the createDataSource throw new > UnsupportedOperationException("Not supported by BasicDataSource"); > } > > @@ -1170,10 +1142,7 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean public int getNumActive() > { // Copy reference to avoid NPE if close happens after null check > final GenericObjectPool<PoolableConnection> pool = connectionPool; > - if (pool != null) { - return > pool.getNumActive(); - } - return 0; + return > pool == null ? 0 : pool.getNumActive(); } > > /** @@ -1185,10 +1154,7 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean public int getNumIdle() { > // Copy reference to avoid NPE if close happens after null check > final GenericObjectPool<PoolableConnection> pool = connectionPool; > - if (pool != null) { - return > pool.getNumIdle(); - } - return 0; + return > pool == null ? 0 : pool.getNumIdle(); } > > /** @@ -1246,10 +1212,7 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean */ @Override public > boolean getRemoveAbandonedOnBorrow() { - if (abandonedConfig > != null) { - return > abandonedConfig.getRemoveAbandonedOnBorrow(); - } - > return false; + return abandonedConfig == null ? false : > abandonedConfig.getRemoveAbandonedOnBorrow(); } > > /** @@ -1270,10 +1233,7 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean */ @Override public > boolean getRemoveAbandonedOnMaintenance() { - if > (abandonedConfig != null) { - return > abandonedConfig.getRemoveAbandonedOnMaintenance(); - } - > return false; + return abandonedConfig == null ? false : > abandonedConfig.getRemoveAbandonedOnMaintenance(); } > > /** @@ -1298,10 +1258,7 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean */ @Override public int > getRemoveAbandonedTimeout() { - if (abandonedConfig != null) > { - return abandonedConfig.getRemoveAbandonedTimeout(); > - } - return 300; + return abandonedConfig == > null ? 300 : abandonedConfig.getRemoveAbandonedTimeout(); } > > /** @@ -1478,7 +1435,18 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean } > > /** - * If true, this data source is closed and no more > connections can be retrieved from this datasource. + * Returns > true if the statement pool is cleared when the connection is > returned to its pool. + * + * @return true if the statement > pool is cleared at connection return + * @since 2.8.0 + */ > + @Override + public boolean isClearStatementPoolOnReturn() > { + return clearStatementPoolOnReturn; + } + + /** + > * If true, this data source is closed and no more connections can > be retrieved from this data source. * * @return true, if the data > source is closed; false otherwise */ @@ -1591,6 +1559,31 @@ public > class BasicDataSource implements DataSource, BasicDataSourceMXBean, > MBean } > > /** + * Restarts the datasource. + * <p> + * This > method calls {@link #close()} and {@link #start()} in sequence > within synchronized scope so any + * connection requests that > come in while the datsource is shutting down will be served by the > new pool. + * <p> + * Idle connections that are stored in > the connection pool when this method is invoked are closed, but + > * connections that are checked out to clients when this method is > invoked are not affected. When client + * applications > subsequently invoke {@link Connection#close()} to return these > connections to the pool, the + * underlying JDBC connections > are closed. These connections do not count in {@link > #getMaxTotal()} or + * {@link #getNumActive()} after invoking > this method. For example, if there are 3 connections checked out > by + * clients when {@link #restart()} is invoked, after this > method is called, {@link #getNumActive()} will + * return 0 and > up to {@link #getMaxTotal()} + 3 connections may be open until the > connections sourced from + * the original pool are returned. + > * <p> + * The new connection pool created by this method is > initialized with currently set configuration properties. + * + > * @throws SQLException if an error occurs initializing the > datasource + */ + @Override + public synchronized void > restart() throws SQLException { + close(); + > start(); + } + + /** * Sets the print writer to be used by > this configuration to log information on abandoned objects. * * > @param logWriter The new log writer @@ -1655,8 +1648,6 @@ public > class BasicDataSource implements DataSource, BasicDataSourceMXBean, > MBean this.autoCommitOnReturn = autoCommitOnReturn; } > > - // ----------------------------------------------------- > DataSource Methods - /** * Sets the state caching flag. * @@ > -1667,17 +1658,24 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean } > > /** + * Sets whether the pool of statements (which was enabled > with {@link #setPoolPreparedStatements(boolean)}) should + * be > cleared when the connection is returned to its pool. Default is > false. + * + * @param clearStatementPoolOnReturn clear or > not + * @since 2.8.0 + */ + public void > setClearStatementPoolOnReturn(final boolean > clearStatementPoolOnReturn) { + > this.clearStatementPoolOnReturn = clearStatementPoolOnReturn; + > } + + /** * Sets the ConnectionFactory class name. * * @param > connectionFactoryClassName A class name. * @since 2.7.0 */ public > void setConnectionFactoryClassName(final String > connectionFactoryClassName) { - if > (isEmpty(connectionFactoryClassName)) { - > this.connectionFactoryClassName = null; - } else { - > this.connectionFactoryClassName = connectionFactoryClassName; - > } + this.connectionFactoryClassName = > isEmpty(connectionFactoryClassName) ? null : > connectionFactoryClassName; } > > /** @@ -1768,11 +1766,7 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean * @param defaultCatalog > the default catalog */ public void setDefaultCatalog(final String > defaultCatalog) { - if (isEmpty(defaultCatalog)) { - > this.defaultCatalog = null; - } else { - > this.defaultCatalog = defaultCatalog; - } + > this.defaultCatalog = isEmpty(defaultCatalog) ? null : > defaultCatalog; } > > /** @@ -1815,11 +1809,7 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean * @since 2.5.0 */ public > void setDefaultSchema(final String defaultSchema) { - if > (isEmpty(defaultSchema)) { - this.defaultSchema = null; > - } else { - this.defaultSchema = defaultSchema; > - } + this.defaultSchema = isEmpty(defaultSchema) ? > null : defaultSchema; } > > /** @@ -1920,11 +1910,7 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean * @param driverClassName > the class name of the JDBC driver */ public synchronized void > setDriverClassName(final String driverClassName) { - if > (isEmpty(driverClassName)) { - this.driverClassName = > null; - } else { - this.driverClassName = > driverClassName; - } + this.driverClassName = > isEmpty(driverClassName) ? null : driverClassName; } > > /** @@ -2409,11 +2395,7 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean * @param validationQuery > the new value for the validation query */ public void > setValidationQuery(final String validationQuery) { - if > (isEmpty(validationQuery)) { - this.validationQuery = > null; - } else { - this.validationQuery = > validationQuery; - } + this.validationQuery = > isEmpty(validationQuery) ? null : validationQuery; } > > /** @@ -2432,6 +2414,29 @@ public class BasicDataSource implements > DataSource, BasicDataSourceMXBean, MBean } > > /** + * Starts the datasource. + * <p> + * It is not > necessary to call this method before using a newly created > BasicDataSource instance, but + * calling it in that context > causes the datasource to be immediately initialized (instead of > waiting for + * the first {@link #getConnection()} request). > Its primary use is to restart and reinitialize a + * datasource > that has been closed. + * <p> + * When this method is > called after {@link #close()}, connections checked out by clients + > * before the datasource was stopped do not count in {@link > #getMaxTotal()} or {@link #getNumActive()}. + * For example, if > there are 3 connections checked out by clients when {@link > #close()} is invoked and they are + * not returned before > {@link #start()} is invoked, after this method is called, {@link > #getNumActive()} will + * return 0. These connections will be > physically closed when they are returned, but they will not count > against + * the maximum allowed in the newly started > datasource. + * + * @throws SQLException if an error occurs > initializing the datasource + */ + @Override + public > synchronized void start() throws SQLException { + closed = > false; + createDataSource(); + } + + /** * Starts the > connection pool maintenance task, if configured. */ protected void > startPoolMaintenance() { diff --git > a/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java > b/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java > index 158b944..b8ae8f2 100644 --- > a/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java +++ > b/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java @@ > -100,6 +100,7 @@ public class BasicDataSourceFactory implements > ObjectFactory { private static final String PROP_LOG_ABANDONED = > "logAbandoned"; private static final String > PROP_ABANDONED_USAGE_TRACKING = "abandonedUsageTracking"; private > static final String PROP_POOL_PREPARED_STATEMENTS = > "poolPreparedStatements"; + private static final String > PROP_CLEAR_STATEMENT_POOL_ON_RETURN = > "clearStatementPoolOnReturn"; private static final String > PROP_MAX_OPEN_PREPARED_STATEMENTS = "maxOpenPreparedStatements"; > private static final String PROP_CONNECTION_PROPERTIES = > "connectionProperties"; private static final String > PROP_MAX_CONN_LIFETIME_MILLIS = "maxConnLifetimeMillis"; @@ -140,6 > +141,7 @@ public class BasicDataSourceFactory implements > ObjectFactory { PROP_URL, PROP_USER_NAME, PROP_VALIDATION_QUERY, > PROP_VALIDATION_QUERY_TIMEOUT, PROP_CONNECTION_INIT_SQLS, > PROP_ACCESS_TO_UNDERLYING_CONNECTION_ALLOWED, > PROP_REMOVE_ABANDONED_ON_BORROW, > PROP_REMOVE_ABANDONED_ON_MAINTENANCE, > PROP_REMOVE_ABANDONED_TIMEOUT, PROP_LOG_ABANDONED, > PROP_ABANDONED_USAGE_TRACKING, PROP_POOL_PREPARED_STATEMENTS, + > PROP_CLEAR_STATEMENT_POOL_ON_RETURN, > PROP_MAX_OPEN_PREPARED_STATEMENTS, PROP_CONNECTION_PROPERTIES, > PROP_MAX_CONN_LIFETIME_MILLIS, PROP_LOG_EXPIRED_CONNECTIONS, > PROP_ROLLBACK_ON_RETURN, PROP_ENABLE_AUTO_COMMIT_ON_RETURN, > PROP_DEFAULT_QUERY_TIMEOUT, PROP_FAST_FAIL_VALIDATION, > PROP_DISCONNECTION_SQL_CODES, PROP_JMX_NAME, @@ -255,7 +257,7 @@ > public class BasicDataSourceFactory implements ObjectFactory { > final List<String> infoMessages) { final List<String> > allPropsAsList = Arrays.asList(ALL_PROPERTIES); final String > nameString = name != null ? "Name = " + name.toString() + " " : > ""; - if (NUPROP_WARNTEXT != null && > !NUPROP_WARNTEXT.keySet().isEmpty()) { + if (NUPROP_WARNTEXT > != null && !NUPROP_WARNTEXT.isEmpty()) { for (final String > propertyName : NUPROP_WARNTEXT.keySet()) { final RefAddr ra = > ref.get(propertyName); if (ra != null && > !allPropsAsList.contains(ra.getType())) { @@ -275,7 +277,7 @@ > public class BasicDataSourceFactory implements ObjectFactory { > final String propertyName = ra.getType(); // If property name is > not in the properties list, we haven't warned on it // and it is > not in the "silent" list, tell user we are ignoring it. - > if (!(allPropsAsList.contains(propertyName) || > NUPROP_WARNTEXT.keySet().contains(propertyName) + if > (!(allPropsAsList.contains(propertyName) || > NUPROP_WARNTEXT.containsKey(propertyName) || > SILENT_PROPERTIES.contains(propertyName))) { final String > propertyValue = ra.getContent().toString(); final StringBuilder > stringBuilder = new StringBuilder(nameString); @@ -490,6 +492,11 @@ > public class BasicDataSourceFactory implements ObjectFactory { > dataSource.setPoolPreparedStatements(Boolean.valueOf(value).booleanVal ue()); > > } > > + value = > properties.getProperty(PROP_CLEAR_STATEMENT_POOL_ON_RETURN); + > if (value != null) { + > dataSource.setClearStatementPoolOnReturn(Boolean.valueOf(value).boolea nValue()); > > + } > + value = > properties.getProperty(PROP_MAX_OPEN_PREPARED_STATEMENTS); if > (value != null) { > dataSource.setMaxOpenPreparedStatements(Integer.parseInt(value)); > diff --git > a/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java > b/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java > index 687786e..5dc6b7a 100644 --- > a/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java +++ > b/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java @@ > -16,6 +16,8 @@ */ package org.apache.tomcat.dbcp.dbcp2; > > +import java.sql.SQLException; + /** * Defines the methods that > will be made available via JMX. * @@ -132,6 +134,16 @@ public > interface BasicDataSourceMXBean { boolean > isPoolPreparedStatements(); > > /** + * See {@link > BasicDataSource#isClearStatementPoolOnReturn()} + * + * > @return {@link BasicDataSource#isClearStatementPoolOnReturn()} + > * @since 2.8.0 + */ + default boolean > isClearStatementPoolOnReturn() { + return false; + } + + > /** * See {@link BasicDataSource#getMaxOpenPreparedStatements()} * > * @return {@link BasicDataSource#getMaxOpenPreparedStatements()} @@ > -315,4 +327,21 @@ public interface BasicDataSourceMXBean { * @since > 2.1 */ String[] getDisconnectionSqlCodesAsArray(); + + /** + > * See {@link BasicDataSource#start()} + * + * @throws > SQLException if an error occurs initializing the datasource + > * + * @since 2.8 + */ + default void start() throws > SQLException {} + + /** + * See {@link > BasicDataSource#restart()} + * @throws SQLException if an error > occurs initializing the datasource + * + * @since 2.8 + > */ + default void restart() throws SQLException {} } diff --git > a/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java > b/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java index > c215d03..45e4dd6 100644 --- > a/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java +++ > b/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java @@ > -532,7 +532,7 @@ public class DelegatingConnection<C extends > Connection> extends AbandonedTrace i try { > connection.setAutoCommit(autoCommit); if (cacheState) { - > autoCommitCached = Boolean.valueOf(autoCommit); + > autoCommitCached = Boolean.valueOf(connection.getAutoCommit()); } } > catch (final SQLException e) { autoCommitCached = null; @@ -556,7 > +556,7 @@ public class DelegatingConnection<C extends Connection> > extends AbandonedTrace i try { connection.setReadOnly(readOnly); if > (cacheState) { - readOnlyCached = > Boolean.valueOf(readOnly); + readOnlyCached = > Boolean.valueOf(connection.isReadOnly()); } } catch (final > SQLException e) { readOnlyCached = null; diff --git > a/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java > b/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java index > 9c15c7e..bdca159 100644 --- > a/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java +++ > b/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java @@ > -124,6 +124,9 @@ public class PoolableConnection extends > DelegatingConnection<Connection> impleme protected void passivate() > throws SQLException { super.passivate(); setClosedInternal(true); + > if (getDelegateInternal() instanceof PoolingConnection) { + > ((PoolingConnection) > getDelegateInternal()).connectionReturnedToPool(); + } } > > /** diff --git > a/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java > b/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java > index 4123d16..b25bb9a 100644 --- > a/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java > +++ > b/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java > @@ -84,6 +84,8 @@ public class PoolableConnectionFactory implements > PooledObjectFactory<PoolableCo > > private boolean poolStatements; > > + private boolean clearStatementPoolOnReturn; + private int > maxOpenPreparedStatements = > GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY; > > private long maxConnLifetimeMillis = -1; @@ -392,6 +394,7 @@ public > class PoolableConnectionFactory implements > PooledObjectFactory<PoolableCo final KeyedObjectPool<PStmtKey, > DelegatingPreparedStatement> stmtPool = new > GenericKeyedObjectPool<>( poolingConn, config); > poolingConn.setStatementPool(stmtPool); + > poolingConn.setClearStatementPoolOnReturn(clearStatementPoolOnReturn); > > poolingConn.setCacheState(cacheState); > } > > @@ -597,6 +600,17 @@ public class PoolableConnectionFactory > implements PooledObjectFactory<PoolableCo this.poolStatements = > poolStatements; } > > + /** + * Sets whether the pool of statements (which was > enabled with {@link #setPoolStatements(boolean)}) should + * be > cleared when the connection is returned to its pool. Default is > false. + * + * @param clearStatementPoolOnReturn clear or > not + * @since 2.8.0 + */ + public void > setClearStatementPoolOnReturn(final boolean > clearStatementPoolOnReturn) { + > this.clearStatementPoolOnReturn = clearStatementPoolOnReturn; + > } + public void setRollbackOnReturn(final boolean rollbackOnReturn) > { this.rollbackOnReturn = rollbackOnReturn; } diff --git > a/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java > b/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java index > 86e6d4e..8615074 100644 --- > a/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java +++ > b/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java @@ -65,6 > +65,8 @@ public class PoolingConnection extends > DelegatingConnection<Connection> /** Pool of {@link > PreparedStatement}s. and {@link CallableStatement}s */ private > KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> pstmtPool; > > + private boolean clearStatementPoolOnReturn = false; + /** * > Constructor. * @@ -117,6 +119,23 @@ public class PoolingConnection > extends DelegatingConnection<Connection> } > > /** + * Notification from {@link PoolableConnection} that we > returned to the pool. + * + * @throws SQLException when > <code>clearStatementPoolOnReturn</code> is true and the statement > pool could not be + * cleared + * > @since 2.8.0 + */ + public void connectionReturnedToPool() > throws SQLException { + if (pstmtPool != null && > clearStatementPoolOnReturn) { + try { + > pstmtPool.clear(); + } catch (Exception e) { + > throw new SQLException("Error clearing statement pool", e); + > } + } + } + + /** * Creates a PStmtKey for the given > arguments. * * @param sql @@ -134,7 +153,8 @@ public class > PoolingConnection extends DelegatingConnection<Connection> * @param > sql * the SQL string used to define the statement * > @param columnIndexes - * column indexes + * > An array of column indexes indicating the columns that should be > returned from the inserted row or + * rows. * * > @return the PStmtKey created for the given arguments. */ @@ -142,6 > +162,17 @@ public class PoolingConnection extends > DelegatingConnection<Connection> return new > PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), > columnIndexes); } > > + /** + * Creates a PStmtKey for the given arguments. + > * + * @param sql + * the SQL string used to > define the statement + * @param autoGeneratedKeys + * > A flag indicating whether auto-generated keys should be returned; > one of + * > <code>Statement.RETURN_GENERATED_KEYS</code> or > <code>Statement.NO_GENERATED_KEYS</code>. + * + * @return > the PStmtKey created for the given arguments. + */ protected > PStmtKey createKey(final String sql, final int autoGeneratedKeys) > { return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), > getSchemaOrNull(), autoGeneratedKeys); } @@ -277,13 +308,23 @@ > public class PoolingConnection extends > DelegatingConnection<Connection> } > > private String getSchemaOrNull() { - String catalog = null; > + String schema = null; try { - catalog = > getSchema(); + schema = getSchema(); } catch (final > SQLException e) { // Ignored } - return catalog; + > return schema; + } + + /** + * Returns the prepared > statement pool we're using. + * + * @return statement pool > + * @since 2.8.0 + */ + public KeyedObjectPool<PStmtKey, > DelegatingPreparedStatement> getStatementPool() { + return > pstmtPool; } > > /** @@ -342,6 +383,19 @@ public class PoolingConnection extends > DelegatingConnection<Connection> /** * Creates or obtains a {@link > CallableStatement} from the pool. * + * @param key + * > a {@link PStmtKey} for the given arguments + * @return a {@link > PoolableCallableStatement} + * @throws SQLException + * > Wraps an underlying exception. + */ + private > CallableStatement prepareCall(final PStmtKey key) throws > SQLException { + return (CallableStatement) > prepareStatement(key); + } + + /** + * Creates or obtains > a {@link CallableStatement} from the pool. + * * @param sql * > the SQL string used to define the CallableStatement * @return a > {@link PoolableCallableStatement} @@ -350,15 +404,7 @@ public class > PoolingConnection extends DelegatingConnection<Connection> */ > @Override public CallableStatement prepareCall(final String sql) > throws SQLException { - try { - return > (CallableStatement) pstmtPool.borrowObject(createKey(sql, > StatementType.CALLABLE_STATEMENT)); - } catch (final > NoSuchElementException e) { - throw new > SQLException("MaxOpenCallableStatements limit reached", e); - > } catch (final RuntimeException e) { - throw e; - > } catch (final Exception e) { - throw new > SQLException("Borrow callableStatement from pool failed", e); - > } + return prepareCall(createKey(sql, > StatementType.CALLABLE_STATEMENT)); } > > /** @@ -377,16 +423,7 @@ public class PoolingConnection extends > DelegatingConnection<Connection> @Override public CallableStatement > prepareCall(final String sql, final int resultSetType, final int > resultSetConcurrency) throws SQLException { - try { - > return (CallableStatement) pstmtPool.borrowObject( - > createKey(sql, resultSetType, resultSetConcurrency, > StatementType.CALLABLE_STATEMENT)); - } catch (final > NoSuchElementException e) { - throw new > SQLException("MaxOpenCallableStatements limit reached", e); - > } catch (final RuntimeException e) { - throw e; - > } catch (final Exception e) { - throw new > SQLException("Borrow callableStatement from pool failed", e); - > } + return prepareCall(createKey(sql, resultSetType, > resultSetConcurrency, StatementType.CALLABLE_STATEMENT)); } > > /** @@ -407,32 +444,25 @@ public class PoolingConnection extends > DelegatingConnection<Connection> @Override public CallableStatement > prepareCall(final String sql, final int resultSetType, final int > resultSetConcurrency, final int resultSetHoldability) throws > SQLException { - try { - return > (CallableStatement) pstmtPool.borrowObject(createKey(sql, > resultSetType, resultSetConcurrency, - > resultSetHoldability, StatementType.CALLABLE_STATEMENT)); - > } catch (final NoSuchElementException e) { - throw new > SQLException("MaxOpenCallableStatements limit reached", e); - > } catch (final RuntimeException e) { - throw e; - > } catch (final Exception e) { - throw new > SQLException("Borrow callableStatement from pool failed", e); - > } + return prepareCall(createKey(sql, resultSetType, > resultSetConcurrency, + resultSetHoldability, > StatementType.CALLABLE_STATEMENT)); } > > /** * Creates or obtains a {@link PreparedStatement} from the > pool. * - * @param sql - * the SQL string used > to define the PreparedStatement + * @param key + * > a {@link PStmtKey} for the given arguments * @return a {@link > PoolablePreparedStatement} + * @throws SQLException + * > Wraps an underlying exception. */ - @Override - public > PreparedStatement prepareStatement(final String sql) throws > SQLException { + private PreparedStatement > prepareStatement(final PStmtKey key) throws SQLException { if (null > == pstmtPool) { throw new SQLException("Statement pool is null - > closed or invalid PoolingConnection."); } try { - return > pstmtPool.borrowObject(createKey(sql)); + return > pstmtPool.borrowObject(key); } catch (final NoSuchElementException > e) { throw new SQLException("MaxOpenPreparedStatements limit > reached", e); } catch (final RuntimeException e) { @@ -442,20 > +472,35 @@ public class PoolingConnection extends > DelegatingConnection<Connection> } } > > + /** + * Creates or obtains a {@link PreparedStatement} > from the pool. + * + * @param sql + * the > SQL string used to define the PreparedStatement + * @return a > {@link PoolablePreparedStatement} + * @throws SQLException + > * Wraps an underlying exception. + */ + > @Override + public PreparedStatement prepareStatement(final > String sql) throws SQLException { + return > prepareStatement(createKey(sql)); + } + + /* + * Creates > or obtains a {@link PreparedStatement} from the pool. + * + > * @param sql + * the SQL string used to define the > PreparedStatement + * @param autoGeneratedKeys + * > A flag indicating whether auto-generated keys should be returned; > one of + * > <code>Statement.RETURN_GENERATED_KEYS</code> or > <code>Statement.NO_GENERATED_KEYS</code>. + * @return a {@link > PoolablePreparedStatement} + * @throws SQLException + * > Wraps an underlying exception. + */ @Override public > PreparedStatement prepareStatement(final String sql, final int > autoGeneratedKeys) throws SQLException { - if (null == > pstmtPool) { - throw new SQLException("Statement pool is > null - closed or invalid PoolingConnection."); - } - > try { - return pstmtPool.borrowObject(createKey(sql, > autoGeneratedKeys)); - } catch (final NoSuchElementException > e) { - throw new SQLException("MaxOpenPreparedStatements > limit reached", e); - } catch (final RuntimeException e) { - > throw e; - } catch (final Exception e) { - throw > new SQLException("Borrow prepareStatement from pool failed", e); - > } + return prepareStatement(createKey(sql, > autoGeneratedKeys)); } > > /** @@ -464,23 +509,16 @@ public class PoolingConnection extends > DelegatingConnection<Connection> * @param sql * the SQL > string used to define the PreparedStatement * @param columnIndexes > - * column indexes + * An array of > column indexes indicating the columns that should be returned from > the inserted row or + * rows. * @return a {@link > PoolablePreparedStatement} + * @throws SQLException + * > Wraps an underlying exception. + * */ @Override public > PreparedStatement prepareStatement(final String sql, final int > columnIndexes[]) throws SQLException { - if (null == > pstmtPool) { - throw new SQLException("Statement pool is > null - closed or invalid PoolingConnection."); - } - > try { - return pstmtPool.borrowObject(createKey(sql, > columnIndexes)); - } catch (final NoSuchElementException e) > { - throw new SQLException("MaxOpenPreparedStatements > limit reached", e); - } catch (final RuntimeException e) { - > throw e; - } catch (final Exception e) { - throw > new SQLException("Borrow prepareStatement from pool failed", e); - > } + return prepareStatement(createKey(sql, columnIndexes)); > } > > /** @@ -493,22 +531,13 @@ public class PoolingConnection extends > DelegatingConnection<Connection> * @param resultSetConcurrency * > result set concurrency * @return a {@link > PoolablePreparedStatement} + * @throws SQLException + * > Wraps an underlying exception. */ @Override public > PreparedStatement prepareStatement(final String sql, final int > resultSetType, final int resultSetConcurrency) throws SQLException > { - if (null == pstmtPool) { - throw new > SQLException("Statement pool is null - closed or invalid > PoolingConnection."); - } - try { - return > pstmtPool.borrowObject(createKey(sql, resultSetType, > resultSetConcurrency)); - } catch (final > NoSuchElementException e) { - throw new > SQLException("MaxOpenPreparedStatements limit reached", e); - > } catch (final RuntimeException e) { - throw e; - > } catch (final Exception e) { - throw new > SQLException("Borrow prepareStatement from pool failed", e); - > } + return prepareStatement(createKey(sql, resultSetType, > resultSetConcurrency)); } > > /** @@ -523,22 +552,13 @@ public class PoolingConnection extends > DelegatingConnection<Connection> * @param resultSetHoldability * > result set holdability * @return a {@link > PoolablePreparedStatement} + * @throws SQLException + * > Wraps an underlying exception. */ @Override public > PreparedStatement prepareStatement(final String sql, final int > resultSetType, final int resultSetConcurrency, final int > resultSetHoldability) throws SQLException { - if (null == > pstmtPool) { - throw new SQLException("Statement pool is > null - closed or invalid PoolingConnection."); - } - > try { - return pstmtPool.borrowObject(createKey(sql, > resultSetType, resultSetConcurrency, resultSetHoldability)); - > } catch (final NoSuchElementException e) { - throw new > SQLException("MaxOpenPreparedStatements limit reached", e); - > } catch (final RuntimeException e) { - throw e; - > } catch (final Exception e) { - throw new > SQLException("Borrow prepareStatement from pool failed", e); - > } + return prepareStatement(createKey(sql, resultSetType, > resultSetConcurrency, resultSetHoldability)); } > > /** @@ -549,21 +569,23 @@ public class PoolingConnection extends > DelegatingConnection<Connection> * @param columnNames * > column names * @return a {@link PoolablePreparedStatement} + * > @throws SQLException + * Wraps an underlying > exception. */ @Override public PreparedStatement > prepareStatement(final String sql, final String columnNames[]) > throws SQLException { - if (null == pstmtPool) { - > throw new SQLException("Statement pool is null - closed or invalid > PoolingConnection."); - } - try { - return > pstmtPool.borrowObject(createKey(sql, columnNames)); - } > catch (final NoSuchElementException e) { - throw new > SQLException("MaxOpenPreparedStatements limit reached", e); - > } catch (final RuntimeException e) { - throw e; - > } catch (final Exception e) { - throw new > SQLException("Borrow prepareStatement from pool failed", e); - > } + return prepareStatement(createKey(sql, columnNames)); + > } + + /** + * Sets whether the pool of statements should be > cleared when the connection is returned to its pool. + * > Default is false. + * + * @param clearStatementPoolOnReturn > clear or not + * @since 2.8.0 + */ + public void > setClearStatementPoolOnReturn(final boolean > clearStatementPoolOnReturn) { + > this.clearStatementPoolOnReturn = clearStatementPoolOnReturn; } > > /** diff --git > a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java > b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java > > index 34bad40..772682f 100644 > --- > a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java > > +++ b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.ja va > @@ -37,6 +37,7 @@ import javax.naming.spi.ObjectFactory; import > javax.sql.ConnectionPoolDataSource; import > javax.sql.PooledConnection; > > +import org.apache.tomcat.dbcp.dbcp2.BasicDataSource; import > org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement; import > org.apache.tomcat.dbcp.dbcp2.PStmtKey; import > org.apache.tomcat.dbcp.dbcp2.Utils; @@ -621,17 +622,15 @@ public > class DriverAdapterCPDS implements ConnectionPoolDataSource, > Referenceabl /** * Sets the number of statements to examine during > each run of the idle object evictor thread (if any). * <p> - * > When a negative value is supplied, <code>ceil({*link > #numIdle})/abs({*link #getNumTestsPerEvictionRun})</code> - * > tests will be run. I.e., when the value is <i>-n</i>, roughly one > <i>n</i>th of the idle objects will be tested - * per run. + > * When a negative value is supplied, + * <code>ceil({@link > BasicDataSource#getNumIdle})/abs({@link > #getNumTestsPerEvictionRun})</code> tests will be run. + * > I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the > idle objects will be tested per run. * </p> * - * @param > numTestsPerEvictionRun - * number of statements to > examine per run + * @param numTestsPerEvictionRun number of > statements to examine per run * @see #getNumTestsPerEvictionRun() * > @see #setTimeBetweenEvictionRunsMillis(long) - * @throws > IllegalStateException - * if {@link > #getPooledConnection()} has been called + * @throws > IllegalStateException if {@link #getPooledConnection()} has been > called */ public void setNumTestsPerEvictionRun(final int > numTestsPerEvictionRun) { assertInitializationAllowed(); @@ -755,11 > +754,8 @@ public class DriverAdapterCPDS implements > ConnectionPoolDataSource, Referenceabl > builder.append(getConnectionCalled); builder.append(", > connectionProperties="); Properties tmpProps = > connectionProperties; - final String pwdKey = "password"; - > if (connectionProperties != null && > connectionProperties.contains(pwdKey)) { - tmpProps = > (Properties) connectionProperties.clone(); - > tmpProps.remove(pwdKey); - } + tmpProps = > mask(tmpProps, "user"); + tmpProps = mask(tmpProps, > "password"); builder.append(tmpProps); builder.append(", > accessToUnderlyingConnectionAllowed="); > builder.append(accessToUnderlyingConnectionAllowed); @@ -767,6 > +763,14 @@ public class DriverAdapterCPDS implements > ConnectionPoolDataSource, Referenceabl return builder.toString(); > } > > + private Properties mask(Properties properties, final String > maskValueAtKey) { + if (connectionProperties != null && > connectionProperties.contains(maskValueAtKey)) { + > properties = (Properties) connectionProperties.clone(); + > properties.put(maskValueAtKey, "[" + maskValueAtKey + "]"); + > } + return properties; + } + private void update(final > Properties properties, final String key, final String value) { if > (properties != null && key != null) { if (value == null) { diff > --git > a/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory. java > b/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory. java > > index 915e4cd..93363a4 100644 > --- > a/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory. java > > +++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory.ja va > @@ -37,8 +37,7 @@ import > org.apache.tomcat.dbcp.pool2.PooledObjectFactory; import > org.apache.tomcat.dbcp.pool2.impl.DefaultPooledObject; > > /** - * A {@link PooledObjectFactory} that creates - * {@link > org.apache.tomcat.dbcp.dbcp2.PoolableConnection > PoolableConnection}s. + * A {@link PooledObjectFactory} that > creates {@link org.apache.tomcat.dbcp.dbcp2.PoolableConnection > PoolableConnection}s. * * @since 2.0 */ diff --git > a/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource. java > b/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource. java > > index 69d6eff..8168bcc 100644 > --- > a/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource. java > > +++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.ja va > @@ -532,7 +532,7 @@ public abstract class InstanceKeyDataSource > implements DataSource, Referenceable } > > /** - * Sets the backend ConnectionPoolDataSource. This > property should not be set if using JNDI to access the + * Sets > the back end ConnectionPoolDataSource. This property should not be > set if using JNDI to access the * data source. * * @param v @@ > -689,7 +689,7 @@ public abstract class InstanceKeyDataSource > implements DataSource, Referenceable > > /** * Gets the value of jndiEnvironment which is used when > instantiating a JNDI InitialContext. This InitialContext is - * > used to locate the backend ConnectionPoolDataSource. + * used > to locate the back end ConnectionPoolDataSource. * * @param key * > JNDI environment key. @@ -705,7 +705,7 @@ public abstract class > InstanceKeyDataSource implements DataSource, Referenceable > > /** * Sets the value of the given JNDI environment property to be > used when instantiating a JNDI InitialContext. This - * > InitialContext is used to locate the backend > ConnectionPoolDataSource. + * InitialContext is used to locate > the back end ConnectionPoolDataSource. * * @param key * > the JNDI environment property to set. @@ -721,7 +721,7 @@ public > abstract class InstanceKeyDataSource implements DataSource, > Referenceable > > /** * Sets the JNDI environment to be used when instantiating a > JNDI InitialContext. This InitialContext is used to - * locate > the backend ConnectionPoolDataSource. + * locate the back end > ConnectionPoolDataSource. * * @param properties * the > JNDI environment property to set which will overwrite any current > settings diff --git > a/java/org/apache/tomcat/dbcp/dbcp2/datasources/package-info.java > b/java/org/apache/tomcat/dbcp/dbcp2/datasources/package-info.java > index 6395e29..531db68 100644 --- > a/java/org/apache/tomcat/dbcp/dbcp2/datasources/package-info.java > +++ > b/java/org/apache/tomcat/dbcp/dbcp2/datasources/package-info.java > @@ -127,7 +127,7 @@ * Connection pooling is useful in applications > regardless of whether they run * in a J2EE environment and a > <code>DataSource</code> can be used within a * simpler environment. > The example below shows SharedPoolDataSource using - * > DriverAdapterCPDS as the backend source, though any CPDS is > applicable. + * DriverAdapterCPDS as the back end source, though > any CPDS is applicable. * </p> * * <code> diff --git > a/java/org/apache/tomcat/dbcp/dbcp2/managed/BasicManagedDataSource.jav a > b/java/org/apache/tomcat/dbcp/dbcp2/managed/BasicManagedDataSource.jav a > > index 0db3393..17ecca9 100644 > --- > a/java/org/apache/tomcat/dbcp/dbcp2/managed/BasicManagedDataSource.jav a > > +++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/BasicManagedDataSource.j ava > @@ -175,7 +175,7 @@ public class BasicManagedDataSource extends > BasicDataSource { if (xaDataSource == null) { final > ConnectionFactory connectionFactory = > super.createConnectionFactory(); final XAConnectionFactory > xaConnectionFactory = new > LocalXAConnectionFactory(getTransactionManager(), - > connectionFactory); + > getTransactionSynchronizationRegistry(), connectionFactory); > transactionRegistry = > xaConnectionFactory.getTransactionRegistry(); return > xaConnectionFactory; } @@ -238,6 +238,7 @@ public class > BasicManagedDataSource extends BasicDataSource { > connectionFactory.setDefaultSchema(getDefaultSchema()); > connectionFactory.setCacheState(getCacheState()); > connectionFactory.setPoolStatements(isPoolPreparedStatements()); + > connectionFactory.setClearStatementPoolOnReturn(isClearStatementPoolOn Return()); > > connectionFactory.setMaxOpenPreparedStatements(getMaxOpenPreparedStateme nts()); > connectionFactory.setMaxConnLifetimeMillis(getMaxConnLifetimeMillis()) ; > > connectionFactory.setRollbackOnReturn(getRollbackOnReturn()); > diff --git > a/java/org/apache/tomcat/dbcp/dbcp2/managed/LocalXAConnectionFactory.j ava > b/java/org/apache/tomcat/dbcp/dbcp2/managed/LocalXAConnectionFactory.j ava > > index 5eda07d..23e7283 100644 > --- > a/java/org/apache/tomcat/dbcp/dbcp2/managed/LocalXAConnectionFactory.j ava > > +++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/LocalXAConnectionFactory.jav a > @@ -26,6 +26,7 @@ import javax.transaction.xa.XAResource; import > javax.transaction.xa.Xid; > > import jakarta.transaction.TransactionManager; +import > jakarta.transaction.TransactionSynchronizationRegistry; > > import org.apache.tomcat.dbcp.dbcp2.ConnectionFactory; > > @@ -317,9 +318,27 @@ public class LocalXAConnectionFactory > implements XAConnectionFactory { */ public > LocalXAConnectionFactory(final TransactionManager > transactionManager, final ConnectionFactory connectionFactory) { + > this(transactionManager, null, connectionFactory); + } + + > /** + * Creates an LocalXAConnectionFactory which uses the > specified connection factory to create database connections. + > * The connections are enlisted into transactions using the > specified transaction manager. + * + * @param > transactionManager + * the transaction manager in > which connections will be enlisted + * @param > transactionSynchronizationRegistry + * the optional > TSR to register synchronizations with + * @param > connectionFactory + * the connection factory from > which connections will be retrieved + * @since 2.8.0 + */ + > public LocalXAConnectionFactory(final TransactionManager > transactionManager, + final > TransactionSynchronizationRegistry > transactionSynchronizationRegistry, + final > ConnectionFactory connectionFactory) { > Objects.requireNonNull(transactionManager, "transactionManager is > null"); Objects.requireNonNull(connectionFactory, > "connectionFactory is null"); - this.transactionRegistry = > new TransactionRegistry(transactionManager); + > this.transactionRegistry = new > TransactionRegistry(transactionManager, > transactionSynchronizationRegistry); this.connectionFactory = > connectionFactory; } > > diff --git a/webapps/docs/changelog.xml > b/webapps/docs/changelog.xml index 0d64135..1bc6937 100644 --- > a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ > -219,6 +219,10 @@ Update the internal fork of Apache Commons Pool > to 2.8.1. Code clean-up and improved abandoned pool handling. > (markt) </add> + <add> + Update the internal fork of > Apache Commons DBCP to 6d232e5 (2020-08-11, + > 2.8.0-SNAPSHOT). Code clean-up various bug fixes. (markt) + > </add> </changelog> </subsection> </section> > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org > For additional commands, e-mail: dev-h...@tomcat.apache.org > -----BEGIN PGP SIGNATURE----- Comment: Using GnuPG with Thunderbird - https://www.enigmail.net/ iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAl9GlFAACgkQHPApP6U8 pFhPMg/+NORUcXAQAB4fF8deGKO2SUBf7ZSV9mnoNtzt7xOPU90qAWeu/tUWshBR +8tM8ya9xVgUSEgPskjUGcRCmiGn/fC1o76VMLXr/WNDJmdzty7xVvzkrY5Wn6Vf CoKpB7hd7tEFECt1h+NU5iEmgiGFr/3A3qmK++YXU1hzKPjiENWhYZrkd4A1bjOR XEZh+pzeadSkB25YtS0GP7ea/FeDx2xyQ9bD4nRLHDFrbIJzW077q+DSVug0zukR FA/8nfjoU1ajIPJ7ZrJz/P0IfMMACuz6jXNcVF2opm/CILyav44SQ+JLDDGTpZ1N tNtLpn0HU5efxzNKiqrJ+7/UVbwHwRt3cIS+RfxMDHvyUPq3cFWpx8EogDbRzH/V HkUBHyssxwxmD9SPc1zCI/pdEbA6tsH3e3XcD0P4FQdcG4uKB43GfCNS/vo6M4NP /ekU6WyO+5pVD5uKSKn/4i8hW6KKo8G6nzxYBvfR+xZ8KFf+yikN/GigwMjJ5qJp VkYgmWNW2eXKC/fplYguOH0i5l1jjn30Y0xETXGnaLp+Q+MbSjqQcs0YprveRbPo JU7+vCMIfMI7RJOJT1+kLNmP7Yj99+JYmypDV41xo3B0e7rhiquTiRpJa2A4jELq ARWYmS21yGHTnTngI9wWrB/bhSTio2bnaSPNtzg6NSX3PCzF/lY= =yGdr -----END PGP SIGNATURE----- --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org