FYI, this change broke 22 tests in the embedded setup. The change is definitely a good one, but when we have a moment to catch our breath we should find a way to at least mock this.
For RequestScoped I ended up making a TestNG Listener that stars/stops a request scope before and after each test method. That was a nice approach as the guts themselves weren't mocked and what we're testing is the real behavior. Not sure if we could do something similar (always start a session or other scope), but an idea. -David On Jul 15, 2011, at 4:41 PM, [email protected] wrote: > Author: djencks > Date: Fri Jul 15 23:41:06 2011 > New Revision: 1147347 > > URL: http://svn.apache.org/viewvc?rev=1147347&view=rev > Log: > GERONIMO-5050 add in session management to contexts service > > Modified: > openejb/trunk/openejb3/container/openejb-core/pom.xml > > openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiAppContextsService.java > openejb/trunk/openejb3/pom.xml > > Modified: openejb/trunk/openejb3/container/openejb-core/pom.xml > URL: > http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/pom.xml?rev=1147347&r1=1147346&r2=1147347&view=diff > ============================================================================== > --- openejb/trunk/openejb3/container/openejb-core/pom.xml (original) > +++ openejb/trunk/openejb3/container/openejb-core/pom.xml Fri Jul 15 23:41:06 > 2011 > @@ -425,6 +425,10 @@ > <groupId>org.apache.openwebbeans</groupId> > </dependency> > <dependency> > + <groupId>org.apache.openwebbeans</groupId> > + <artifactId>openwebbeans-web</artifactId> > + </dependency> > + <dependency> > <groupId>org.beanshell</groupId> > <artifactId>bsh</artifactId> > </dependency> > > Modified: > openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiAppContextsService.java > URL: > http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiAppContextsService.java?rev=1147347&r1=1147346&r2=1147347&view=diff > ============================================================================== > --- > openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiAppContextsService.java > (original) > +++ > openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiAppContextsService.java > Fri Jul 15 23:41:06 2011 > @@ -18,44 +18,43 @@ package org.apache.openejb.cdi; > > import org.apache.openejb.util.LogCategory; > import org.apache.openejb.util.Logger; > +import org.apache.webbeans.config.OWBLogConst; > import org.apache.webbeans.config.WebBeansContext; > -import org.apache.webbeans.context.AbstractContextsService; > -import org.apache.webbeans.context.ApplicationContext; > -import org.apache.webbeans.context.ConversationContext; > -import org.apache.webbeans.context.DependentContext; > -import org.apache.webbeans.context.RequestContext; > -import org.apache.webbeans.context.SessionContext; > -import org.apache.webbeans.context.SingletonContext; > +import org.apache.webbeans.context.*; > +import org.apache.webbeans.el.ELContextStore; > import org.apache.webbeans.spi.ContextsService; > +import org.apache.webbeans.web.context.ServletRequestContext; > +import org.apache.webbeans.web.context.SessionContextManager; > > -import javax.enterprise.context.ApplicationScoped; > -import javax.enterprise.context.ContextException; > -import javax.enterprise.context.ConversationScoped; > -import javax.enterprise.context.Dependent; > -import javax.enterprise.context.RequestScoped; > -import javax.enterprise.context.SessionScoped; > +import javax.enterprise.context.*; > import javax.enterprise.context.spi.Context; > import javax.inject.Singleton; > - > +import javax.servlet.ServletRequestEvent; > +import javax.servlet.http.HttpServletRequest; > +import javax.servlet.http.HttpSession; > import java.lang.annotation.Annotation; > > public class CdiAppContextsService extends AbstractContextsService implements > ContextsService { > > private static final Logger logger = > Logger.getInstance(LogCategory.OPENEJB.createChild("cdi"), > CdiAppContextsService.class); > private final ThreadLocal<RequestContext> requestContext = new > ThreadLocal<RequestContext>(); > + > private final ThreadLocal<SessionContext> sessionContext = new > ThreadLocal<SessionContext>(); > + private final SessionContextManager sessionCtxManager = new > SessionContextManager(); > + > + /** > + * Conversation context manager > + */ > private final ThreadLocal<ConversationContext> conversationContext; > + > private final DependentContext dependentContext = new DependentContext(); > > - private final ApplicationContext currentApplicationContext = new > ApplicationContext(); > - private final SingletonContext currentSingletonContext = new > SingletonContext(); > + private final ApplicationContext applicationContext = new > ApplicationContext(); > > - public CdiAppContextsService() { > - this(false); > - } > + private final SingletonContext singletonContext = new SingletonContext(); > > - public CdiAppContextsService(WebBeansContext webBeansContext) { > - > this(webBeansContext.getOpenWebBeansConfiguration().supportsConversation()); > + public CdiAppContextsService() { > + > this(WebBeansContext.currentInstance().getOpenWebBeansConfiguration().supportsConversation()); > } > > public CdiAppContextsService(boolean supportsConversation) { > @@ -65,28 +64,54 @@ public class CdiAppContextsService exten > } else { > conversationContext = null; > } > + applicationContext.setActive(true); > + singletonContext.setActive(true); > } > > @Override > public void init(Object initializeObject) { > - currentApplicationContext.setActive(true); > - currentSingletonContext.setActive(true); > + //Start application context > + startContext(ApplicationScoped.class, initializeObject); > + > + //Start signelton context > + startContext(Singleton.class, initializeObject); > + } > + > + public void destroy(Object destroyObject) { > +// //Destroy application context > +// endContext(ApplicationScoped.class, destroyObject); > +// > +// //Destroy singleton context > +// endContext(Singleton.class, destroyObject); > + > + > + //Remove thread locals > + //for preventing memory leaks > + requestContext.set(null); > + requestContext.remove(); > + sessionContext.set(null); > + sessionContext.remove(); > + conversationContext.set(null); > + conversationContext.remove(); > + > } > > @Override > - public void startContext(Class<? extends Annotation> scopeType, Object > startParameter) throws ContextException { > + public void endContext(Class<? extends Annotation> scopeType, Object > endParameters) { > + > if (supportsContext(scopeType)) { > if (scopeType.equals(RequestScoped.class)) { > - initRequestContext(); > + destroyRequestContext(); > } else if (scopeType.equals(SessionScoped.class)) { > - initSessionContext(); > + destroySessionContext((HttpSession) endParameters); > } else if (scopeType.equals(ApplicationScoped.class)) { > + destroyApplicationContext(); > } else if (scopeType.equals(Dependent.class)) { > // Do nothing > } else if (scopeType.equals(Singleton.class)) { > - initSingletonContext(); > - } else if (conversationContext != null && > scopeType.equals(ConversationScoped.class)) { > - initConversationContext((ConversationContext)startParameter); > + destroySingletonContext(); > + } else if (supportsConversation() && > scopeType.equals(ConversationScoped.class)) { > + destroyConversationContext(); > } else { > if (logger.isWarningEnabled()) { > logger.warning("CDI-OpenWebBeans container in OpenEJB > does not support context scope " > @@ -95,24 +120,42 @@ public class CdiAppContextsService exten > } > } > } > + > } > > @Override > - public void endContext(Class<? extends Annotation> scopeType, Object > endParameters) { > + public Context getCurrentContext(Class<? extends Annotation> scopeType) { > + if (scopeType.equals(RequestScoped.class)) { > + return getRequestContext(); > + } else if (scopeType.equals(SessionScoped.class)) { > + return getSessionContext(); > + } else if (scopeType.equals(ApplicationScoped.class)) { > + return getApplicationContext(); > + } else if (supportsConversation() && > scopeType.equals(ConversationScoped.class)) { > + return getConversationContext(); > + } else if (scopeType.equals(Dependent.class)) { > + return dependentContext; > + } else if (scopeType.equals(Singleton.class)) { > + return getSingletonContext(); > + } > > + return null; > + } > + > + @Override > + public void startContext(Class<? extends Annotation> scopeType, Object > startParameter) throws ContextException { > if (supportsContext(scopeType)) { > if (scopeType.equals(RequestScoped.class)) { > - destroyRequestContext(); > + initRequestContext((ServletRequestEvent) startParameter); > } else if (scopeType.equals(SessionScoped.class)) { > - destroySessionContext(); > + initSessionContext((HttpSession) startParameter); > } else if (scopeType.equals(ApplicationScoped.class)) { > - destroyApplicationContext(); > } else if (scopeType.equals(Dependent.class)) { > // Do nothing > } else if (scopeType.equals(Singleton.class)) { > - destroySingletonContext(); > - } else if (conversationContext != null && > scopeType.equals(ConversationScoped.class)) { > - destroyConversationContext(); > + initSingletonContext(); > + } else if (supportsConversation() && > scopeType.equals(ConversationScoped.class)) { > + initConversationContext((ConversationContext) > startParameter); > } else { > if (logger.isWarningEnabled()) { > logger.warning("CDI-OpenWebBeans container in OpenEJB > does not support context scope " > @@ -121,54 +164,135 @@ public class CdiAppContextsService exten > } > } > } > - > } > > @Override > - public Context getCurrentContext(Class<? extends Annotation> scopeType) { > - if (supportsContext(scopeType)) { > - if (scopeType.equals(RequestScoped.class)) { > - return getRequestContext(); > - } else if (scopeType.equals(SessionScoped.class)) { > - return getSessionContext(); > - } else if (scopeType.equals(ApplicationScoped.class)) { > - return currentApplicationContext; > - } else if (scopeType.equals(Dependent.class)) { > - return dependentContext; > - } else if (conversationContext != null && > scopeType.equals(ConversationScoped.class)) { > - return getConversationContext(); > - } else { > - return currentSingletonContext; > - } > + public boolean supportsContext(Class<? extends Annotation> scopeType) { > + if (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; > } > > - return null; > + return false; > } > > - private Context getRequestContext() { > - RequestContext context = requestContext.get(); > -// if (context == null) { > -// > -// context = new RequestContext(); > -// context.setActive(true); > + private void initRequestContext(ServletRequestEvent event) { > + > + RequestContext rq = new ServletRequestContext(); > + rq.setActive(true); > + > + requestContext.set(rq);// set thread local > + if (event != null) { > + HttpServletRequest request = (HttpServletRequest) > event.getServletRequest(); > + ((ServletRequestContext) rq).setServletRequest(request); > + > + if (request != null) { > + //Re-initialize thread local for session > + HttpSession session = request.getSession(false); > + > + if (session != null) { > + initSessionContext(session); > + } > + > +// //Init thread local application context > +// initApplicationContext(event.getServletContext()); > // > -// requestContext.set(context); > -// } > - return context; > +// //Init thread local sigleton context > +// initSingletonContext(event.getServletContext()); > + } > + } > } > > - private Context getSessionContext() { > - SessionContext context = sessionContext.get(); > - if (context == null) { > + private void destroyRequestContext() { > + //Get context > + RequestContext context = getRequestContext(); > > - context = new SessionContext(); > - context.setActive(true); > + //Destroy context > + if (context != null) { > + context.destroy(); > + } > > - sessionContext.set(context); > + // clean up the EL caches after each request > + ELContextStore elStore = ELContextStore.getInstance(false); > + if (elStore != null) { > + elStore.destroyELContextStore(); > } > - return context; > + > + //Clear thread locals > + requestContext.set(null); > + requestContext.remove(); > + > + //Also clear application and singleton context > +// applicationContext.set(null); > +// applicationContext.remove(); > + > + //Singleton context > +// singletonContext.set(null); > +// singletonContext.remove(); > + > + //Conversation context > + conversationContext.set(null); > + conversationContext.remove(); > + } > + > + /** > + * Creates the session context at the session start. > + * > + * @param session http session object > + */ > + private void initSessionContext(HttpSession session) { > + if (session == null) { > + // no session -> no SessionContext > + return; > + } > + > + String sessionId = session.getId(); > + //Current context > + SessionContext currentSessionContext = > sessionCtxManager.getSessionContextWithSessionId(sessionId); > + > + //No current context > + if (currentSessionContext == null) { > + currentSessionContext = new SessionContext(); > + sessionCtxManager.addNewSessionContext(sessionId, > currentSessionContext); > + } > + //Activate > + currentSessionContext.setActive(true); > + > + //Set thread local > + sessionContext.set(currentSessionContext); > } > > + /** > + * Destroys the session context and all of its components at the end of > the > + * session. > + * > + * @param session http session object > + */ > + private void destroySessionContext(HttpSession session) { > + if (session != null) { > + //Get current session context > + SessionContext context = sessionContext.get(); > + > + //Destroy context > + if (context != null) { > + context.destroy(); > + } > + > + //Clear thread locals > + sessionContext.set(null); > + sessionContext.remove(); > + > + //Remove session from manager > + > sessionCtxManager.destroySessionContextWithSessionId(session.getId()); > + } > + } > + > + //we don't have initApplicationContext > + > private void destroyApplicationContext() { > // look for thread local > // this can be set by initRequestContext > @@ -182,29 +306,6 @@ public class CdiAppContextsService exten > // this.currentSingletonContext.destroy(); > } > > - @Override > - public boolean supportsContext(Class<? extends Annotation> scopeType) { > - if (scopeType.equals(RequestScoped.class) > - || scopeType.equals(SessionScoped.class) > - || scopeType.equals(ApplicationScoped.class) > - || scopeType.equals(Dependent.class) > - || scopeType.equals(Singleton.class) > - || (scopeType.equals(ConversationScoped.class) && > conversationContext != null)) { > - return true; > - } > - > - return false; > - } > - > - /** > - * Get current conversation ctx. > - * > - * @return conversation context > - */ > - private ConversationContext getConversationContext() { > - return conversationContext.get(); > - } > - > /** > * Initialize conversation context. > * > @@ -241,62 +342,90 @@ public class CdiAppContextsService exten > conversationContext.remove(); > } > > - private void initRequestContext() { > - > - RequestContext rq = new RequestContext(); > - rq.setActive(true); > > - requestContext.set(rq); > + private RequestContext getRequestContext() { > + return requestContext.get(); > } > > - private void destroyRequestContext() { > - // Get context > - RequestContext context = requestContext.get(); > + private Context getSessionContext() { > + SessionContext context = sessionContext.get(); > + if (context == null) { > > - // Destroy context > - if (context != null) { > - context.destroy(); > + lazyStartSessionContext(); > + context = sessionContext.get(); > } > - > - // Remove > - requestContext.remove(); > + return context; > } > > - private void initSessionContext() { > + /** > + * Gets application context. > + * > + * @return application context > + */ > + private ApplicationContext getApplicationContext() { > + return applicationContext; > + } > > - SessionContext rq = new SessionContext(); > - rq.setActive(true); > + /** > + * Gets singleton context. > + * > + * @return singleton context > + */ > + private SingletonContext getSingletonContext() { > + return singletonContext; > + } > > - sessionContext.set(rq); > + /** > + * Get current conversation ctx. > + * > + * @return conversation context > + */ > + private ConversationContext getConversationContext() { > + return conversationContext.get(); > } > > - private void destroySessionContext() { > - // Get context > - SessionContext context = sessionContext.get(); > + private Context lazyStartSessionContext() { > > - // Destroy context > - if (context != null) { > - context.destroy(); > + if (logger.isDebugEnabled()) { > + logger.debug(">lazyStartSessionContext"); > } > > - // Remove > - sessionContext.remove(); > - } > - > - public void destroy(Object destroyObject) { > -// //Destroy application context > -// endContext(ApplicationScoped.class, destroyObject); > -// > -// //Destroy singleton context > -// endContext(Singleton.class, destroyObject); > + Context webContext = null; > + Context context = getCurrentContext(RequestScoped.class); > + if (context instanceof ServletRequestContext) { > + ServletRequestContext requestContext = (ServletRequestContext) > context; > + HttpServletRequest servletRequest = > requestContext.getServletRequest(); > + if (null != servletRequest) { // this could be null if there is > no active request context > + try { > + HttpSession currentSession = servletRequest.getSession(); > + initSessionContext(currentSession); > +// if (failoverService != null && > failoverService.isSupportFailOver()) > +// { > +// failoverService.sessionIsInUse(currentSession); > +// } > + > + if (logger.isDebugEnabled()) { > + logger.debug("Lazy SESSION context initialization > SUCCESS"); > + } > + } catch (Exception e) { > + logger.error(OWBLogConst.ERROR_0013, e); > + } > > + } else { > + logger.warning("Could NOT lazily initialize session context > because NO active request context"); > + } > + } else { > + logger.warning("Could NOT lazily initialize session context > because of " + context + " RequestContext"); > + } > > - //Remove thread locals > - //for preventing memory leaks > - requestContext.remove(); > + if (logger.isDebugEnabled()) { > + logger.debug("<lazyStartSessionContext " + webContext); > + } > + return webContext; > + } > > - //Thread local values to null > - requestContext.set(null); > + private boolean supportsConversation() { > + return conversationContext != null; > } > > } > > Modified: openejb/trunk/openejb3/pom.xml > URL: > http://svn.apache.org/viewvc/openejb/trunk/openejb3/pom.xml?rev=1147347&r1=1147346&r2=1147347&view=diff > ============================================================================== > --- openejb/trunk/openejb3/pom.xml (original) > +++ openejb/trunk/openejb3/pom.xml Fri Jul 15 23:41:06 2011 > @@ -1256,6 +1256,11 @@ > </exclusions> > </dependency> > <dependency> > + <groupId>org.apache.openwebbeans</groupId> > + <artifactId>openwebbeans-web</artifactId> > + <version>${org.apache.openwebbeans.version}</version> > + </dependency> > + <dependency> > <artifactId>openwebbeans-ee-common</artifactId> > <groupId>org.apache.openwebbeans</groupId> > <version>${org.apache.openwebbeans.version}</version> > > >
