Author: markt
Date: Tue Mar  8 22:15:34 2011
New Revision: 1079575

URL: http://svn.apache.org/viewvc?rev=1079575&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=25060
When stopping naming resources look for DataSource resources with a zero-arg 
close() method and call it if one is found
Works with Commons DBCP.

Modified:
    tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
    tomcat/trunk/java/org/apache/catalina/deploy/LocalStrings.properties
    tomcat/trunk/java/org/apache/catalina/deploy/NamingResources.java
    tomcat/trunk/webapps/docs/changelog.xml

Modified: tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardContext.java?rev=1079575&r1=1079574&r2=1079575&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Tue Mar  8 
22:15:34 2011
@@ -5384,15 +5384,13 @@ public class StandardContext extends Con
         
         setState(LifecycleState.STOPPING);
 
-        // Currently this is effectively a NO-OP but needs to be called to
-        // ensure the NamingResources follows the correct lifecycle
+        // Binding thread
+        ClassLoader oldCCL = bindThread();
+
         if (namingResources != null) {
             namingResources.stop();
         }
         
-        // Binding thread
-        ClassLoader oldCCL = bindThread();
-
         try {
 
             // Stop our child containers, if any

Modified: tomcat/trunk/java/org/apache/catalina/deploy/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/deploy/LocalStrings.properties?rev=1079575&r1=1079574&r2=1079575&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/deploy/LocalStrings.properties 
(original)
+++ tomcat/trunk/java/org/apache/catalina/deploy/LocalStrings.properties Tue 
Mar  8 22:15:34 2011
@@ -43,5 +43,10 @@ webxml.unrecognisedPublicId=The public I
 webXml.version.nfe=Unable to parse [{0}] from the version string [{1}]. This 
component of the version string will be ignored. 
 webXml.wrongFragmentName=Used a wrong fragment name {0} at web.xml 
absolute-ordering tag!
 
+namingResources.cleanupCloseFailed=Failed to invoke close method for resource 
[{0}] in container [{1}] so no cleanup was performed for that resource
+namingResources.cleanupCloseSecurity=Unable to retrieve close method for 
resource [{0}] in container [{1}] so no cleanup was performed for that resource
+namingResources.cleanupNoClose=Resource [{0}] in container [{1}] does not have 
a close method so no cleanup was performed for that resource
+namingResources.cleanupNoContext=Failed to retrieve JNDI naming context for 
container [{0}] so no cleanup was performed for that container
+namingResources.cleanupNoResource=Failed to retrieve JNDI resource [{0}] for 
container [{1}] so no cleanup was performed for that resource
 namingResources.mbeanCreateFail=Failed to create MBean for naming resource 
[{0}]
 namingResources.mbeanDestroyFail=Failed to destroy MBean for naming resource 
[{0}]

Modified: tomcat/trunk/java/org/apache/catalina/deploy/NamingResources.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/deploy/NamingResources.java?rev=1079575&r1=1079574&r2=1079575&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/deploy/NamingResources.java (original)
+++ tomcat/trunk/java/org/apache/catalina/deploy/NamingResources.java Tue Mar  
8 22:15:34 2011
@@ -22,9 +22,14 @@ package org.apache.catalina.deploy;
 import java.beans.PropertyChangeListener;
 import java.beans.PropertyChangeSupport;
 import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.Hashtable;
 
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+
 import org.apache.catalina.Container;
 import org.apache.catalina.Context;
 import org.apache.catalina.Engine;
@@ -35,6 +40,7 @@ import org.apache.catalina.mbeans.MBeanU
 import org.apache.catalina.util.LifecycleMBeanBase;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
+import org.apache.naming.ContextBindings;
 import org.apache.tomcat.util.res.StringManager;
 
 
@@ -949,11 +955,84 @@ public class NamingResources extends Lif
 
     @Override
     protected void stopInternal() throws LifecycleException {
+        cleanUp();
         setState(LifecycleState.STOPPING);
         fireLifecycleEvent(CONFIGURE_STOP_EVENT, null);
     }
 
+    /**
+     * Close those resources that an explicit close may help clean-up faster.
+     */
+    private void cleanUp() {
+        if (resources.size() == 0) {
+            return;
+        }
+        javax.naming.Context ctxt;
+        try {
+            if (container instanceof Server) {
+                ctxt = ((Server) container).getGlobalNamingContext();
+            } else {
+                ctxt = ContextBindings.getClassLoader();
+                ctxt = (javax.naming.Context) ctxt.lookup("comp/env");
+            }
+        } catch (NamingException e) {
+            log.warn(sm.getString("namingResources.cleanupNoContext",
+                    container), e);
+            return;
+        }
+        for (ContextResource cr: resources.values()) {
+            if (DataSource.class.getName().equals(cr.getType())) {
+                String name = cr.getName();
+                DataSource ds;
+                try {
+                     ds = (DataSource) ctxt.lookup(name);
+                } catch (NamingException e) {
+                    log.warn(sm.getString("namingResources.cleanupNoResource",
+                            cr.getName(), container), e);
+                    continue;
+                }
+                cleanUp(ds, name);
+            }
+        }
+    }
+
     
+    /**
+     * Closing a database connection pool will close it's open connections. 
This
+     * will happen on GC but that leaves db connections open that may cause
+     * issues.
+     * @param ds    The DataSource to close.
+     */
+    private void cleanUp(DataSource ds, String name) {
+        // Look for a zero-arg close() method
+        Method m = null;
+        try {
+            m = ds.getClass().getMethod("close", (Class<?>[]) null);
+        } catch (SecurityException e) {
+            log.debug(sm.getString("namingResources.cleanupCloseSecurity", 
name,
+                    container));
+            return;
+        } catch (NoSuchMethodException e) {
+            log.debug(sm.getString("namingResources.cleanupNoClose", name,
+                    container));
+            return;
+        }
+        if (m != null) {
+            try {
+                m.invoke(ds, (Object[]) null);
+            } catch (IllegalArgumentException e) {
+                log.warn(sm.getString("namingResources.cleanupCloseFailed",
+                        name, container), e);
+            } catch (IllegalAccessException e) {
+                log.warn(sm.getString("namingResources.cleanupCloseFailed",
+                        name, container), e);
+            } catch (InvocationTargetException e) {
+                log.warn(sm.getString("namingResources.cleanupCloseFailed",
+                        name, container), e);
+            }
+        }
+    }
+
     @Override
     protected void destroyInternal() throws LifecycleException {
 

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1079575&r1=1079574&r2=1079575&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Tue Mar  8 22:15:34 2011
@@ -45,19 +45,26 @@
 <section name="Tomcat 7.0.11 (markt)">
   <subsection name="Catalina">
     <changelog>
-      <fix>
+      <add>
+        <bug>25060</bug>: Close Apache Commons DBCP datasources when the
+        associated JNDI naming context is stopped (e.g. for a non-global
+        DataSource resource on web application reload) to close remaining
+        database connections immediately rather than waiting for garbage 
+        collection. (markt)
+      </add>
+      <add>
         <bug>26701</bug>: Provide a mechanism for users to register their own
         <code>URLStreamHandlerFactory</code> objects. (markt)
-      </fix>
+      </add>
       <fix>
         <bug>50855</bug>: Fix NPE on HttpServletRequest.logout() when debug
         logging is enabled. (markt)
       </fix>
-      <fix>
+      <add>
         New context attribute "swallowAbortedUploads" allows
         to make request data swallowing configurable for requests
         that are too large. (rjung)
-      </fix>
+      </add>
     </changelog>
   </subsection>
   <subsection name="Coyote">



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to