Author: psteitz Date: Tue Jan 13 04:11:09 2015 New Revision: 1651275 URL: http://svn.apache.org/r1651275 Log: Made expired connection logging configurable. JIRA: DBCP-424.
Added: commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/LifetimeExceededException.java (with props) commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/StackMessageLog.java (with props) Modified: commons/proper/dbcp/trunk/pom.xml commons/proper/dbcp/trunk/src/changes/changes.xml commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSourceFactory.java commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSourceMXBean.java commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/SwallowedExceptionLogger.java commons/proper/dbcp/trunk/src/site/xdoc/configuration.xml commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java Modified: commons/proper/dbcp/trunk/pom.xml URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/pom.xml?rev=1651275&r1=1651274&r2=1651275&view=diff ============================================================================== --- commons/proper/dbcp/trunk/pom.xml (original) +++ commons/proper/dbcp/trunk/pom.xml Tue Jan 13 04:11:09 2015 @@ -272,8 +272,8 @@ <artifactId>maven-surefire-plugin</artifactId> <configuration> <systemPropertyVariables> - <!-- Ensure that logging messges are seen --> - <xorg.apache.commons.logging.Log>org.apache.commons.logging.impl.SimpleLog</xorg.apache.commons.logging.Log> + <!-- Ensure that logging messges can be inspected --> + <org.apache.commons.logging.Log>org.apache.commons.dbcp2.StackMessageLog</org.apache.commons.logging.Log> </systemPropertyVariables> <reportFormat>plain</reportFormat> <excludes> Modified: commons/proper/dbcp/trunk/src/changes/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/changes/changes.xml?rev=1651275&r1=1651274&r2=1651275&view=diff ============================================================================== --- commons/proper/dbcp/trunk/src/changes/changes.xml (original) +++ commons/proper/dbcp/trunk/src/changes/changes.xml Tue Jan 13 04:11:09 2015 @@ -82,6 +82,10 @@ The <action> type attribute can be add,u <action issue="DBCP-428" dev="psteitz" type="fix" due-to="Vladimir Konkov"> Unsuccessful Connection enlistment in XA Transaction ignored by TransactionContext. </action> + <action issue="DBCP-424" dev="psteitz" type="update"> + Made expired connection logging configurable in BasicDataSource. Setting + logExpiredConnections to false suppresses expired connection log messages. + </action> </release> <release version="2.0.1" date="24 May 2014" description="This is a bug fix release."> <action dev="markt" type="fix"> Modified: commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java?rev=1651275&r1=1651274&r2=1651275&view=diff ============================================================================== --- commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java (original) +++ commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java Tue Jan 13 04:11:09 2015 @@ -1267,6 +1267,18 @@ public class BasicDataSource implements public long getMaxConnLifetimeMillis() { return maxConnLifetimeMillis; } + + private boolean logExpiredConnections = true; + + /** + * When {@link #getMaxConnLifetimeMillis()} is set to limit connection lifetime, + * this property determines whether or not log messages are generated when the + * pool closes connections due to maximum lifetime exceeded. + */ + @Override + public boolean isLogExpiredConnections() { + return logExpiredConnections; + } /** * <p>Sets the maximum permitted lifetime of a connection in @@ -1280,6 +1292,16 @@ public class BasicDataSource implements public void setMaxConnLifetimeMillis(long maxConnLifetimeMillis) { this.maxConnLifetimeMillis = maxConnLifetimeMillis; } + + /** + * When {@link #getMaxConnLifetimeMillis()} is set to limit connection lifetime, + * this property determines whether or not log messages are generated when the + * pool closes connections due to maximum lifetime exceeded. Set this property + * to false to suppress log messages when connections expire. + */ + public void setLogExpiredConnections(boolean logExpiredConnections) { + this.logExpiredConnections = logExpiredConnections; + } private String jmxName = null; @@ -2121,7 +2143,7 @@ public class BasicDataSource implements gop.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); gop.setTestWhileIdle(testWhileIdle); gop.setLifo(lifo); - gop.setSwallowedExceptionListener(new SwallowedExceptionLogger(log)); + gop.setSwallowedExceptionListener(new SwallowedExceptionLogger(log, logExpiredConnections)); gop.setEvictionPolicyClassName(evictionPolicyClassName); factory.setPool(gop); connectionPool = gop; Modified: commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSourceFactory.java URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSourceFactory.java?rev=1651275&r1=1651274&r2=1651275&view=diff ============================================================================== --- commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSourceFactory.java (original) +++ commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSourceFactory.java Tue Jan 13 04:11:09 2015 @@ -94,6 +94,7 @@ public class BasicDataSourceFactory impl private static final String PROP_MAXOPENPREPAREDSTATEMENTS = "maxOpenPreparedStatements"; private static final String PROP_CONNECTIONPROPERTIES = "connectionProperties"; private static final String PROP_MAXCONNLIFETIMEMILLIS = "maxConnLifetimeMillis"; + private static final String PROP_LOGEXPIREDCONNECTIONS = "logExpiredConnections"; private static final String PROP_ROLLBACK_ON_RETURN = "rollbackOnReturn"; private static final String PROP_ENABLE_AUTOCOMMIT_ON_RETURN = "enableAutoCommitOnReturn"; private static final String PROP_DEFAULT_QUERYTIMEOUT = "defaultQueryTimeout"; @@ -135,6 +136,7 @@ public class BasicDataSourceFactory impl PROP_MAXOPENPREPAREDSTATEMENTS, PROP_CONNECTIONPROPERTIES, PROP_MAXCONNLIFETIMEMILLIS, + PROP_LOGEXPIREDCONNECTIONS, PROP_ROLLBACK_ON_RETURN, PROP_ENABLE_AUTOCOMMIT_ON_RETURN, PROP_DEFAULT_QUERYTIMEOUT @@ -412,6 +414,11 @@ public class BasicDataSourceFactory impl if (value != null) { dataSource.setMaxConnLifetimeMillis(Long.parseLong(value)); } + + value = properties.getProperty(PROP_LOGEXPIREDCONNECTIONS); + if (value != null) { + dataSource.setLogExpiredConnections(Boolean.valueOf(value).booleanValue()); + } value = properties.getProperty(PROP_JMX_NAME); if (value != null) { Modified: commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSourceMXBean.java URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSourceMXBean.java?rev=1651275&r1=1651274&r2=1651275&view=diff ============================================================================== --- commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSourceMXBean.java (original) +++ commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/BasicDataSourceMXBean.java Tue Jan 13 04:11:09 2015 @@ -215,6 +215,12 @@ public interface BasicDataSourceMXBean { * @return {@link BasicDataSource#getMaxConnLifetimeMillis()} */ long getMaxConnLifetimeMillis(); + + /** + * See {@link BasicDataSource#isLogExpiredConnections()} + * @return {@link BasicDataSource#isLogExpiredConnections()} + */ + boolean isLogExpiredConnections(); /** * See {@link BasicDataSource#getRemoveAbandonedOnBorrow()} Added: commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/LifetimeExceededException.java URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/LifetimeExceededException.java?rev=1651275&view=auto ============================================================================== --- commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/LifetimeExceededException.java (added) +++ commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/LifetimeExceededException.java Tue Jan 13 04:11:09 2015 @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.dbcp2; + +/** + * Exception thrown when a connection's maximum lifetime has been exceeded. + * + * @since 2.1 + */ + class LifetimeExceededException extends Exception { + + private static final long serialVersionUID = -3783783104516492659L; + + /** + * Create a LifetimeExceededException. + */ + public LifetimeExceededException() { + super(); + } + + /** + * Create a LifetimeExceededException with the given message. + */ + public LifetimeExceededException(String message) { + super(message); + } + +} Propchange: commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/LifetimeExceededException.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java?rev=1651275&r1=1651274&r2=1651275&view=diff ============================================================================== --- commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java (original) +++ commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java Tue Jan 13 04:11:09 2015 @@ -367,7 +367,7 @@ public class PoolableConnectionFactory if (maxConnLifetimeMillis > 0) { long lifetime = System.currentTimeMillis() - p.getCreateTime(); if (lifetime > maxConnLifetimeMillis) { - throw new Exception(Utils.getMessage( + throw new LifetimeExceededException(Utils.getMessage( "connectionFactory.lifetimeExceeded", Long.valueOf(lifetime), Long.valueOf(maxConnLifetimeMillis))); Modified: commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/SwallowedExceptionLogger.java URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/SwallowedExceptionLogger.java?rev=1651275&r1=1651274&r2=1651275&view=diff ============================================================================== --- commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/SwallowedExceptionLogger.java (original) +++ commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2/SwallowedExceptionLogger.java Tue Jan 13 04:11:09 2015 @@ -27,14 +27,35 @@ import org.apache.commons.pool2.Swallowe public class SwallowedExceptionLogger implements SwallowedExceptionListener{ private final Log log; + private final boolean logExpiredConnections; + /** + * Create a SwallowedExceptionLogger with the given logger. By default, + * expired connection logging is turned on. + * + * @param log logger + */ public SwallowedExceptionLogger(Log log) { + this(log, true); + } + + /** + * Create a SwallowedExceptionLogger with the given logger and expired + * connection logging property. + * + * @param log logger + * @param logExpiredConnections false suppresses logging of expired connection events + */ + public SwallowedExceptionLogger(Log log, boolean logExpiredConnections) { this.log = log; + this.logExpiredConnections = logExpiredConnections; } @Override public void onSwallowException(Exception e) { - log.warn(Utils.getMessage( - "swallowedExceptionLogger.onSwallowedException"), e); + if (logExpiredConnections || !(e instanceof LifetimeExceededException)) { + log.warn(Utils.getMessage( + "swallowedExceptionLogger.onSwallowedException"), e); + } } } Modified: commons/proper/dbcp/trunk/src/site/xdoc/configuration.xml URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/site/xdoc/configuration.xml?rev=1651275&r1=1651274&r2=1651275&view=diff ============================================================================== --- commons/proper/dbcp/trunk/src/site/xdoc/configuration.xml (original) +++ commons/proper/dbcp/trunk/src/site/xdoc/configuration.xml Tue Jan 13 04:11:09 2015 @@ -18,7 +18,7 @@ <document> <properties> - <title>Configuration</title> + <title>BasicDataSource Configuration</title> <author email="d...@commons.apache.org">Commons Documentation Team</author> </properties> @@ -46,7 +46,7 @@ testWhileIdle </section> --> -<section name="Parameters"> +<section name="BasicDataSource Configuration Parameters"> <table> <hr><th>Parameter</th><th>Description</th></hr> @@ -283,6 +283,15 @@ isValid() method. </td> </tr> <tr> + <td>logExpiredConnections</td> + <td>true</td> + <td> + Flag to log a message indicating that a connection is being closed by the + pool due to maxConnLifetimeMillis exceeded. Set this property to false + to suppress expired connection logging that is turned on by default. + </td> +</tr> +<tr> <td>connectionInitSqls</td> <td>null</td> <td> Added: commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/StackMessageLog.java URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/StackMessageLog.java?rev=1651275&view=auto ============================================================================== --- commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/StackMessageLog.java (added) +++ commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/StackMessageLog.java Tue Jan 13 04:11:09 2015 @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.dbcp2; + +import java.util.EmptyStackException; +import java.util.Stack; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import org.apache.commons.logging.impl.SimpleLog; + +/** + * A logger that pushes log messages onto a stack. The stack itself is static. + * To get a log exclusive to a test case, use explicit lock / unlock and clear. + * + * @version $Id$ + */ +public class StackMessageLog extends SimpleLog { + + private static final long serialVersionUID = 1L; + private static Stack<String> messageStack = new Stack<String>(); + private static Lock lock = new ReentrantLock(); + + public StackMessageLog(String name) { + super(name); + } + + /** + * Ignores type. Pushes message followed by stack trace of t onto the stack. + */ + protected void log(int type, Object message, Throwable t) { + lock.lock(); + try { + final StringBuffer buf = new StringBuffer(); + buf.append(message.toString()); + if(t != null) { + buf.append(" <"); + buf.append(t.toString()); + buf.append(">"); + final java.io.StringWriter sw = new java.io.StringWriter(1024); + final java.io.PrintWriter pw = new java.io.PrintWriter(sw); + t.printStackTrace(pw); + pw.close(); + buf.append(sw.toString()); + } + messageStack.push(buf.toString()); + } finally { + lock.unlock(); + } + } + + /** + * @return the most recent log message, or null if the log is empty + */ + public static String popMessage() { + String ret = null; + lock.lock(); + try { + ret = messageStack.pop(); + } catch (EmptyStackException ex) { + // ignore, return null + } finally { + lock.unlock(); + } + return ret; + } + + public static void clear() { + lock.lock(); + try { + messageStack.clear(); + } finally { + lock.unlock(); + } + } + + public static boolean isEmpty() { + return messageStack.isEmpty(); + } + + /** + * Obtains an exclusive lock on the log. + */ + public static void lock() { + lock.lock(); + } + + /** + * Relinquishes exclusive lock on the log. + */ + public static void unLock() { + try { + lock.unlock(); + } catch (IllegalMonitorStateException ex) { + // ignore + } + } +} Propchange: commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/StackMessageLog.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java?rev=1651275&r1=1651274&r2=1651275&view=diff ============================================================================== --- commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java (original) +++ commons/proper/dbcp/trunk/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java Tue Jan 13 04:11:09 2015 @@ -590,6 +590,42 @@ public class TestBasicDataSource extends // make sure cleanup is complete assertNull(ds.getConnectionPool()); } + + @Test + public void testMaxConnLifetimeExceeded() throws Exception { + try { + StackMessageLog.lock(); + ds.setMaxConnLifetimeMillis(100); + Connection conn = ds.getConnection(); + assertEquals(1, ds.getNumActive()); + Thread.sleep(500); + conn.close(); + assertEquals(0, ds.getNumIdle()); + String message = StackMessageLog.popMessage(); + assertTrue(message.indexOf("exceeds the maximum permitted value") > 0); + } finally { + StackMessageLog.clear(); + StackMessageLog.unLock(); + } + } + + @Test + public void testMaxConnLifetimeExceededMutedLog() throws Exception { + try { + StackMessageLog.lock(); + ds.setMaxConnLifetimeMillis(100); + ds.setLogExpiredConnections(false); + Connection conn = ds.getConnection(); + assertEquals(1, ds.getNumActive()); + Thread.sleep(500); + conn.close(); + assertEquals(0, ds.getNumIdle()); + assertTrue(StackMessageLog.isEmpty()); + } finally { + StackMessageLog.clear(); + StackMessageLog.unLock(); + } + } } /**