[jboss-cvs] jboss-seam/src/main/org/jboss/seam/contexts ...
Gavin King
gavin.king at jboss.com
Wed Jun 20 04:23:17 EDT 2007
User: gavin
Date: 07/06/20 04:23:17
Modified: src/main/org/jboss/seam/contexts Contexts.java
ContextualHttpServletRequest.java Lifecycle.java
PageContext.java ServerConversationContext.java
SessionContext.java
Added: src/main/org/jboss/seam/contexts
FacesLifecycle.java ServletLifecycle.java
TestLifecycle.java
Log:
split up Lifecycle, much better
Revision Changes Path
1.52 +191 -8 jboss-seam/src/main/org/jboss/seam/contexts/Contexts.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: Contexts.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/src/main/org/jboss/seam/contexts/Contexts.java,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -b -r1.51 -r1.52
--- Contexts.java 20 Jun 2007 05:06:40 -0000 1.51
+++ Contexts.java 20 Jun 2007 08:23:17 -0000 1.52
@@ -1,23 +1,31 @@
/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
package org.jboss.seam.contexts;
import static org.jboss.seam.InterceptionType.NEVER;
import static org.jboss.seam.annotations.Install.BUILT_IN;
-import org.jboss.seam.log.LogProvider;
-import org.jboss.seam.log.Logging;
+import java.util.Map;
+
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Intercept;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.bpm.BusinessProcess;
import org.jboss.seam.core.Events;
+import org.jboss.seam.core.Init;
+import org.jboss.seam.core.Manager;
+import org.jboss.seam.core.Mutable;
+import org.jboss.seam.core.ServletSession;
+import org.jboss.seam.log.LogProvider;
+import org.jboss.seam.log.Logging;
+import org.jboss.seam.transaction.Transaction;
/**
* Provides access to the current contexts associated with the thread.
@@ -112,6 +120,9 @@
return businessProcessContext.get() != null;
}
+ /**
+ * Remove the named component from all contexts.
+ */
public static void removeFromAllContexts(String name)
{
log.debug("removing from all contexts: " + name);
@@ -145,6 +156,13 @@
}
}
+ /**
+ * Search for a named attribute in all contexts, in the
+ * following order: method, event, page, conversation,
+ * session, business process, application.
+ *
+ * @return the first component found, or null
+ */
public static Object lookupInStatefulContexts(String name)
{
if (isMethodContextActive())
@@ -167,7 +185,7 @@
}
}
- if ( isPageContextActive() && Lifecycle.getPhaseId()!=null ) // phase id is null when third-party phase listeners try to do stuff
+ if ( isPageContextActive() )
{
Object result = getPageContext().get(name);
if (result!=null)
@@ -221,6 +239,9 @@
}
+ /**
+ * Destroy all components in the given context
+ */
public static void destroy(Context context)
{
if ( Events.exists() ) Events.instance().raiseEvent("org.jboss.seam.preDestroyContext." + context.getType().toString());
@@ -251,4 +272,166 @@
if ( Events.exists() ) Events.instance().raiseEvent("org.jboss.seam.postDestroyContext." + context.getType().toString());
}
+ /**
+ * Startup all @Startup components in the given scope
+ */
+ static void startup(ScopeType scopeType)
+ {
+ Context context = Contexts.getApplicationContext();
+ for ( String name: context.getNames() )
+ {
+ Object object = context.get(name);
+ if ( object!=null && (object instanceof Component) )
+ {
+ Component component = (Component) object;
+ if ( component.isStartup() && component.getScope()==scopeType )
+ {
+ startup(component);
+ }
+ }
+ }
+ }
+
+ /**
+ * Startup a component and all its dependencies
+ */
+ static void startup(Component component)
+ {
+ if ( component.isStartup() )
+ {
+ for ( String dependency: component.getDependencies() )
+ {
+ Component dependentComponent = Component.forName(dependency);
+ if (dependentComponent!=null)
+ {
+ startup(dependentComponent);
+ }
+ }
+ }
+
+ if ( !component.getScope().getContext().isSet( component.getName() ) )
+ {
+ log.info( "starting up: " + component.getName() );
+ component.newInstance();
+ }
+ }
+
+ /**
+ * Does this context attribute need to be force-replicated?
+ */
+ static boolean isAttributeDirty(Object attribute)
+ {
+ return attribute instanceof Mutable && ( (Mutable) attribute ).clearDirty();
+ }
+
+ /**
+ * At the end of a request, flush all contexts to their underlying
+ * persistent stores, or destroy their attributes (one or the other!).
+ */
+ static void flushAndDestroyContexts()
+ {
+
+ if ( isConversationContextActive() )
+ {
+
+ if ( isBusinessProcessContextActive() )
+ {
+ boolean transactionActive = false;
+ try
+ {
+ transactionActive = Transaction.instance().isActive();
+ }
+ catch (Exception e)
+ {
+ log.error("could not discover transaction status");
+ }
+ if (transactionActive)
+ {
+ //in calls to MDBs and remote calls to SBs, the
+ //transaction doesn't commit until after contexts
+ //are destroyed, so pre-emptively flush here:
+ getBusinessProcessContext().flush();
+ }
+
+ //TODO: it would be nice if BP context spanned redirects along with the conversation
+ // this would also require changes to BusinessProcessContext
+ boolean destroyBusinessProcessContext = !Init.instance().isJbpmInstalled() ||
+ !BusinessProcess.instance().hasActiveProcess();
+ if (destroyBusinessProcessContext)
+ {
+ //TODO: note that this occurs from Lifecycle.endRequest(), after
+ // the Seam-managed txn was committed, but Contexts.destroy()
+ // calls BusinessProcessContext.getNames(), which hits the
+ // database!
+ log.debug("destroying business process context");
+ destroy( getBusinessProcessContext() );
+ }
+ }
+
+ if ( !Manager.instance().isLongRunningConversation() )
+ {
+ log.debug("destroying conversation context");
+ destroy( getConversationContext() );
+ }
+ if ( !Init.instance().isClientSideConversations() )
+ {
+ //note that we need to flush even if the session is
+ //about to be invalidated, since we still need
+ //to destroy the conversation context in endSession()
+ log.debug("flushing server-side conversation context");
+ getConversationContext().flush();
+ }
+
+ //uses the event and session contexts
+ if ( ServletSession.getInstance()!=null )
+ {
+ Manager.instance().unlockConversation();
+ }
+
+ }
+
+ if ( isSessionContextActive() )
+ {
+ log.debug("flushing session context");
+ getSessionContext().flush();
+ }
+
+ //destroy the event context after the
+ //conversation context, since we need
+ //the manager to flush() conversation
+ if ( isEventContextActive() )
+ {
+ log.debug("destroying event context");
+ destroy( getEventContext() );
+ }
+
+ }
+
+ /**
+ * Destroy a conversation context that is not currently bound to the request, called
+ * due to a timeout.
+ *
+ * @param session the current session, to which both current and destroyed conversation belong
+ * @param conversationId the conversation id of the conversation to be destroyed
+ */
+ static void destroyConversationContext(Map<String, Object> session, String conversationId)
+ {
+ Context current = getConversationContext();
+ ServerConversationContext temp = new ServerConversationContext(session, conversationId);
+ conversationContext.set(temp);
+ try
+ {
+ destroy(temp);
+ if ( !ServletSession.instance().isInvalid() ) //its also unnecessary during a session timeout
+ {
+ temp.clear();
+ temp.flush();
+ }
+ }
+ finally
+ {
+ conversationContext.set(current);
+ }
+ }
+
}
1.3 +4 -7 jboss-seam/src/main/org/jboss/seam/contexts/ContextualHttpServletRequest.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: ContextualHttpServletRequest.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/src/main/org/jboss/seam/contexts/ContextualHttpServletRequest.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- ContextualHttpServletRequest.java 19 Jun 2007 19:02:31 -0000 1.2
+++ ContextualHttpServletRequest.java 20 Jun 2007 08:23:17 -0000 1.3
@@ -2,7 +2,6 @@
import java.io.IOException;
-import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@@ -18,12 +17,10 @@
private static final LogProvider log = Logging.getLogProvider(ContextualHttpServletRequest.class);
private final HttpServletRequest request;
- private final ServletContext servletContext;
- public ContextualHttpServletRequest(HttpServletRequest request, ServletContext servletContext)
+ public ContextualHttpServletRequest(HttpServletRequest request)
{
this.request = request;
- this.servletContext = servletContext;
}
public abstract void process() throws Exception;
@@ -31,18 +28,18 @@
public void run() throws ServletException, IOException
{
log.debug("beginning request");
- Lifecycle.beginRequest(servletContext, request);
+ ServletLifecycle.beginRequest(request);
ServletContexts.instance().setRequest(request);
restoreConversationId();
Manager.instance().restoreConversation();
- Lifecycle.resumeConversation(request);
+ ServletLifecycle.resumeConversation(request);
handleConversationPropagation();
try
{
process();
//TODO: conversation timeout
Manager.instance().endRequest( new ServletRequestSessionMap(request) );
- Lifecycle.endRequest(request);
+ ServletLifecycle.endRequest(request);
}
catch (IOException ioe)
{
1.101 +82 -416 jboss-seam/src/main/org/jboss/seam/contexts/Lifecycle.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: Lifecycle.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/src/main/org/jboss/seam/contexts/Lifecycle.java,v
retrieving revision 1.100
retrieving revision 1.101
diff -u -b -r1.100 -r1.101
--- Lifecycle.java 19 Jun 2007 19:02:31 -0000 1.100
+++ Lifecycle.java 20 Jun 2007 08:23:17 -0000 1.101
@@ -9,27 +9,11 @@
import java.util.Map;
import java.util.Set;
-import javax.faces.context.ExternalContext;
-import javax.faces.context.FacesContext;
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-
-import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
-import org.jboss.seam.bpm.BusinessProcess;
import org.jboss.seam.core.ConversationEntries;
-import org.jboss.seam.core.Events;
-import org.jboss.seam.core.Init;
import org.jboss.seam.core.Manager;
-import org.jboss.seam.core.Mutable;
-import org.jboss.seam.core.ServletSession;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
-import org.jboss.seam.navigation.Pages;
-import org.jboss.seam.servlet.ServletApplicationMap;
-import org.jboss.seam.servlet.ServletRequestMap;
-import org.jboss.seam.servlet.ServletRequestSessionMap;
-import org.jboss.seam.transaction.Transaction;
/**
* @author Gavin King
@@ -38,30 +22,65 @@
public class Lifecycle
{
- private static final LogProvider log = Logging.getLogProvider(Lifecycle.class);
+ static final LogProvider log = Logging.getLogProvider(Lifecycle.class);
+
+ private static ThreadLocal<Boolean> destroying = new ThreadLocal<Boolean>();
+ private static Map<String, Object> application;
+ private static ThreadLocal phaseId = new ThreadLocal();
+
+ public static Object getPhaseId()
+ {
+ return phaseId.get();
+ }
- public static void beginRequest(ExternalContext externalContext)
+ static void setPhaseId(Object phase)
{
- log.debug( ">>> Begin JSF request" );
- Contexts.eventContext.set( new EventContext( externalContext.getRequestMap() ) );
- Contexts.applicationContext.set( new ApplicationContext( externalContext.getApplicationMap() ) );
- Contexts.sessionContext.set( new SessionContext( externalContext.getSessionMap() ) );
- ServletSession servletSession = ServletSession.getInstance();
- if ( servletSession!=null && servletSession.isInvalidDueToNewScheme( Pages.getRequestScheme( FacesContext.getCurrentInstance() ) ) )
+ phaseId.set(phase);
+ }
+
+ public static Map<String, Object> getApplication()
+ {
+ if (application==null)
+ {
+ throw new IllegalStateException("Attempted to invoke a Seam component outside the an initialized application");
+ }
+ return application;
+ }
+
+ public static void beginApplication(Map<String, Object> app)
{
- invalidateSession(externalContext);
+ application = app;
}
- Contexts.conversationContext.set(null); //in case endRequest() was never called
- //Events.instance(); //TODO: only for now, until we have a way to do EL outside of JSF!
+
+ public static void endApplication()
+ {
+ log.debug("Undeploying, destroying application context");
+
+ Context tempApplicationContext = new ApplicationContext( getApplication() );
+ Contexts.applicationContext.set(tempApplicationContext);
+ Contexts.destroy(tempApplicationContext);
+ Contexts.applicationContext.set(null);
+ Contexts.eventContext.set(null);
+ Contexts.sessionContext.set(null);
+ Contexts.conversationContext.set(null);
+
+ application = null;
}
- public static void beginRequest(ServletContext servletContext, HttpServletRequest request)
+ public static void startDestroying()
{
- log.debug( ">>> Begin web request" );
- Contexts.eventContext.set( new EventContext( new ServletRequestMap(request) ) );
- Contexts.sessionContext.set( new SessionContext( new ServletRequestSessionMap(request) ) );
- Contexts.applicationContext.set(new ApplicationContext( new ServletApplicationMap(servletContext) ) );
- Contexts.conversationContext.set(null); //in case endRequest() was never called
+ destroying.set(true);
+ }
+
+ public static void stopDestroying()
+ {
+ destroying.set(false);
+ }
+
+ public static boolean isDestroying()
+ {
+ Boolean value = destroying.get();
+ return value!=null && value.booleanValue();
}
public static void beginCall()
@@ -71,7 +90,7 @@
Contexts.sessionContext.set( new BasicContext(ScopeType.SESSION) );
Contexts.conversationContext.set( new BasicContext(ScopeType.CONVERSATION) );
Contexts.businessProcessContext.set( new BusinessProcessContext() );
- Contexts.applicationContext.set( new ApplicationContext( new ServletApplicationMap( getServletContext() ) ) );
+ Contexts.applicationContext.set( new ApplicationContext(application) );
}
public static void endCall()
@@ -79,7 +98,7 @@
try
{
Contexts.destroy( Contexts.getSessionContext() );
- flushAndDestroyContexts();
+ Contexts.flushAndDestroyContexts();
if ( Manager.instance().isLongRunningConversation() )
{
throw new IllegalStateException("Do not start long-running conversations in direct calls to EJBs");
@@ -92,25 +111,9 @@
}
}
- public static void beginTest(ServletContext context, Map<String, Object> session)
- {
- log.debug( ">>> Begin test" );
- Contexts.eventContext.set( new BasicContext(ScopeType.EVENT) );
- Contexts.conversationContext.set( new BasicContext(ScopeType.CONVERSATION) );
- Contexts.businessProcessContext.set( new BusinessProcessContext() );
- Contexts.sessionContext.set( new SessionContext(session) );
- Contexts.applicationContext.set( new ApplicationContext( new ServletApplicationMap(context) ) );
- }
-
- public static void endTest()
- {
- clearThreadlocals();
- log.debug( "<<< End test" );
- }
-
public static void mockApplication()
{
- Contexts.applicationContext.set( new ApplicationContext( new ServletApplicationMap( getServletContext() ) ) );
+ Contexts.applicationContext.set( new ApplicationContext(application) );
}
public static void unmockApplication()
@@ -130,107 +133,36 @@
Contexts.methodContext.set(context);
}
- public static void beginInitialization(ServletContext servletContext)
+ public static void endRequest()
{
- log.debug(">>> Begin initialization");
- Contexts.applicationContext.set( new ApplicationContext( new ServletApplicationMap(servletContext) ) );
- Contexts.eventContext.set( new BasicContext(ScopeType.EVENT) );
- Contexts.conversationContext.set( new BasicContext(ScopeType.CONVERSATION) );
- }
-
- public static void beginReinitialization(ServletContext servletContext, HttpServletRequest request)
+ log.debug("After request, destroying contexts");
+ try
{
- log.debug(">>> Begin re-initialization");
- Contexts.applicationContext.set( new ApplicationContext( new ServletApplicationMap(servletContext) ) );
- Contexts.eventContext.set( new BasicContext(ScopeType.EVENT) );
- Contexts.sessionContext.set( new SessionContext( new ServletRequestSessionMap(request) ) );
- Contexts.conversationContext.set( new BasicContext(ScopeType.CONVERSATION) );
+ Contexts.flushAndDestroyContexts();
}
-
- public static void beginExceptionRecovery(ExternalContext externalContext)
+ finally
{
- log.debug(">>> Begin exception recovery");
- Contexts.applicationContext.set( new ApplicationContext( externalContext.getApplicationMap() ) );
- Contexts.eventContext.set( new EventContext( externalContext.getRequestMap() ) );
- Contexts.sessionContext.set( new SessionContext( externalContext.getSessionMap() ) );
- Contexts.conversationContext.set( new ServerConversationContext( externalContext.getSessionMap() ) );
- Contexts.pageContext.set(null);
- Contexts.businessProcessContext.set(null); //TODO: is this really correct?
+ clearThreadlocals();
+ log.debug( "<<< End web request" );
+ }
}
- public static void endInitialization()
+ static void clearThreadlocals()
{
- startup(ScopeType.APPLICATION);
-
- Events.instance().raiseEvent("org.jboss.seam.postInitialization");
-
- // Clean up contexts used during initialization
- Contexts.destroy( Contexts.getConversationContext() );
- Contexts.conversationContext.set(null);
- Contexts.destroy( Contexts.getEventContext() );
Contexts.eventContext.set(null);
+ Contexts.pageContext.set(null);
Contexts.sessionContext.set(null);
+ Contexts.conversationContext.set(null);
+ Contexts.businessProcessContext.set(null);
Contexts.applicationContext.set(null);
-
- log.debug("<<< End initialization");
- }
-
- private static void startup(ScopeType scopeType)
- {
- // instantiate all components in the given scope
- Context context = Contexts.getApplicationContext();
- for ( String name: context.getNames() )
- {
- Object object = context.get(name);
- if ( object!=null && (object instanceof Component) )
- {
- Component component = (Component) object;
- if ( component.isStartup() && component.getScope()==scopeType )
- {
- startup(component);
- }
- }
- }
- }
-
- private static void startup(Component component)
- {
- if ( component.isStartup() )
- {
- for ( String dependency: component.getDependencies() )
- {
- Component dependentComponent = Component.forName(dependency);
- if (dependentComponent!=null)
- {
- startup(dependentComponent);
- }
- }
}
- if ( !component.getScope().getContext().isSet( component.getName() ) )
+ public static void destroyConversationContext(Map<String, Object> session, String conversationId)
{
- log.info( "starting up: " + component.getName() );
- component.newInstance();
- }
+ Contexts.destroyConversationContext(session, conversationId);
}
- public static void endApplication(ServletContext servletContext)
- {
- log.debug("Undeploying, destroying application context");
-
- Context tempApplicationContext = new ApplicationContext( new ServletApplicationMap(servletContext) );
- Contexts.applicationContext.set(tempApplicationContext);
- Contexts.destroy(tempApplicationContext);
- Contexts.applicationContext.set(null);
- Contexts.eventContext.set(null);
- Contexts.sessionContext.set(null);
- Contexts.conversationContext.set(null);
- }
-
- /***
- * Instantiate @Startup components for session scoped component
- */
- public static void beginSession(ServletContext servletContext, Map<String, Object> session)
+ public static void beginSession(Map<String, Object> session)
{
log.debug("Session started");
@@ -243,7 +175,7 @@
if ( !applicationContextActive )
{
- Context tempApplicationContext = new ApplicationContext( new ServletApplicationMap(servletContext) );
+ Context tempApplicationContext = new ApplicationContext( getApplication() );
Contexts.applicationContext.set(tempApplicationContext);
}
Context oldSessionContext = Contexts.sessionContext.get();
@@ -261,7 +193,7 @@
Contexts.conversationContext.set(tempConversationContext);
}
- startup(ScopeType.SESSION);
+ Contexts.startup(ScopeType.SESSION);
if ( !conversationContextActive )
{
@@ -281,7 +213,7 @@
}
- public static void endSession(ServletContext servletContext, Map<String, Object> session)
+ public static void endSession(Map<String, Object> session)
{
log.debug("End of session, destroying contexts");
@@ -294,7 +226,7 @@
throw new IllegalStateException("Please end the HttpSession via Seam.invalidateSession()");
}
- Context tempApplicationContext = new ApplicationContext( new ServletApplicationMap(servletContext) );
+ Context tempApplicationContext = new ApplicationContext( getApplication() );
Contexts.applicationContext.set(tempApplicationContext);
//this is used just as a place to stick the ConversationManager
@@ -310,7 +242,7 @@
log.debug("destroying conversation contexts: " + conversationIds);
for (String conversationId: conversationIds)
{
- destroyConversationContext(session, conversationId);
+ Contexts.destroyConversationContext(session, conversationId);
}
//we need some conversation-scope components for destroying
@@ -331,270 +263,4 @@
Contexts.applicationContext.set(null);
}
- public static void endRequest(ExternalContext externalContext)
- {
- log.debug("After render response, destroying contexts");
- try
- {
- ServletSession servletSession = ServletSession.getInstance();
- boolean sessionInvalid = servletSession!=null && servletSession.isInvalid();
-
- flushAndDestroyContexts();
-
- if (sessionInvalid)
- {
- clearThreadlocals();
- Lifecycle.setPhaseId(null);
- invalidateSession(externalContext);
- //actual session context will be destroyed from the listener
- }
- }
- finally
- {
- clearThreadlocals();
- log.debug( "<<< End JSF request" );
- }
- }
-
- /**
- * Invalidate the session, no matter what kind of session it is
- * (portlet or servlet). Why is this method not on ExternalContext?!
- * Oh boy, those crazy rascals in the JSF EG...
- */
- public static void invalidateSession(ExternalContext externalContext)
- {
- Object session = externalContext.getSession(false);
- if (session!=null)
- {
- try
- {
- session.getClass().getMethod("invalidate").invoke(session);
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
- }
- }
-
- public static void endRequest()
- {
- log.debug("After request, destroying contexts");
- try
- {
- flushAndDestroyContexts();
- }
- finally
- {
- clearThreadlocals();
- log.debug( "<<< End web request" );
- }
- }
-
- public static void endRequest(HttpServletRequest request)
- {
- log.debug("After request, destroying contexts");
- try
- {
- ServletSession servletSession = ServletSession.getInstance();
- boolean sessionInvalid = servletSession!=null && servletSession.isInvalid();
-
- flushAndDestroyContexts();
-
- if (sessionInvalid)
- {
- clearThreadlocals();
- request.getSession().invalidate();
- //actual session context will be destroyed from the listener
- }
- }
- finally
- {
- clearThreadlocals();
- log.debug( "<<< End web request" );
- }
- }
-
- private static void clearThreadlocals()
- {
- Contexts.eventContext.set(null);
- Contexts.pageContext.set(null);
- Contexts.sessionContext.set(null);
- Contexts.conversationContext.set(null);
- Contexts.businessProcessContext.set(null);
- Contexts.applicationContext.set(null);
- }
-
- private static void flushAndDestroyContexts()
- {
-
- if ( Contexts.isConversationContextActive() )
- {
-
- if ( Contexts.isBusinessProcessContextActive() )
- {
- boolean transactionActive = false;
- try
- {
- transactionActive = Transaction.instance().isActive();
- }
- catch (Exception e)
- {
- log.error("could not discover transaction status");
- }
- if (transactionActive)
- {
- //in calls to MDBs and remote calls to SBs, the
- //transaction doesn't commit until after contexts
- //are destroyed, so pre-emptively flush here:
- Contexts.getBusinessProcessContext().flush();
- }
-
- //TODO: it would be nice if BP context spanned redirects along with the conversation
- // this would also require changes to BusinessProcessContext
- boolean destroyBusinessProcessContext = !Init.instance().isJbpmInstalled() ||
- !BusinessProcess.instance().hasActiveProcess();
- if (destroyBusinessProcessContext)
- {
- //TODO: note that this occurs from Lifecycle.endRequest(), after
- // the Seam-managed txn was committed, but Contexts.destroy()
- // calls BusinessProcessContext.getNames(), which hits the
- // database!
- log.debug("destroying business process context");
- Contexts.destroy( Contexts.getBusinessProcessContext() );
- }
- }
-
- if ( !Manager.instance().isLongRunningConversation() )
- {
- log.debug("destroying conversation context");
- Contexts.destroy( Contexts.getConversationContext() );
- }
- if ( !Init.instance().isClientSideConversations() )
- {
- //note that we need to flush even if the session is
- //about to be invalidated, since we still need
- //to destroy the conversation context in endSession()
- log.debug("flushing server-side conversation context");
- Contexts.getConversationContext().flush();
- }
-
- //uses the event and session contexts
- if ( ServletSession.getInstance()!=null )
- {
- Manager.instance().unlockConversation();
- }
-
- }
-
- if ( Contexts.isSessionContextActive() )
- {
- log.debug("flushing session context");
- Contexts.getSessionContext().flush();
- }
-
- //destroy the event context after the
- //conversation context, since we need
- //the manager to flush() conversation
- if ( Contexts.isEventContextActive() )
- {
- log.debug("destroying event context");
- Contexts.destroy( Contexts.getEventContext() );
- }
-
- }
-
- public static void resumePage()
- {
- Contexts.pageContext.set( new PageContext() );
- }
-
- public static void resumeConversation(ExternalContext externalContext)
- {
- Init init = Init.instance();
- Context conversationContext = init.isClientSideConversations() ?
- (Context) new ClientConversationContext() :
- (Context) new ServerConversationContext( externalContext.getSessionMap() );
- Contexts.conversationContext.set( conversationContext );
- Contexts.businessProcessContext.set( new BusinessProcessContext() );
- }
-
- public static void resumeConversation(HttpServletRequest request)
- {
- Context conversationContext = new ServerConversationContext( new ServletRequestSessionMap(request) );
- Contexts.conversationContext.set( conversationContext );
- Contexts.businessProcessContext.set( new BusinessProcessContext() );
- }
-
- private static ThreadLocal phaseId = new ThreadLocal();
-
- public static Object getPhaseId()
- {
- return phaseId.get();
- }
-
- public static void setPhaseId(Object phase)
- {
- phaseId.set(phase);
- }
-
- private static ServletContext servletContext;
-
- public static ServletContext getServletContext()
- {
- if (servletContext==null)
- {
- throw new IllegalStateException("Attempted to invoke a Seam component outside the context of a web application");
- }
- return servletContext;
- }
-
- public static void setServletContext(ServletContext servletContext)
- {
- Lifecycle.servletContext = servletContext;
- }
-
- private static ThreadLocal<Boolean> destroying = new ThreadLocal<Boolean>();
-
- public static void startDestroying()
- {
- destroying.set(true);
- }
-
- public static void stopDestroying()
- {
- destroying.set(false);
- }
-
- public static boolean isDestroying()
- {
- Boolean value = destroying.get();
- return value!=null && value.booleanValue();
- }
-
- public static boolean isAttributeDirty(Object attribute)
- {
- return attribute instanceof Mutable && ( (Mutable) attribute ).clearDirty();
- }
-
- public static void destroyConversationContext(Map<String, Object> session, String conversationId)
- {
- ServerConversationContext conversationContext = new ServerConversationContext(session, conversationId);
- Context old = Contexts.getConversationContext();
- Contexts.conversationContext.set(conversationContext);
- try
- {
- Contexts.destroy(conversationContext);
- if ( !ServletSession.instance().isInvalid() ) //its also unnecessary during a session timeout
- {
- conversationContext.clear();
- conversationContext.flush();
- }
- }
- finally
- {
- Contexts.conversationContext.set(old);
- }
- }
-
}
1.17 +17 -4 jboss-seam/src/main/org/jboss/seam/contexts/PageContext.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: PageContext.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/src/main/org/jboss/seam/contexts/PageContext.java,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -b -r1.16 -r1.17
--- PageContext.java 19 Jun 2007 19:02:31 -0000 1.16
+++ PageContext.java 20 Jun 2007 08:23:17 -0000 1.17
@@ -7,6 +7,7 @@
package org.jboss.seam.contexts;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -73,9 +74,16 @@
private Map<String, Object> getCurrentReadableMap()
{
+ if ( !isInPhase() )
+ {
+ return Collections.EMPTY_MAP;
+ }
+ else
+ {
return isRenderResponsePhase() ?
nextPageMap : previousPageMap;
}
+ }
private Map<String, Object> getCurrentWritableMap()
{
@@ -148,12 +156,17 @@
private static PhaseId getPhaseId()
{
- Object phaseId = Lifecycle.getPhaseId();
+ PhaseId phaseId = FacesLifecycle.getPhaseId();
if (phaseId==null)
{
throw new IllegalStateException("No phase id bound to current thread (make sure you do not have two SeamPhaseListener instances installed)");
}
- return (PhaseId) phaseId;
+ return phaseId;
+ }
+
+ private static boolean isInPhase()
+ {
+ return FacesLifecycle.getPhaseId()!=null;
}
private static boolean isBeforeInvokeApplicationPhase()
1.29 +1 -1 jboss-seam/src/main/org/jboss/seam/contexts/ServerConversationContext.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: ServerConversationContext.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/src/main/org/jboss/seam/contexts/ServerConversationContext.java,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -b -r1.28 -r1.29
--- ServerConversationContext.java 17 Jun 2007 05:46:57 -0000 1.28
+++ ServerConversationContext.java 20 Jun 2007 08:23:17 -0000 1.29
@@ -239,7 +239,7 @@
{
String key = getKey(name);
Object attribute = session.get(key);
- if ( attribute!=null && Lifecycle.isAttributeDirty(attribute) )
+ if ( attribute!=null && Contexts.isAttributeDirty(attribute) )
{
session.put(key, attribute);
}
1.4 +1 -1 jboss-seam/src/main/org/jboss/seam/contexts/SessionContext.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: SessionContext.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/src/main/org/jboss/seam/contexts/SessionContext.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- SessionContext.java 20 Jun 2007 05:06:40 -0000 1.3
+++ SessionContext.java 20 Jun 2007 08:23:17 -0000 1.4
@@ -45,7 +45,7 @@
{
Object attribute = get(name);
boolean dirty = attribute!=null &&
- ( Lifecycle.isAttributeDirty(attribute) || Seam.isEntityClass( attribute.getClass() ) );
+ ( Contexts.isAttributeDirty(attribute) || Seam.isEntityClass( attribute.getClass() ) );
if ( dirty )
{
set(name, attribute);
1.1 date: 2007/06/20 08:23:17; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/contexts/FacesLifecycle.java
Index: FacesLifecycle.java
===================================================================
/*
* JBoss, Home of Professional Open Source
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.seam.contexts;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseId;
import org.jboss.seam.core.Init;
import org.jboss.seam.core.ServletSession;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
import org.jboss.seam.navigation.Pages;
/**
* @author Gavin King
* @author <a href="mailto:theute at jboss.org">Thomas Heute</a>
*/
public class FacesLifecycle
{
private static final LogProvider log = Logging.getLogProvider(FacesLifecycle.class);
public static void setPhaseId(PhaseId phase)
{
Lifecycle.setPhaseId(phase);
}
public static PhaseId getPhaseId()
{
return (PhaseId) Lifecycle.getPhaseId();
}
public static void clearPhaseId()
{
Lifecycle.setPhaseId(null);
}
public static void beginRequest(ExternalContext externalContext)
{
log.debug( ">>> Begin JSF request" );
Contexts.eventContext.set( new EventContext( externalContext.getRequestMap() ) );
Contexts.applicationContext.set( new ApplicationContext( externalContext.getApplicationMap() ) );
Contexts.sessionContext.set( new SessionContext( externalContext.getSessionMap() ) );
ServletSession servletSession = ServletSession.getInstance();
if ( servletSession!=null && servletSession.isInvalidDueToNewScheme( Pages.getRequestScheme( FacesContext.getCurrentInstance() ) ) )
{
invalidateSession(externalContext);
}
Contexts.conversationContext.set(null); //in case endRequest() was never called
//Events.instance(); //TODO: only for now, until we have a way to do EL outside of JSF!
}
public static void beginExceptionRecovery(ExternalContext externalContext)
{
log.debug(">>> Begin exception recovery");
Contexts.applicationContext.set( new ApplicationContext( externalContext.getApplicationMap() ) );
Contexts.eventContext.set( new EventContext( externalContext.getRequestMap() ) );
Contexts.sessionContext.set( new SessionContext( externalContext.getSessionMap() ) );
Contexts.conversationContext.set( new ServerConversationContext( externalContext.getSessionMap() ) );
Contexts.pageContext.set(null);
Contexts.businessProcessContext.set(null); //TODO: is this really correct?
}
public static void endRequest(ExternalContext externalContext)
{
log.debug("After render response, destroying contexts");
try
{
ServletSession servletSession = ServletSession.getInstance();
boolean sessionInvalid = servletSession!=null && servletSession.isInvalid();
Contexts.flushAndDestroyContexts();
if (sessionInvalid)
{
Lifecycle.clearThreadlocals();
Lifecycle.setPhaseId(null);
invalidateSession(externalContext);
//actual session context will be destroyed from the listener
}
}
finally
{
Lifecycle.clearThreadlocals();
log.debug( "<<< End JSF request" );
}
}
/**
* Invalidate the session, no matter what kind of session it is
* (portlet or servlet). Why is this method not on ExternalContext?!
* Oh boy, those crazy rascals in the JSF EG...
*/
public static void invalidateSession(ExternalContext externalContext)
{
Object session = externalContext.getSession(false);
if (session!=null)
{
try
{
session.getClass().getMethod("invalidate").invoke(session);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
}
public static void resumeConversation(ExternalContext externalContext)
{
Init init = Init.instance();
Context conversationContext = init.isClientSideConversations() ?
(Context) new ClientConversationContext() :
(Context) new ServerConversationContext( externalContext.getSessionMap() );
Contexts.conversationContext.set( conversationContext );
Contexts.businessProcessContext.set( new BusinessProcessContext() );
}
public static void resumePage()
{
Contexts.pageContext.set( new PageContext() );
}
}
1.1 date: 2007/06/20 08:23:17; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/contexts/ServletLifecycle.java
Index: ServletLifecycle.java
===================================================================
/*
* JBoss, Home of Professional Open Source
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.seam.contexts;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.jboss.seam.ScopeType;
import org.jboss.seam.core.Events;
import org.jboss.seam.core.ServletSession;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
import org.jboss.seam.servlet.ServletApplicationMap;
import org.jboss.seam.servlet.ServletRequestMap;
import org.jboss.seam.servlet.ServletRequestSessionMap;
import org.jboss.seam.servlet.ServletSessionMap;
/**
* @author Gavin King
* @author <a href="mailto:theute at jboss.org">Thomas Heute</a>
*/
public class ServletLifecycle
{
private static final LogProvider log = Logging.getLogProvider(ServletLifecycle.class);
private static ServletContext servletContext;
public static ServletContext getServletContext()
{
if (servletContext==null)
{
throw new IllegalStateException("Attempted to invoke a Seam component outside the context of a web application");
}
return servletContext;
}
public static void beginRequest(HttpServletRequest request)
{
log.debug( ">>> Begin web request" );
Contexts.eventContext.set( new EventContext( new ServletRequestMap(request) ) );
Contexts.sessionContext.set( new SessionContext( new ServletRequestSessionMap(request) ) );
Contexts.applicationContext.set(new ApplicationContext( Lifecycle.getApplication() ) );
Contexts.conversationContext.set(null); //in case endRequest() was never called
}
public static void endRequest(HttpServletRequest request)
{
log.debug("After request, destroying contexts");
try
{
ServletSession servletSession = ServletSession.getInstance();
boolean sessionInvalid = servletSession!=null && servletSession.isInvalid();
Contexts.flushAndDestroyContexts();
if (sessionInvalid)
{
Lifecycle.clearThreadlocals();
request.getSession().invalidate();
//actual session context will be destroyed from the listener
}
}
finally
{
Lifecycle.clearThreadlocals();
log.debug( "<<< End web request" );
}
}
public static void beginInitialization()
{
log.debug(">>> Begin initialization");
Contexts.applicationContext.set( new ApplicationContext( Lifecycle.getApplication() ) );
Contexts.eventContext.set( new BasicContext(ScopeType.EVENT) );
Contexts.conversationContext.set( new BasicContext(ScopeType.CONVERSATION) );
}
public static void beginReinitialization(HttpServletRequest request)
{
log.debug(">>> Begin re-initialization");
Contexts.applicationContext.set( new ApplicationContext( Lifecycle.getApplication() ) );
Contexts.eventContext.set( new BasicContext(ScopeType.EVENT) );
Contexts.sessionContext.set( new SessionContext( new ServletRequestSessionMap(request) ) );
Contexts.conversationContext.set( new BasicContext(ScopeType.CONVERSATION) );
}
public static void endInitialization()
{
Contexts.startup(ScopeType.APPLICATION);
Events.instance().raiseEvent("org.jboss.seam.postInitialization");
// Clean up contexts used during initialization
Contexts.destroy( Contexts.getConversationContext() );
Contexts.conversationContext.set(null);
Contexts.destroy( Contexts.getEventContext() );
Contexts.eventContext.set(null);
Contexts.sessionContext.set(null);
Contexts.applicationContext.set(null);
log.debug("<<< End initialization");
}
public static void beginApplication(ServletContext context)
{
servletContext = context;
Lifecycle.beginApplication( new ServletApplicationMap(context) );
}
public static void endApplication()
{
Lifecycle.endApplication();
servletContext=null;
}
public static void beginSession(HttpSession session)
{
Lifecycle.beginSession( new ServletSessionMap(session) );
}
public static void endSession(HttpSession session)
{
Lifecycle.endSession( new ServletSessionMap(session) );
}
public static void resumeConversation(HttpServletRequest request)
{
Context conversationContext = new ServerConversationContext( new ServletRequestSessionMap(request) );
Contexts.conversationContext.set( conversationContext );
Contexts.businessProcessContext.set( new BusinessProcessContext() );
}
}
1.1 date: 2007/06/20 08:23:17; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/contexts/TestLifecycle.java
Index: TestLifecycle.java
===================================================================
/*
* JBoss, Home of Professional Open Source
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.seam.contexts;
import java.util.Map;
import javax.servlet.ServletContext;
import org.jboss.seam.ScopeType;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
import org.jboss.seam.servlet.ServletApplicationMap;
/**
* @author Gavin King
*/
public class TestLifecycle
{
private static final LogProvider log = Logging.getLogProvider(TestLifecycle.class);
public static void beginTest(ServletContext context, Map<String, Object> session)
{
log.debug( ">>> Begin test" );
Contexts.eventContext.set( new BasicContext(ScopeType.EVENT) );
Contexts.conversationContext.set( new BasicContext(ScopeType.CONVERSATION) );
Contexts.businessProcessContext.set( new BusinessProcessContext() );
Contexts.sessionContext.set( new SessionContext(session) );
Contexts.applicationContext.set( new ApplicationContext( new ServletApplicationMap(context) ) );
}
public static void endTest()
{
Lifecycle.clearThreadlocals();
log.debug( "<<< End test" );
}
}
More information about the jboss-cvs-commits
mailing list