Author: rmannibucau Date: Tue Jan 15 15:31:55 2013 New Revision: 1433456 URL: http://svn.apache.org/viewvc?rev=1433456&view=rev Log: TOMEE-737 TOMEE-731 better session proxying when session-context activated + config of OWB through app properties
Added: tomee/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/SessionNormalScopeBeanHandler.java Modified: tomee/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiAppContextsService.java tomee/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java tomee/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/SessionContextBackedByHttpSession.java Modified: tomee/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiAppContextsService.java URL: http://svn.apache.org/viewvc/tomee/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiAppContextsService.java?rev=1433456&r1=1433455&r2=1433456&view=diff ============================================================================== --- tomee/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiAppContextsService.java (original) +++ tomee/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiAppContextsService.java Tue Jan 15 15:31:55 2013 @@ -16,7 +16,6 @@ */ package org.apache.openejb.cdi; -import org.apache.openejb.loader.SystemInstance; import org.apache.openejb.util.LogCategory; import org.apache.openejb.util.Logger; import org.apache.webbeans.config.OWBLogConst; @@ -56,8 +55,6 @@ public class CdiAppContextsService exten private static final Logger logger = Logger.getInstance(LogCategory.OPENEJB.createChild("cdi"), CdiAppContextsService.class); - private static final String SESSION_CONTEXT_CLAZZ = SystemInstance.get().getProperty("openejb.session-context", null); - private final ThreadLocal<RequestContext> requestContext = new ThreadLocal<RequestContext>(); private final ThreadLocal<SessionContext> sessionContext = new ThreadLocal<SessionContext>(); @@ -81,10 +78,12 @@ public class CdiAppContextsService exten } public CdiAppContextsService(WebBeansContext wbc, boolean supportsConversation) { - webBeansContext = wbc; - if (wbc == null) { - wbc = WebBeansContext.currentInstance(); + if (wbc != null) { + webBeansContext = wbc; + } else { + webBeansContext = WebBeansContext.currentInstance(); } + dependentContext.setActive(true); if (supportsConversation) { conversationContext = new ThreadLocal<ConversationContext>(); @@ -198,16 +197,13 @@ public class CdiAppContextsService exten @Override public boolean supportsContext(Class<? extends Annotation> scopeType) { - if (scopeType.equals(RequestScoped.class) + return scopeType.equals(RequestScoped.class) || scopeType.equals(SessionScoped.class) || scopeType.equals(ApplicationScoped.class) || scopeType.equals(Dependent.class) || scopeType.equals(Singleton.class) - || (scopeType.equals(ConversationScoped.class) && supportsConversation())) { - return true; - } + || (scopeType.equals(ConversationScoped.class) && supportsConversation()); - return false; } private void initRequestContext(ServletRequestEvent event) { @@ -330,12 +326,8 @@ public class CdiAppContextsService exten } private SessionContext newSessionContext(final HttpSession session) { - if (SESSION_CONTEXT_CLAZZ != null) { - String classname = SESSION_CONTEXT_CLAZZ; - if ("http".equals(classname)) { // easier in the config - classname = "org.apache.tomee.catalina.cdi.SessionContextBackedByHttpSession"; - } - + final String classname = ThreadSingletonServiceImpl.sessionContextClass(); + if (classname != null) { try { final Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass(classname); try { @@ -346,7 +338,7 @@ public class CdiAppContextsService exten } } catch (Exception e) { - logger.error("Can't instantiate " + SESSION_CONTEXT_CLAZZ + ", using default session context", e); + logger.error("Can't instantiate " + classname + ", using default session context", e); } } return new SessionContext(); @@ -520,5 +512,4 @@ public class CdiAppContextsService exten private boolean supportsConversation() { return conversationContext != null; } - } Modified: tomee/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java URL: http://svn.apache.org/viewvc/tomee/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java?rev=1433456&r1=1433455&r2=1433456&view=diff ============================================================================== --- tomee/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java (original) +++ tomee/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java Tue Jan 15 15:31:55 2013 @@ -62,6 +62,7 @@ public class ThreadSingletonServiceImpl public static final Logger logger = Logger.getInstance(LogCategory.OPENEJB_STARTUP, ThreadSingletonServiceImpl.class); public static final String OPENEJB_OWB_PROXY_FACTORY = "openejb.owb.proxy-factory"; + private static final String SESSION_CONTEXT_CLAZZ = SystemInstance.get().getProperty("openejb.session-context", null); //this needs to be static because OWB won't tell us what the existing SingletonService is and you can't set it twice. private static final ThreadLocal<WebBeansContext> contexts = new ThreadLocal<WebBeansContext>(); @@ -81,12 +82,13 @@ public class ThreadSingletonServiceImpl @Override public void initialize(StartupObject startupObject) { - AppContext appContext = startupObject.getAppContext(); + final AppContext appContext = startupObject.getAppContext(); appContext.setCdiEnabled(hasBeans(startupObject.getAppInfo())); //initialize owb context, cf geronimo's OpenWebBeansGBean - Properties properties = new Properties(); + final Properties properties = new Properties(); + Map<Class<?>, Object> services = new HashMap<Class<?>, Object>(); properties.setProperty(OpenWebBeansConfiguration.APPLICATION_IS_JSP, "true"); properties.setProperty(OpenWebBeansConfiguration.USE_EJB_DISCOVERY, "true"); @@ -103,17 +105,26 @@ public class ThreadSingletonServiceImpl properties.setProperty(OpenWebBeansConfiguration.IGNORED_INTERFACES, failoverService); } + final boolean tomee = SystemInstance.get().getProperty("openejb.loader", "foo").startsWith("tomcat"); + properties.setProperty("org.apache.webbeans.proxy.mapping.javax.enterprise.context.ApplicationScoped", ApplicationScopedBeanInterceptorHandler.class.getName()); - if (SystemInstance.get().getProperty("openejb.loader", "foo").startsWith("tomcat")) { + + if (tomee) { properties.setProperty("org.apache.webbeans.proxy.mapping.javax.enterprise.context.RequestScoped", RequestScopedBeanInterceptorHandler.class.getName()); } else { properties.setProperty("org.apache.webbeans.proxy.mapping.javax.enterprise.context.RequestScoped", NormalScopedBeanInterceptorHandler.class.getName()); } + if (SESSION_CONTEXT_CLAZZ != null && tomee) { + properties.setProperty("org.apache.webbeans.proxy.mapping.javax.enterprise.context.SessionScoped", "org.apache.tomee.catalina.cdi.SessionNormalScopeBeanHandler"); + } + if (SystemInstance.get().getOptions().get(WEBBEANS_FAILOVER_ISSUPPORTFAILOVER, false)) { properties.setProperty(WEBBEANS_FAILOVER_ISSUPPORTFAILOVER, "true"); } + properties.putAll(appContext.getProperties()); + services.put(AppContext.class, appContext); services.put(TransactionService.class, new OpenEJBTransactionService()); if (startupObject.getWebContext() == null) { @@ -312,4 +323,13 @@ public class ThreadSingletonServiceImpl ctx.clear(); } + public static String sessionContextClass() { + if (SESSION_CONTEXT_CLAZZ != null) { + if ("http".equals(SESSION_CONTEXT_CLAZZ)) { // easy way to manage this config + return "org.apache.tomee.catalina.cdi.SessionContextBackedByHttpSession"; + } + return SESSION_CONTEXT_CLAZZ; + } + return null; + } } Modified: tomee/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/SessionContextBackedByHttpSession.java URL: http://svn.apache.org/viewvc/tomee/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/SessionContextBackedByHttpSession.java?rev=1433456&r1=1433455&r2=1433456&view=diff ============================================================================== --- tomee/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/SessionContextBackedByHttpSession.java (original) +++ tomee/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/SessionContextBackedByHttpSession.java Tue Jan 15 15:31:55 2013 @@ -1,3 +1,19 @@ +/** + * 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 org.apache.catalina.session.StandardSession; @@ -58,7 +74,7 @@ public class SessionContextBackedByHttpS } } - private static String key(final Object key) { + public static String key(final Object key) { if (key instanceof String) { // avoid nested calls return (String) key; } @@ -70,6 +86,10 @@ public class SessionContextBackedByHttpS return key.toString(); // shouldn't occur } + public HttpSession getSession() { + return session; + } + private static class DirectSessionMap implements ConcurrentMap<Contextual<?>, BeanInstanceBag<?>> { private final ConcurrentHashMap<String, Object> delegate; @@ -229,8 +249,9 @@ public class SessionContextBackedByHttpS @Override public BeanInstanceBag<?> put(Contextual<?> key, BeanInstanceBag<?> value) { + final BeanInstanceBag<?> bag = get(key); session.setAttribute(key(key), value); - return value; + return bag; } @Override @@ -262,6 +283,11 @@ public class SessionContextBackedByHttpS remove(key(key)); return true; } + + @Override + public String toString() { + return "HttpSessionMap{session=" + session + '}'; + } } } Added: tomee/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/SessionNormalScopeBeanHandler.java URL: http://svn.apache.org/viewvc/tomee/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/SessionNormalScopeBeanHandler.java?rev=1433456&view=auto ============================================================================== --- tomee/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/SessionNormalScopeBeanHandler.java (added) +++ tomee/trunk/openejb/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/cdi/SessionNormalScopeBeanHandler.java Tue Jan 15 15:31:55 2013 @@ -0,0 +1,67 @@ +/** + * 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 org.apache.webbeans.component.OwbBean; +import org.apache.webbeans.context.creational.BeanInstanceBag; +import org.apache.webbeans.context.creational.CreationalContextImpl; +import org.apache.webbeans.intercept.NormalScopedBeanInterceptorHandler; + +import javax.enterprise.context.SessionScoped; +import javax.enterprise.context.spi.Context; +import javax.enterprise.context.spi.CreationalContext; +import javax.servlet.http.HttpSession; +import java.lang.reflect.Method; + +public class SessionNormalScopeBeanHandler extends NormalScopedBeanInterceptorHandler { + public SessionNormalScopeBeanHandler(final OwbBean<?> bean, final CreationalContext<?> creationalContext) { + super(bean, creationalContext); + } + + @Override + public Object invoke(final Object instance, final Method method, final Object[] arguments) throws Throwable { + final Object webbeansInstance = getContextualInstance(); + try { + return super.invoke(webbeansInstance, method, arguments, (CreationalContextImpl<?>) getContextualCreationalContext()); + } finally { + updateBean(webbeansInstance); + } + } + + private void updateBean(final Object value) { + final HttpSession session = session(); + if (session == null) { + return; + } + + // go through all listeners to be able to be replicated or do any processing which can be done + final String key = SessionContextBackedByHttpSession.key(bean); + final BeanInstanceBag<Object> bag = (BeanInstanceBag<Object>) session.getAttribute(key); + if (bag != null) { + bag.setBeanInstance(value); + session.setAttribute(key, bag); + } + } + + private HttpSession session() { + final Context context = getBeanManager().getContext(SessionScoped.class); + if (!SessionContextBackedByHttpSession.class.isInstance(context)) { + return null; + } + return ((SessionContextBackedByHttpSession) context).getSession(); + } +}