You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by st...@apache.org on 2015/05/14 18:51:16 UTC

[6/6] tomee git commit: TOMEE-1572 add a ThreadBindingListener to prevent mem leaks in async servlet requests

TOMEE-1572 add a ThreadBindingListener to prevent mem leaks in async servlet requests


Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/c8c7f5c9
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/c8c7f5c9
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/c8c7f5c9

Branch: refs/heads/fb_tomee2_owb16
Commit: c8c7f5c91a94ed3c40f42b8e635cb0e6bb9aaae5
Parents: ac291b9
Author: Mark Struberg <st...@apache.org>
Authored: Thu May 14 18:50:14 2015 +0200
Committer: Mark Struberg <st...@apache.org>
Committed: Thu May 14 18:50:14 2015 +0200

----------------------------------------------------------------------
 .../tomee/catalina/TomcatWebAppBuilder.java     |  8 +++
 .../cdi/WebBeansThreadBindingListener.java      | 56 ++++++++++++++++++++
 2 files changed, 64 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tomee/blob/c8c7f5c9/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java
----------------------------------------------------------------------
diff --git a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java
index 8137673..a64dab3 100644
--- a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java
+++ b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java
@@ -79,6 +79,7 @@ import org.apache.openejb.assembler.classic.WebAppBuilder;
 import org.apache.openejb.assembler.classic.WebAppInfo;
 import org.apache.openejb.assembler.classic.event.NewEjbAvailableAfterApplicationCreated;
 import org.apache.openejb.cdi.CdiBuilder;
+import org.apache.openejb.cdi.OWBContextThreadListener;
 import org.apache.openejb.cdi.OpenEJBLifecycle;
 import org.apache.openejb.cdi.Proxys;
 import org.apache.openejb.config.AppModule;
@@ -118,6 +119,7 @@ import org.apache.tomcat.util.descriptor.web.FilterMap;
 import org.apache.tomcat.util.descriptor.web.ResourceBase;
 import org.apache.tomcat.util.scan.StandardJarScanFilter;
 import org.apache.tomee.catalina.cdi.ServletContextHandler;
+import org.apache.tomee.catalina.cdi.WebBeansThreadBindingListener;
 import org.apache.tomee.catalina.cluster.ClusterObserver;
 import org.apache.tomee.catalina.cluster.TomEEClusterListener;
 import org.apache.tomee.catalina.environment.Hosts;
@@ -1678,6 +1680,12 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare
                 newLifecycleListeners[newLifecycleListeners.length - 1] = endWebBeansListener;
                 standardContext.setApplicationLifecycleListeners(newLifecycleListeners);
             }
+
+            // also add the ThreadBindingListener to clean up async thread executions
+            {
+                WebBeansThreadBindingListener webBeansThreadBindingListener = new WebBeansThreadBindingListener(webBeansContext, standardContext.getThreadBindingListener());
+                standardContext.setThreadBindingListener(webBeansThreadBindingListener);
+            }
         } else {
             // just add the end listener to be able to stack tasks to execute at the request end
             final EndWebBeansListener endWebBeansListener = new EndWebBeansListener(webBeansContext);

http://git-wip-us.apache.org/repos/asf/tomee/blob/c8c7f5c9/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/WebBeansThreadBindingListener.java
----------------------------------------------------------------------
diff --git a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/WebBeansThreadBindingListener.java b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/WebBeansThreadBindingListener.java
new file mode 100644
index 0000000..10bb76a
--- /dev/null
+++ b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/WebBeansThreadBindingListener.java
@@ -0,0 +1,56 @@
+/**
+ * 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.tomee.catalina.cdi;
+
+import javax.enterprise.context.RequestScoped;
+
+import org.apache.catalina.ThreadBindingListener;
+import org.apache.webbeans.config.WebBeansContext;
+import org.apache.webbeans.spi.ContextsService;
+
+/**
+ * For Tomcat we need to implement a ThreadBindingListener to
+ * release the ServletRequest in case of Async requests.
+ * Tomcat only sends the requestDestroyed event only when the 'final'
+ * detached response gets rendered. But this happens on a totally
+ * different Thread.
+ * Thus in order to release e.g. locks on Conversations and prevent mem leaks
+ * we need to end the request on unbind() as well.
+ * Note that the ContextsService will do nothing if the Request was already
+ * properly destroyed in standard synchronous Servlet Requests.
+ */
+public class WebBeansThreadBindingListener implements ThreadBindingListener {
+
+    private final ContextsService contextsService;
+    private final ThreadBindingListener delegate;
+
+    public WebBeansThreadBindingListener(WebBeansContext webBeansContext, ThreadBindingListener delegate) {
+        this.contextsService = webBeansContext.getContextsService();
+        this.delegate = delegate;
+    }
+
+    @Override
+    public void bind() {
+        delegate.bind();
+    }
+
+    @Override
+    public void unbind() {
+        contextsService.endContext(RequestScoped.class, null);
+        delegate.unbind();
+    }
+}