Repository: tomee Updated Branches: refs/heads/master ee551e05d -> b25b8bda8
TOMEE-1687 firing ApplicationScoped initialized event after webapp start Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/b25b8bda Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/b25b8bda Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/b25b8bda Branch: refs/heads/master Commit: b25b8bda863132382bb9c9c68664fb240bf4e454 Parents: ee551e0 Author: Romain Manni-Bucau <rmannibu...@gmail.com> Authored: Tue Dec 29 10:24:44 2015 +0100 Committer: Romain Manni-Bucau <rmannibu...@gmail.com> Committed: Tue Dec 29 10:24:44 2015 +0100 ---------------------------------------------------------------------- .../embedded/AppContextStartedTest.java | 73 ++++++++++++++++++++ .../openejb/arquillian/embedded/Start.java | 45 ++++++++++++ .../openejb/cdi/CdiAppContextsService.java | 24 ++++--- .../apache/openejb/cdi/OpenEJBLifecycle.java | 30 +------- .../java/org/apache/openejb/cdi/Proxys.java | 12 +++- .../openejb/cdi/AppScopeInitEventTest.java | 45 ++++++++++++ .../server/httpd/EmbeddedServletContext.java | 22 ++++++ .../server/httpd/AppScopeInitEventTest.java | 72 +++++++++++++++++++ .../tomee/catalina/TomcatWebAppBuilder.java | 22 +++++- .../catalina/cdi/ServletContextHandler.java | 21 +++++- 10 files changed, 323 insertions(+), 43 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/b25b8bda/arquillian/arquillian-tomee-embedded/src/test/java/org/apache/openejb/arquillian/embedded/AppContextStartedTest.java ---------------------------------------------------------------------- diff --git a/arquillian/arquillian-tomee-embedded/src/test/java/org/apache/openejb/arquillian/embedded/AppContextStartedTest.java b/arquillian/arquillian-tomee-embedded/src/test/java/org/apache/openejb/arquillian/embedded/AppContextStartedTest.java new file mode 100644 index 0000000..322255f --- /dev/null +++ b/arquillian/arquillian-tomee-embedded/src/test/java/org/apache/openejb/arquillian/embedded/AppContextStartedTest.java @@ -0,0 +1,73 @@ +/** + * 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.openejb.arquillian.embedded; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.shrinkwrap.descriptor.api.Descriptors; +import org.jboss.shrinkwrap.descriptor.api.webapp31.WebAppDescriptor; +import org.jboss.shrinkwrap.descriptor.api.webcommon31.WebAppVersionType; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.inject.Inject; +import javax.servlet.ServletContext; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(Arquillian.class) +public class AppContextStartedTest { + @Deployment + public static Archive<?> app() { + return ShrinkWrap.create(WebArchive.class, AppContextStartedTest.class.getSimpleName() + ".war") + .addClass(Start.class) + .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") + .setWebXML(new StringAsset( + Descriptors.create(WebAppDescriptor.class) + .version(WebAppVersionType._3_1) + .getOrCreateContextParam() + .paramName("test") + .paramValue("start") + .up() + .exportAsString() + )); + } + + @Inject + private Start start; + + @Inject + private ServletContext context; + + @Test + public void checkAccessAtStartup() { + assertNotNull(start.getContext()); + assertEquals("start", start.getValue()); + } + + @Test + public void checkAccessAtRuntime() { + assertEquals("start", start.getContext().getInitParameter("test")); + assertEquals("start", context.getInitParameter("test")); + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/b25b8bda/arquillian/arquillian-tomee-embedded/src/test/java/org/apache/openejb/arquillian/embedded/Start.java ---------------------------------------------------------------------- diff --git a/arquillian/arquillian-tomee-embedded/src/test/java/org/apache/openejb/arquillian/embedded/Start.java b/arquillian/arquillian-tomee-embedded/src/test/java/org/apache/openejb/arquillian/embedded/Start.java new file mode 100644 index 0000000..c33efad --- /dev/null +++ b/arquillian/arquillian-tomee-embedded/src/test/java/org/apache/openejb/arquillian/embedded/Start.java @@ -0,0 +1,45 @@ +/** + * 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.openejb.arquillian.embedded; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.Initialized; +import javax.enterprise.event.Observes; +import javax.servlet.ServletContext; + +@ApplicationScoped +public class Start { + private volatile ServletContext context; + private volatile String value; + + private void capture(@Observes @Initialized(ApplicationScoped.class) final ServletContext context) { + if (this.context != null) { + throw new IllegalStateException("app context started twice"); + } + + this.context = context; + this.value = context.getInitParameter("test"); + } + + public ServletContext getContext() { + return context; + } + + public String getValue() { + return value; + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/b25b8bda/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiAppContextsService.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiAppContextsService.java b/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiAppContextsService.java index c03778b..c5f69eb 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiAppContextsService.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiAppContextsService.java @@ -82,17 +82,23 @@ public class CdiAppContextsService extends WebContextsService implements Context } else if (ServletContextEvent.class.isInstance(initializeObject)) { event = ServletContextEvent.class.cast(initializeObject).getServletContext(); } - Object appEvent = event != null ? event : applicationContext; - webBeansContext.getBeanManagerImpl().fireEvent( - appEvent, - new EventMetadataImpl(null, - ServletContext.class.isInstance(appEvent) ? ServletContext.class : Object.class, null, - new Annotation[]{InitializedLiteral.INSTANCE_APPLICATION_SCOPED}, - webBeansContext), - false); + if (!FiredManually.class.isInstance(event)) { + applicationStarted(event); + } } } + public void applicationStarted(final Object event) { + Object appEvent = event != null ? event : applicationContext; + webBeansContext.getBeanManagerImpl().fireEvent( + appEvent, + new EventMetadataImpl(null, + ServletContext.class.isInstance(appEvent) ? ServletContext.class : Object.class, null, + new Annotation[]{InitializedLiteral.INSTANCE_APPLICATION_SCOPED}, + webBeansContext), + false); + } + public void destroy(final Object destroyObject) { super.destroy(destroyObject); removeThreadLocals(); @@ -106,4 +112,6 @@ public class CdiAppContextsService extends WebContextsService implements Context super.destroyRequestContext(requestEvent); } + + public interface FiredManually {} } http://git-wip-us.apache.org/repos/asf/tomee/blob/b25b8bda/container/openejb-core/src/main/java/org/apache/openejb/cdi/OpenEJBLifecycle.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/cdi/OpenEJBLifecycle.java b/container/openejb-core/src/main/java/org/apache/openejb/cdi/OpenEJBLifecycle.java index dd25ddf..a718bb8 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/cdi/OpenEJBLifecycle.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/cdi/OpenEJBLifecycle.java @@ -73,9 +73,6 @@ import java.util.Collections; import java.util.HashSet; import java.util.Properties; import java.util.Set; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadFactory; /** * @version $Rev:$ $Date:$ @@ -111,7 +108,6 @@ public class OpenEJBLifecycle implements ContainerLifecycle { /** * Manages unused conversations */ - private ScheduledExecutorService service; public OpenEJBLifecycle(final WebBeansContext webBeansContext) { this.webBeansContext = webBeansContext; @@ -121,8 +117,6 @@ public class OpenEJBLifecycle implements ContainerLifecycle { this.jndiService = webBeansContext.getService(JNDIService.class); this.scannerService = webBeansContext.getScannerService(); this.contextsService = webBeansContext.getContextsService(); - - initApplication(null); } @Override @@ -282,11 +276,6 @@ public class OpenEJBLifecycle implements ContainerLifecycle { logger.debug("OpenWebBeans Container is stopping."); try { - //Sub-classes operations - if (service != null) { - service.shutdownNow(); - } - // Fire shut down if (WebappBeanManager.class.isInstance(beanManager)) { WebappBeanManager.class.cast(beanManager).beforeStop(); @@ -381,23 +370,10 @@ public class OpenEJBLifecycle implements ContainerLifecycle { } public void startServletContext(final ServletContext servletContext) { - if (service != null) { - return; - } - service = initializeServletContext(servletContext, webBeansContext); + initializeServletContext(servletContext, webBeansContext); } - public static ScheduledExecutorService initializeServletContext(final ServletContext servletContext, final WebBeansContext context) { - - final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1, new ThreadFactory() { - @Override - public Thread newThread(final Runnable runable) { - final Thread t = new Thread(runable, "OwbConversationCleaner-" + servletContext.getContextPath()); - t.setDaemon(true); - return t; - } - }); - + public static void initializeServletContext(final ServletContext servletContext, final WebBeansContext context) { final ELAdaptor elAdaptor = context.getService(ELAdaptor.class); final ELResolver resolver = elAdaptor.getOwbELResolver(); //Application is configured as JSP @@ -409,8 +385,6 @@ public class OpenEJBLifecycle implements ContainerLifecycle { // Add BeanManager to the 'javax.enterprise.inject.spi.BeanManager' servlet context attribute servletContext.setAttribute(BeanManager.class.getName(), context.getBeanManagerImpl()); - - return executorService; } /** http://git-wip-us.apache.org/repos/asf/tomee/blob/b25b8bda/container/openejb-core/src/main/java/org/apache/openejb/cdi/Proxys.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/cdi/Proxys.java b/container/openejb-core/src/main/java/org/apache/openejb/cdi/Proxys.java index f1a7de4..c98027b 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/cdi/Proxys.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/cdi/Proxys.java @@ -23,6 +23,10 @@ import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Collection; + +import static java.util.Arrays.asList; // some helper reused accross several modules public final class Proxys { @@ -36,9 +40,13 @@ public final class Proxys { new Class<?>[] { HttpSession.class, Serializable.class }, new ThreadLocalSessionFromRequestHandler(threadLocal, defaultValue)); } - public static <T> T handlerProxy(final Class<T> type, final InvocationHandler raw) { + public static <T> T handlerProxy(final InvocationHandler raw, final Class<T> main, final Class<?>... type) { + final Collection<Class<?>> types = new ArrayList<>(type.length + 2); + types.add(main); + types.addAll(asList(type)); + types.add(Serializable.class); return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), - new Class<?>[] { type, Serializable.class }, new EnsureExceptionIsUnwrapped(raw)); + types.toArray(new Class<?>[types.size()]), new EnsureExceptionIsUnwrapped(raw)); } private Proxys() { http://git-wip-us.apache.org/repos/asf/tomee/blob/b25b8bda/container/openejb-core/src/test/java/org/apache/openejb/cdi/AppScopeInitEventTest.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/test/java/org/apache/openejb/cdi/AppScopeInitEventTest.java b/container/openejb-core/src/test/java/org/apache/openejb/cdi/AppScopeInitEventTest.java new file mode 100644 index 0000000..e0ff032 --- /dev/null +++ b/container/openejb-core/src/test/java/org/apache/openejb/cdi/AppScopeInitEventTest.java @@ -0,0 +1,45 @@ +package org.apache.openejb.cdi; + +import org.apache.openejb.junit.ApplicationComposer; +import org.apache.openejb.testing.Classes; +import org.apache.openejb.testing.SimpleLog; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.Initialized; +import javax.enterprise.event.Observes; +import javax.inject.Inject; + +import static org.junit.Assert.assertNotNull; + +@SimpleLog +@Classes(cdi = true, innerClassesAsBean = true) +@RunWith(ApplicationComposer.class) +public class AppScopeInitEventTest { // servlet context not present without config cause we miss http module + @Inject + private Start start; + + @Test + public void checkAccessAtStartup() { + assertNotNull(start.getContext()); + } + + @ApplicationScoped + public static class Start { + private volatile Object context; + + // ensure we start only once + private void capture(@Observes @Initialized(ApplicationScoped.class) final Object context) { + if (this.context != null) { + throw new IllegalStateException("app context started twice"); + } + + this.context = context; + } + + public Object getContext() { + return context; + } + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/b25b8bda/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/EmbeddedServletContext.java ---------------------------------------------------------------------- diff --git a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/EmbeddedServletContext.java b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/EmbeddedServletContext.java index d6ecc3c..18994eb 100644 --- a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/EmbeddedServletContext.java +++ b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/EmbeddedServletContext.java @@ -33,6 +33,7 @@ import java.util.concurrent.ConcurrentHashMap; public class EmbeddedServletContext extends MockServletContext { private final Map<String, Object> attributes = new ConcurrentHashMap<>(); + private final Map<String, String> initParameters = new ConcurrentHashMap<>(); private Collection<ResourceProvider> resourceProviders = new ArrayList<>(); @@ -43,6 +44,22 @@ public class EmbeddedServletContext extends MockServletContext { } @Override + public String getInitParameter(final String name) { + return initParameters.get(name); + } + + @Override + public Enumeration<String> getInitParameterNames() { + return Collections.enumeration(initParameters.keySet()); + } + + @Override + public boolean setInitParameter(final String name, final String value) { + initParameters.put(name, value); + return true; + } + + @Override public ClassLoader getClassLoader() { return Thread.currentThread().getContextClassLoader(); } @@ -90,6 +107,11 @@ public class EmbeddedServletContext extends MockServletContext { } @Override + public int getMinorVersion() { + return 1; + } + + @Override public String getVirtualServerName() { return "openejb"; } http://git-wip-us.apache.org/repos/asf/tomee/blob/b25b8bda/server/openejb-http/src/test/java/org/apache/openejb/server/httpd/AppScopeInitEventTest.java ---------------------------------------------------------------------- diff --git a/server/openejb-http/src/test/java/org/apache/openejb/server/httpd/AppScopeInitEventTest.java b/server/openejb-http/src/test/java/org/apache/openejb/server/httpd/AppScopeInitEventTest.java new file mode 100644 index 0000000..f1578a2 --- /dev/null +++ b/server/openejb-http/src/test/java/org/apache/openejb/server/httpd/AppScopeInitEventTest.java @@ -0,0 +1,72 @@ +package org.apache.openejb.server.httpd; + +import org.apache.openejb.junit.ApplicationComposer; +import org.apache.openejb.testing.Classes; +import org.apache.openejb.testing.Component; +import org.apache.openejb.testing.EnableServices; +import org.apache.openejb.testing.SimpleLog; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.Initialized; +import javax.enterprise.event.Observes; +import javax.inject.Inject; +import javax.servlet.ServletContext; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@SimpleLog +@EnableServices("http") +@Classes(cdi = true, innerClassesAsBean = true) +@RunWith(ApplicationComposer.class) +public class AppScopeInitEventTest { + @Component + public ServletContext context() { // default one doesnt read WebApp + final EmbeddedServletContext servletContext = new EmbeddedServletContext(); + servletContext.setInitParameter("test", "start"); + return servletContext; + } + + @Inject + private Start start; + + @Inject + private ServletContext context; + + @Test + public void checkAccessAtStartup() { + assertNotNull(start.getContext()); + assertEquals("start", start.getValue()); + } + + @Test + public void checkAccessAtRuntime() { + assertEquals("start", start.getContext().getInitParameter("test")); + assertEquals("start", context.getInitParameter("test")); + } + + @ApplicationScoped + public static class Start { + private volatile ServletContext context; + private volatile String value; + + private void capture(@Observes @Initialized(ApplicationScoped.class) final ServletContext context) { + if (this.context != null) { + throw new IllegalStateException("app context started twice"); + } + + this.context = context; + this.value = context.getInitParameter("test"); + } + + public ServletContext getContext() { + return context; + } + + public String getValue() { + return value; + } + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/b25b8bda/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 a45de69..83b8a12 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.ServletInfo; 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.CdiAppContextsService; import org.apache.openejb.cdi.CdiBuilder; import org.apache.openejb.cdi.OpenEJBLifecycle; import org.apache.openejb.cdi.Proxys; @@ -129,6 +130,7 @@ import org.apache.tomee.common.NamingUtil; import org.apache.tomee.common.UserTransactionFactory; import org.apache.tomee.loader.TomcatHelper; import org.apache.webbeans.config.WebBeansContext; +import org.apache.webbeans.spi.ContextsService; import org.apache.webbeans.spi.adaptor.ELAdaptor; import org.omg.CORBA.ORB; @@ -265,6 +267,7 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare private ClassLoader parentClassLoader; private boolean initJEEInfo = true; + private final ServletContextHandler servletContextHandler; /** * Creates a new web application builder @@ -323,6 +326,7 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare configurationFactory = new ConfigurationFactory(); deploymentLoader = new DeploymentLoader(); + servletContextHandler = new ServletContextHandler(); setComponentsUsedByCDI(); try { // before tomcat was using ServiceLoader or manually instantiation, now it uses SL for itself so we can be in conflict @@ -341,7 +345,7 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare systemInstance.setComponent(javax.servlet.http.HttpSession.class, Proxys.threadLocalRequestSessionProxy(OpenEJBSecurityListener.requests, null)); } if (systemInstance.getComponent(ServletContext.class) == null) { - systemInstance.setComponent(ServletContext.class, Proxys.handlerProxy(ServletContext.class, new ServletContextHandler())); + systemInstance.setComponent(ServletContext.class, Proxys.handlerProxy(servletContextHandler, ServletContext.class, CdiAppContextsService.FiredManually.class)); } } @@ -1211,7 +1215,12 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare setFinderOnContextConfig(standardContext, appModule); - appContext = a.createApplication(contextInfo.appInfo, classLoader); + servletContextHandler.getContexts().put(classLoader, standardContext.getServletContext()); + try { + appContext = a.createApplication(contextInfo.appInfo, classLoader); + } finally { + servletContextHandler.getContexts().remove(classLoader); + } // todo add watched resources to context eagerInitOfLocalBeanProxies(appContext.getBeanContexts(), classLoader); @@ -1325,6 +1334,7 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare if (!contextInfo.appInfo.webAppAlone) { final List<BeanContext> beanContexts = assembler.initEjbs(classLoader, contextInfo.appInfo, appContext, injections, new ArrayList<BeanContext>(), webAppInfo.moduleId); OpenEJBLifecycle.CURRENT_APP_INFO.set(contextInfo.appInfo); + servletContextHandler.getContexts().put(classLoader, standardContext.getServletContext()); try { new CdiBuilder().build(contextInfo.appInfo, appContext, beanContexts, webContext); } catch (final Exception e) { @@ -1334,6 +1344,7 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare } throw e; } finally { + servletContextHandler.getContexts().remove(classLoader); OpenEJBLifecycle.CURRENT_APP_INFO.remove(); } assembler.startEjbs(true, beanContexts); @@ -1694,6 +1705,11 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare WebBeansThreadBindingListener webBeansThreadBindingListener = new WebBeansThreadBindingListener(webBeansContext, standardContext.getThreadBindingListener()); standardContext.setThreadBindingListener(webBeansThreadBindingListener); } + + final ContextsService contextsService = webBeansContext.getContextsService(); + if (CdiAppContextsService.class.isInstance(contextsService)) { // here ServletContext is usable + CdiAppContextsService.class.cast(contextsService).applicationStarted(standardContext.getServletContext()); + } } else { // just add the end listener to be able to stack tasks to execute at the request end final EndWebBeansListener endWebBeansListener = new EndWebBeansListener(webBeansContext); @@ -1757,6 +1773,8 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare } addConfiguredDocBases(standardContext, contextInfo); + + } private static String appVersion(final AppInfo appInfo) { http://git-wip-us.apache.org/repos/asf/tomee/blob/b25b8bda/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/ServletContextHandler.java ---------------------------------------------------------------------- diff --git a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/ServletContextHandler.java b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/ServletContextHandler.java index 63b3031..f7c76cc 100644 --- a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/ServletContextHandler.java +++ b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/ServletContextHandler.java @@ -23,27 +23,42 @@ import org.apache.openejb.loader.SystemInstance; import org.apache.openejb.spi.ContainerSystem; import org.apache.tomee.catalina.OpenEJBSecurityListener; +import javax.servlet.ServletContext; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; public class ServletContextHandler implements InvocationHandler { + private final ConcurrentMap<ClassLoader, ServletContext> contexts = new ConcurrentHashMap<>(); + @Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { - // ITE are handler by Proxys + // ITE are handled by Proxys final Request request = OpenEJBSecurityListener.requests.get(); if (request != null) { return method.invoke(request.getServletContext(), args); } + final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + final ServletContext c = contexts.get(contextClassLoader); + if (c != null) { + return method.invoke(c, args); + } + OpenEJBSecurityListener.requests.remove(); // can be a not container thread so clean it up for (final AppContext a : SystemInstance.get().getComponent(ContainerSystem.class).getAppContexts()) { for (final WebContext w : a.getWebContexts()) { - if (w.getClassLoader() == Thread.currentThread().getContextClassLoader()) { // not in CXF so == should be fine + if (w.getClassLoader() == contextClassLoader) { // not in CXF so == should be fine return method.invoke(w.getServletContext(), args); } } } - throw new IllegalStateException("Didnt find a web context for " + Thread.currentThread().getContextClassLoader()); + throw new IllegalStateException("Didnt find a web context for " + contextClassLoader); + } + + public ConcurrentMap<ClassLoader, ServletContext> getContexts() { + return contexts; } }