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();
+        }
+    }
 }
 
 /**


Reply via email to