You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by rm...@apache.org on 2016/01/18 19:50:25 UTC
tomee git commit: TOMEE-1694 use tomcat destroy hook
Repository: tomee
Updated Branches:
refs/heads/master fbc4b38f2 -> fde16235f
TOMEE-1694 use tomcat destroy hook
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/fde16235
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/fde16235
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/fde16235
Branch: refs/heads/master
Commit: fde16235fbf441016a0b44fb4a234cdc2394754f
Parents: fbc4b38
Author: Romain Manni-Bucau <rm...@gmail.com>
Authored: Mon Jan 18 19:50:16 2016 +0100
Committer: Romain Manni-Bucau <rm...@gmail.com>
Committed: Mon Jan 18 19:50:16 2016 +0100
----------------------------------------------------------------------
.../tomee/catalina/JavaeeInstanceManager.java | 46 ++++-
.../tomee/catalina/OpenEJBContextConfig.java | 30 ----
.../JavaEEDefaultServerEnpointConfigurator.java | 166 +------------------
3 files changed, 45 insertions(+), 197 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tomee/blob/fde16235/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/JavaeeInstanceManager.java
----------------------------------------------------------------------
diff --git a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/JavaeeInstanceManager.java b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/JavaeeInstanceManager.java
index 3a4540e..27ab0ac 100644
--- a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/JavaeeInstanceManager.java
+++ b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/JavaeeInstanceManager.java
@@ -18,6 +18,7 @@ package org.apache.tomee.catalina;
import org.apache.openejb.OpenEJBException;
import org.apache.openejb.core.WebContext;
+import org.apache.openejb.loader.SystemInstance;
import org.apache.tomcat.InstanceManager;
import org.apache.webbeans.exception.WebBeansConfigurationException;
import org.apache.webbeans.exception.WebBeansCreationException;
@@ -92,8 +93,17 @@ public class JavaeeInstanceManager implements InstanceManager {
if (o == null) {
return;
}
- preDestroy(o, o.getClass());
- webContext.destroy(o);
+ final Object unwrapped = unwrap(o);
+ preDestroy(unwrapped, unwrapped.getClass());
+ webContext.destroy(unwrapped);
+ if (unwrapped != o) { // PojoEndpointServer, they create and track a cc so release it
+ webContext.destroy(o);
+ }
+ }
+
+ private Object unwrap(final Object o) {
+ return "org.apache.tomcat.websocket.pojo.PojoEndpointServer".equals(o.getClass().getName()) ?
+ WebSocketTypes.unwrapWebSocketPojo(o) : o;
}
public void inject(final Object o) {
@@ -193,4 +203,36 @@ public class JavaeeInstanceManager implements InstanceManager {
preDestroy.setAccessible(accessibility);
}
}
+
+ private static class WebSocketTypes { // extracted for lazy loading
+ private static final WebSocketTypes WEB_SOCKET_TYPES = new WebSocketTypes();
+ private final Method getPojo;
+
+ private WebSocketTypes() {
+ Method tmp;
+ try {
+ tmp = WebSocketTypes.class.getClassLoader()
+ .loadClass("org.apache.tomcat.websocket.pojo.PojoEndpointBase")
+ .getDeclaredMethod("getPojo");
+ tmp.setAccessible(true);
+ } catch (final NoSuchMethodException e) {
+ if ("true".equals(SystemInstance.get().getProperty("tomee.websocket.skip", "false"))) {
+ tmp = null;
+ } else {
+ throw new IllegalStateException(e);
+ }
+ } catch (final ClassNotFoundException e) {
+ tmp = null; // no websocket support
+ }
+ getPojo = tmp;
+ }
+
+ private static Object unwrapWebSocketPojo(final Object o) {
+ try {
+ return WEB_SOCKET_TYPES.getPojo == null ? o : WEB_SOCKET_TYPES.getPojo.invoke(o);
+ } catch (final IllegalAccessException | InvocationTargetException | NullPointerException e) {
+ return o;
+ }
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/tomee/blob/fde16235/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/OpenEJBContextConfig.java
----------------------------------------------------------------------
diff --git a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/OpenEJBContextConfig.java b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/OpenEJBContextConfig.java
index 7e2e410..b3d06a4 100644
--- a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/OpenEJBContextConfig.java
+++ b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/OpenEJBContextConfig.java
@@ -64,10 +64,6 @@ import org.apache.webbeans.web.context.WebConversationFilter;
import org.apache.xbean.finder.IAnnotationFinder;
import javax.servlet.ServletContainerInitializer;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.ws.rs.core.Application;
import java.io.ByteArrayInputStream;
@@ -431,32 +427,6 @@ public class OpenEJBContextConfig extends ContextConfig {
final ClassLoader classLoader = context.getLoader().getClassLoader();
- try {
- classLoader.loadClass("org.apache.tomcat.websocket.server.DefaultServerEndpointConfigurator");
- context.addServletContainerInitializer(new ServletContainerInitializer() {
- @Override
- public void onStartup(final Set<Class<?>> c, final ServletContext ctx) throws ServletException {
- ctx.addListener(new ServletContextListener() {
- @Override
- public void contextInitialized(final ServletContextEvent sce) {
- //no -op
- }
-
- @Override
- public void contextDestroyed(final ServletContextEvent sce) { // ensure we cleanup our "eviction" processes
- try {
- org.apache.tomee.catalina.websocket.JavaEEDefaultServerEnpointConfigurator.unregisterProcesses(sce.getServletContext());
- } catch (final Throwable th) {
- // no-op
- }
- }
- });
- }
- }, null);
- } catch (final Throwable noWebSocket) {
- // no-op: ok
- }
-
// add myfaces auto-initializer if mojarra is not present
try {
classLoader.loadClass("com.sun.faces.context.SessionMap");
http://git-wip-us.apache.org/repos/asf/tomee/blob/fde16235/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/websocket/JavaEEDefaultServerEnpointConfigurator.java
----------------------------------------------------------------------
diff --git a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/websocket/JavaEEDefaultServerEnpointConfigurator.java b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/websocket/JavaEEDefaultServerEnpointConfigurator.java
index f73b80f..34df1dc 100644
--- a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/websocket/JavaEEDefaultServerEnpointConfigurator.java
+++ b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/websocket/JavaEEDefaultServerEnpointConfigurator.java
@@ -16,51 +16,14 @@
*/
package org.apache.tomee.catalina.websocket;
-import org.apache.openejb.core.WebContext;
import org.apache.openejb.loader.SystemInstance;
import org.apache.tomcat.InstanceManager;
-import org.apache.tomcat.websocket.BackgroundProcess;
-import org.apache.tomcat.websocket.BackgroundProcessManager;
-import org.apache.tomcat.websocket.WsWebSocketContainer;
-import org.apache.tomcat.websocket.pojo.PojoEndpointBase;
-import org.apache.tomcat.websocket.server.Constants;
import org.apache.tomcat.websocket.server.DefaultServerEndpointConfigurator;
-import org.apache.tomee.catalina.JavaeeInstanceManager;
import org.apache.tomee.catalina.TomcatWebAppBuilder;
-import javax.servlet.ServletContext;
-import javax.websocket.Endpoint;
-import javax.websocket.Session;
-import javax.websocket.WebSocketContainer;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Collection;
-import java.util.LinkedList;
import java.util.Map;
-import java.util.Set;
public class JavaEEDefaultServerEnpointConfigurator extends DefaultServerEndpointConfigurator {
- private static final String BG_PROCESSES_LIST = JavaEEDefaultServerEnpointConfigurator.class.getName() + ".bgProcesses";
-
- // for websocket eviction
- private static final Field END_POINT_SESSION_MAP_LOCK;
- private static final Field ENDPOINT_SESSION_MAP;
- private static final Method GET_POJO;
- static {
- try {
- ENDPOINT_SESSION_MAP = WsWebSocketContainer.class.getDeclaredField("endpointSessionMap");
- ENDPOINT_SESSION_MAP.setAccessible(true);
- END_POINT_SESSION_MAP_LOCK = WsWebSocketContainer.class.getDeclaredField("endPointSessionMapLock");
- END_POINT_SESSION_MAP_LOCK.setAccessible(true);
-
- GET_POJO = PojoEndpointBase.class.getDeclaredMethod("getPojo");
- GET_POJO.setAccessible(true);
- } catch (final Exception e) {
- throw new IllegalStateException("Toncat not compatible with tomee", e);
- }
- }
-
private final Map<ClassLoader, InstanceManager> instanceManagers;
public JavaEEDefaultServerEnpointConfigurator() {
@@ -87,38 +50,7 @@ public class JavaEEDefaultServerEnpointConfigurator extends DefaultServerEndpoin
}
try {
- final Object instance;
- if (JavaeeInstanceManager.class.isInstance(instanceManager)) {
- final JavaeeInstanceManager javaeeInstanceManager = JavaeeInstanceManager.class.cast(instanceManager);
- final WebContext.Instance cdiInstance = javaeeInstanceManager.newWeakableInstance(clazz);
- instance = cdiInstance.getValue();
- if (cdiInstance.getCreationalContext() != null) { // TODO: if we manage to have better listeners on tomcat we can use it rather than it
- final ServletContext sc = javaeeInstanceManager.getServletContext();
- if (sc != null) {
- Collection<CdiCleanUpBackgroundProcess> processes;
- synchronized (sc) {
- processes = (Collection<CdiCleanUpBackgroundProcess>) sc.getAttribute(BG_PROCESSES_LIST);
- if (processes == null) {
- processes = new LinkedList<>();
- sc.setAttribute(BG_PROCESSES_LIST, processes);
- }
- }
-
- final WebSocketContainer wsc = WebSocketContainer.class.cast(sc.getAttribute(Constants.SERVER_CONTAINER_SERVLET_CONTEXT_ATTRIBUTE));
- final Object lock = END_POINT_SESSION_MAP_LOCK.get(wsc);
- if (wsc != null && WsWebSocketContainer.class.isInstance(wsc)) {
- final CdiCleanUpBackgroundProcess process = new CdiCleanUpBackgroundProcess(wsc, cdiInstance, lock);
- synchronized (processes) {
- processes.add(process);
- }
- BackgroundProcessManager.getInstance().register(process);
- }
- }
- }
- } else {
- instance = instanceManager.newInstance(clazz);
- }
- return clazz.cast(instance);
+ return clazz.cast(instanceManager.newInstance(clazz));
} catch (final Exception e) {
if (InstantiationException.class.isInstance(e)) {
throw InstantiationException.class.cast(e);
@@ -126,100 +58,4 @@ public class JavaEEDefaultServerEnpointConfigurator extends DefaultServerEndpoin
throw new InstantiationException(e.getMessage());
}
}
-
- public static void unregisterProcesses(final ServletContext sc) { // no sync needed at this point - no more "runtime"
- final Collection<CdiCleanUpBackgroundProcess> processes = (Collection<CdiCleanUpBackgroundProcess>) sc.getAttribute(BG_PROCESSES_LIST);
- if (processes == null) {
- return;
- }
- for (final CdiCleanUpBackgroundProcess p : processes) {
- try {
- p.stop();
- } catch (final RuntimeException e) {
- // no-op
- }
- }
- }
-
- private static final class CdiCleanUpBackgroundProcess implements BackgroundProcess {
- private volatile int period = 1; // 1s by default
- private volatile int acceptRetries = 3; // in case there is latency between this call and registerSession()
- private volatile Set<Session> sessions;
- private volatile boolean stopped;
-
- private final WebSocketContainer container;
- private final Object lock;
- private final WebContext.Instance cdiInstance;
-
- private CdiCleanUpBackgroundProcess(final WebSocketContainer wsc, final WebContext.Instance cdiInstance, final Object lock) {
- this.container = wsc;
- this.cdiInstance = cdiInstance;
- this.lock = lock;
- }
-
- @Override
- public void backgroundProcess() {
- if (!hasSession() && --acceptRetries > 0) {
- stop();
- }
- }
-
- @Override
- public void setProcessPeriod(final int period) {
- this.period = period;
- }
-
- @Override
- public int getProcessPeriod() {
- return period;
- }
-
- private boolean hasSession() {
- try {
- if (sessions == null) { // needs to be lazy cause tomcat register sessions after
- final Map<Endpoint, Set<Session>> sessionsByEndpoint = (Map<Endpoint, Set<Session>>) ENDPOINT_SESSION_MAP.get(container);
- if (sessionsByEndpoint != null) { // find sessions
- synchronized (lock) {
- for (final Map.Entry<Endpoint, Set<Session>> e : sessionsByEndpoint.entrySet()) {
- if (e.getKey() == cdiInstance.getValue()) {
- sessions = e.getValue();
- break;
- }
- if (PojoEndpointBase.class.isInstance(e.getKey())) {
- try {
- final Object pojo = GET_POJO.invoke(e.getKey());
- if (pojo == cdiInstance.getValue()) {
- sessions = e.getValue();
- break;
- }
- } catch (final InvocationTargetException e1) {
- // no-op
- }
- }
- }
- }
- }
- }
-
- synchronized (lock) {
- return sessions != null && !sessions.isEmpty();
- }
- } catch (final IllegalAccessException e) {
- // no-op
- }
- return false;
- }
-
- public void stop() {
- if (stopped) {
- return;
- }
- stopped = true;
- try {
- cdiInstance.getCreationalContext().release();
- } finally {
- BackgroundProcessManager.getInstance().unregister(this);
- }
- }
- }
}