You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beehive.apache.org by ri...@apache.org on 2005/05/21 08:23:23 UTC

svn commit: r171199 [1/2] - in /incubator/beehive/branches/rich-vnext/netui: src/pageflow/org/apache/beehive/netui/pageflow/ src/pageflow/org/apache/beehive/netui/pageflow/handler/ src/pageflow/org/apache/beehive/netui/pageflow/internal/ src/util/schema/netui-config/ test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/ test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/ test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/nested/ test/webapps/drt/testRecorder/config/ test/webapps/drt/testRecorder/tests/

Author: rich
Date: Fri May 20 23:23:22 2005
New Revision: 171199

URL: http://svn.apache.org/viewcvs?rev=171199&view=rev
Log:
Fix for http://issues.apache.org/jira/browse/BEEHIVE-756 : Major badness when moving between page flows in the same request, with multiple concurrent requests

tests: bvt in netui (WinXP) (CtBindingReport fails because of the fix for http://issues.apache.org/jira/browse/BEEHIVE-750)


Added:
    incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/StorageHandler.java   (with props)
    incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DeferredSessionStorageHandler.java   (with props)
    incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/SimpleSessionStorageHandler.java   (with props)
    incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/
    incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/
    incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/Controller.jpf   (with props)
    incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/index.jsp   (with props)
    incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/success.jsp   (with props)
    incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/index.jsp   (with props)
    incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/nested/
    incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/nested/Controller.jpf   (with props)
    incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/testRecorder/tests/NestReturnSingleRequest.xml   (with props)
Modified:
    incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/AutoRegisterActionServlet.java
    incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/FacesBackingBean.java
    incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java
    incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowController.java
    incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowManagedObject.java
    incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java
    incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java
    incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowStack.java
    incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowUtils.java
    incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/SharedFlowController.java
    incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/StrutsModuleFactory.java
    incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/Handlers.java
    incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DefaultActionForwardHandler.java
    incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/FacesBackingBeanFactory.java
    incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/InternalUtils.java
    incubator/beehive/branches/rich-vnext/netui/src/util/schema/netui-config/netui-config.xsd
    incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/testRecorder/config/testRecorder-tests.xml

Modified: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/AutoRegisterActionServlet.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/AutoRegisterActionServlet.java?rev=171199&r1=171198&r2=171199&view=diff
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/AutoRegisterActionServlet.java (original)
+++ incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/AutoRegisterActionServlet.java Fri May 20 23:23:22 2005
@@ -622,6 +622,12 @@
             }
             else
             {
+                //
+                // Initialize the ServletContext in the request.  Often, we need access to the ServletContext when we only
+                // have a ServletRequest.
+                //
+                InternalUtils.setServletContext( request, getServletContext() );
+                
                 if ( processUnhandledAction( request, response, servletPath ) ) return;
                 
                 String originalServletPath = requestWrapper.getOriginalServletPath();

Modified: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/FacesBackingBean.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/FacesBackingBean.java?rev=171199&r1=171198&r2=171199&view=diff
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/FacesBackingBean.java (original)
+++ incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/FacesBackingBean.java Fri May 20 23:23:22 2005
@@ -23,6 +23,8 @@
 import org.apache.beehive.netui.pageflow.internal.AdapterManager;
 import org.apache.beehive.netui.pageflow.internal.CachedSharedFlowRefInfo;
 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
+import org.apache.beehive.netui.pageflow.handler.Handlers;
+import org.apache.beehive.netui.pageflow.handler.StorageHandler;
 import org.apache.beehive.netui.util.internal.cache.ClassLevelCache;
 import org.apache.beehive.netui.util.logging.Logger;
 
@@ -62,8 +64,13 @@
      */ 
     public void persistInSession( HttpServletRequest request, HttpServletResponse response )
     {
+        StorageHandler sh = Handlers.get( getServletContext() ).getStorageHandler();
         HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
-        ScopedServletUtils.setScopedSessionAttr( InternalConstants.FACES_BACKING_ATTR, this, unwrappedRequest );
+        RequestContext rc = new RequestContext( unwrappedRequest, null );
+        String attrName =
+                ScopedServletUtils.getScopedSessionAttrName( InternalConstants.FACES_BACKING_ATTR, unwrappedRequest );
+        
+        sh.setAttribute( rc, attrName, this );
     }
 
     /**
@@ -71,8 +78,13 @@
      */ 
     protected void removeFromSession( HttpServletRequest request )
     {
+        StorageHandler sh = Handlers.get( getServletContext() ).getStorageHandler();
         HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
-        ScopedServletUtils.removeScopedSessionAttr( InternalConstants.FACES_BACKING_ATTR, unwrappedRequest );
+        RequestContext rc = new RequestContext( unwrappedRequest, null );
+        String attrName =
+                ScopedServletUtils.getScopedSessionAttrName( InternalConstants.FACES_BACKING_ATTR, unwrappedRequest );
+        
+        sh.removeAttribute( rc, attrName );
     }
 
     /**
@@ -85,11 +97,13 @@
      */ 
     public void ensureFailover( HttpServletRequest request )
     {
+        ServletContext servletContext = InternalUtils.getServletContext( request );
+        StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
         HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
+        RequestContext rc = new RequestContext( unwrappedRequest, null );
         String attr =
                 ScopedServletUtils.getScopedSessionAttrName( InternalConstants.FACES_BACKING_ATTR, unwrappedRequest );
-        ServletContext servletContext = InternalUtils.getServletContext( request );
-        AdapterManager.getServletContainerAdapter( servletContext ).ensureFailover( attr, this, unwrappedRequest );
+        sh.ensureFailover( rc, attr, this );
     }
 
     /**

Modified: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java?rev=171199&r1=171198&r2=171199&view=diff
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java (original)
+++ incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java Fri May 20 23:23:22 2005
@@ -552,7 +552,7 @@
         
         //
         // We may have lost our transient ServletContext reference.  Try to get the ServletContext reference from the
-        // HttpSession object.
+        // HttpSession object if necessary.
         //
         ServletContext servletContext = getServletContext();
         if ( servletContext == null && session != null ) servletContext = session.getServletContext();

Modified: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowController.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowController.java?rev=171199&r1=171198&r2=171199&view=diff
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowController.java (original)
+++ incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowController.java Fri May 20 23:23:22 2005
@@ -44,6 +44,8 @@
 import org.apache.beehive.netui.pageflow.internal.ViewRenderer;
 import org.apache.beehive.netui.pageflow.internal.PageFlowRequestWrapper;
 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
+import org.apache.beehive.netui.pageflow.handler.StorageHandler;
+import org.apache.beehive.netui.pageflow.handler.Handlers;
 
 
 /**
@@ -192,7 +194,7 @@
         }
         else
         {
-            InternalUtils.removeCurrentPageFlow( request );
+            InternalUtils.removeCurrentPageFlow( request, getServletContext() );
         }
     }
     
@@ -222,12 +224,12 @@
             //
             synchronized ( currentPageFlow )
             {
-                InternalUtils.setCurrentPageFlow( this, request );
+                InternalUtils.setCurrentPageFlow( this, request, getServletContext() );
             }
         }
         else
         {
-            InternalUtils.setCurrentPageFlow( this, request );
+            InternalUtils.setCurrentPageFlow( this, request, getServletContext() );
         }
     }
 
@@ -248,8 +250,9 @@
         //
         if ( request.getAttribute( REMOVING_PAGEFLOW_ATTR ) != this && request.getSession( false ) != null )
         {
+            StorageHandler sh = Handlers.get( getServletContext() ).getStorageHandler();
             HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
-            ServletContainerAdapter servletContainerAdapter = AdapterManager.getServletContainerAdapter( getServletContext() );
+            RequestContext rc = new RequestContext( unwrappedRequest, null );
         
             //
             // If this is a long-lived page flow, there are two attributes to deal with.
@@ -260,13 +263,13 @@
                 longLivedAttrName = ScopedServletUtils.getScopedSessionAttrName( longLivedAttrName, unwrappedRequest );
                 String currentLongLivedAttrName =
                     ScopedServletUtils.getScopedSessionAttrName( CURRENT_LONGLIVED_ATTR, unwrappedRequest );
-                servletContainerAdapter.ensureFailover( longLivedAttrName, this, unwrappedRequest );
-                servletContainerAdapter.ensureFailover( currentLongLivedAttrName, getModulePath(), unwrappedRequest );
+                sh.ensureFailover( rc, longLivedAttrName, this );
+                sh.ensureFailover( rc, currentLongLivedAttrName, getModulePath() );
             }
             else
             {
                 String attrName = ScopedServletUtils.getScopedSessionAttrName( CURRENT_JPF_ATTR, unwrappedRequest );
-                servletContainerAdapter.ensureFailover( attrName, this, unwrappedRequest );
+                sh.ensureFailover( rc, attrName, this );
             } 
         }
     }
@@ -880,7 +883,7 @@
         //
         if ( ! _isOnNestingStack )
         {
-            destroy( event.getSession() );
+            super.valueUnbound( event );
         }
     }
     

Modified: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowManagedObject.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowManagedObject.java?rev=171199&r1=171198&r2=171199&view=diff
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowManagedObject.java (original)
+++ incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowManagedObject.java Fri May 20 23:23:22 2005
@@ -18,6 +18,7 @@
 package org.apache.beehive.netui.pageflow;
 
 import org.apache.beehive.netui.pageflow.internal.JavaControlUtils;
+import org.apache.beehive.netui.pageflow.handler.Handlers;
 import org.apache.beehive.netui.util.logging.Logger;
 
 import javax.servlet.http.HttpSessionBindingListener;
@@ -41,7 +42,7 @@
      * Reference to the current ServletContext.
      */ 
     private transient ServletContext _servletContext;
-
+    
     
     /**
      * Reinitialize the object for a new request.  Used by the framework; normally should not be called directly.
@@ -87,7 +88,7 @@
      */ 
     protected void onDestroy( HttpSession session )
     {
-    } 
+    }
     
     /**
      * Callback when this object is added to the user session.
@@ -102,9 +103,27 @@
      */ 
     public void valueUnbound( HttpSessionBindingEvent event )
     {
-        destroy( event.getSession() );
+        //
+        // We may have lost our transient ServletContext reference.  Try to get the ServletContext reference from the
+        // HttpSession object if necessary.
+        //
+        ServletContext servletContext = getServletContext();
+        HttpSession session = event.getSession();
+        
+        if ( servletContext == null && session != null )
+        {
+            servletContext = session.getServletContext();
+        }
+        
+        if ( servletContext != null )
+        {
+            if ( Handlers.get( servletContext ).getStorageHandler().allowBindingEvent( event ) )
+            {
+                destroy( session );
+            }
+        }
     }
-
+    
     /**
      * Remove this instance from the session.
      */ 

Modified: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java?rev=171199&r1=171198&r2=171199&view=diff
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java (original)
+++ incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java Fri May 20 23:23:22 2005
@@ -49,6 +49,7 @@
 import org.apache.beehive.netui.pageflow.internal.InternalConstants;
 import org.apache.beehive.netui.pageflow.internal.AdapterManager;
 import org.apache.beehive.netui.pageflow.internal.PageFlowRequestWrapper;
+import org.apache.beehive.netui.pageflow.internal.DeferredSessionStorageHandler;
 import org.apache.beehive.netui.script.common.ImplicitObjectUtil;
 
 
@@ -163,6 +164,9 @@
             //
             URLRewriterService.registerURLRewriter( 0, request, new DefaultURLRewriter() );
 
+            PageFlowRequestWrapper rw = PageFlowRequestWrapper.unwrap( request );
+            boolean isForwardedRequest = rw != null && rw.isForwardedRequest();
+            
             try
             {
                 ModuleConfig prevModuleConfig = RequestUtils.getRequestModuleConfig( httpRequest );
@@ -230,6 +234,15 @@
                 _servletContainerAdapter.endRequest( httpRequest, httpResponse );
                 long timeTaken = System.currentTimeMillis() - startTime;
                 er.endPageRequest( httpRequest, httpResponse, timeTaken );
+                
+                //
+                // If this is not a forwarded request, then commit any session-scoped changes that were stored in the
+                // request.
+                //
+                if ( ! isForwardedRequest )
+                {
+                    DeferredSessionStorageHandler.applyChanges( httpRequest, _servletContext );
+                }
             }
         }
         else

Modified: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java?rev=171199&r1=171198&r2=171199&view=diff
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java (original)
+++ incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java Fri May 20 23:23:22 2005
@@ -43,6 +43,7 @@
 import org.apache.beehive.netui.pageflow.internal.LegacySettings;
 import org.apache.beehive.netui.pageflow.internal.PageFlowRequestWrapper;
 import org.apache.beehive.netui.pageflow.internal.InternalConstants;
+import org.apache.beehive.netui.pageflow.internal.DeferredSessionStorageHandler;
 import org.apache.beehive.netui.pageflow.scoping.ScopedRequest;
 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
 import org.apache.beehive.netui.script.common.ImplicitObjectUtil;
@@ -89,15 +90,8 @@
 import java.lang.reflect.Field;
 import java.net.URI;
 import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
+import java.util.*;
+
 import org.apache.beehive.netui.util.internal.concurrent.InternalConcurrentHashMap;
 
 
@@ -110,7 +104,7 @@
         extends TilesRequestProcessor
         implements Serializable, InternalConstants, PageFlowConstants
 {
-    private static int requestCount = 0;
+    private static int requestNumber = 0;
 
     private static final Logger _log = Logger.getInstance( PageFlowRequestProcessor.class );
     
@@ -122,7 +116,7 @@
     private static final String REDIRECT_REQUEST_ATTRS_PARAM = "forceRedirect";
     private static final String FLOW_CONTROLLER_ACTION_CLASSNAME = FlowControllerAction.class.getName();
     private static final NullActionForm NULL_ACTION_FORM = new NullActionForm();
-
+    
     
     private Map/*< String, Class >*/ _formBeanClasses = new HashMap/*< String, Class >*/();
     private Map/*< String, List< ActionMapping > >*/ _overloadedActions = new HashMap/*< String, List< ActionMapping > >*/();
@@ -386,7 +380,7 @@
             // no databinding errors when the override action does not use a form bean.
             //
             if ( form == null && requestWrapper.isForwardedByButton() ) form = NULL_ACTION_FORM;
-
+            
             ProcessPopulate.populate( request, response, form, alreadyCalledInRequest );
         }
     }
@@ -799,7 +793,7 @@
 
         if ( _log.isTraceEnabled() )
         {
-            localRequestCount = ++requestCount;
+            localRequestCount = ++requestNumber;
             _log.trace( "------------------------------- Start Request #" + localRequestCount
                        + " -----------------------------------" );
         }
@@ -858,6 +852,9 @@
         // Register the default URLRewriter
         //
         URLRewriterService.registerURLRewriter( 0, request, new DefaultURLRewriter() );
+        
+        PageFlowRequestWrapper rw = PageFlowRequestWrapper.unwrap( request );
+        boolean isForwardedRequest = rw != null && rw.isForwardedRequest();
 
         try
         {
@@ -865,6 +862,15 @@
         }
         finally
         {
+            //
+            // If this is not a forwarded request, then commit any session-scoped changes that were stored in the
+            // request.
+            //
+            if ( ! isForwardedRequest )
+            {
+                DeferredSessionStorageHandler.applyChanges( request, servletContext );
+            }
+            
             //
             // Clean up the ControlBeanContext in the session.
             //

Modified: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowStack.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowStack.java?rev=171199&r1=171198&r2=171199&view=diff
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowStack.java (original)
+++ incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowStack.java Fri May 20 23:23:22 2005
@@ -25,6 +25,8 @@
 import org.apache.beehive.netui.pageflow.interceptor.action.InterceptorForward;
 import org.apache.beehive.netui.pageflow.interceptor.action.ActionInterceptor;
 import org.apache.beehive.netui.pageflow.interceptor.action.ActionInterceptorContext;
+import org.apache.beehive.netui.pageflow.handler.Handlers;
+import org.apache.beehive.netui.pageflow.handler.StorageHandler;
 
 import javax.servlet.http.HttpSessionBindingListener;
 import javax.servlet.http.HttpSessionBindingEvent;
@@ -113,9 +115,12 @@
      */    
     public static PageFlowStack get( HttpServletRequest request, boolean createIfNotExist )
     {
-        PageFlowStack jpfStack =
-                ( PageFlowStack ) ScopedServletUtils.getScopedSessionAttr( JPF_STACK_ATTR,
-                                                                           PageFlowUtils.unwrapMultipart( request ) );
+        ServletContext servletContext = InternalUtils.getServletContext( request );
+        StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
+        HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
+        RequestContext rc = new RequestContext( unwrappedRequest, null );
+        String attrName = ScopedServletUtils.getScopedSessionAttrName( JPF_STACK_ATTR, unwrappedRequest );
+        PageFlowStack jpfStack = ( PageFlowStack ) sh.getAttribute( rc, attrName );
 
         if ( jpfStack == null && createIfNotExist )
         {
@@ -133,7 +138,13 @@
      */ 
     public static void destroy( HttpServletRequest request )
     {
-        ScopedServletUtils.removeScopedSessionAttr( JPF_STACK_ATTR, PageFlowUtils.unwrapMultipart( request ) );
+        ServletContext servletContext = InternalUtils.getServletContext( request );
+        StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
+        HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
+        RequestContext rc = new RequestContext( unwrappedRequest, null );
+        String attrName = ScopedServletUtils.getScopedSessionAttrName( JPF_STACK_ATTR, unwrappedRequest );
+        
+        sh.removeAttribute( rc, attrName );
     }
     
     /**
@@ -161,7 +172,7 @@
                 //
                 // We're discarding the popped page flow.  Invoke its destroy() callback, unless it's longLived.
                 //
-                if ( ! popped.isLongLived() ) popped.destroy( request.getSession() );
+                if ( ! popped.isLongLived() ) popped.destroy( request.getSession( false ) );
             }
         }
 
@@ -198,14 +209,23 @@
     
     void ensureFailover( HttpServletRequest request, ServletContext servletContext )
     {
-        String name =
-            ScopedServletUtils.getScopedSessionAttrName( JPF_STACK_ATTR, PageFlowUtils.unwrapMultipart( request ) );
-        AdapterManager.getServletContainerAdapter( servletContext ).ensureFailover( name, this, request );
+        StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
+        HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
+        RequestContext rc = new RequestContext( unwrappedRequest, null );
+        String attrName = ScopedServletUtils.getScopedSessionAttrName( JPF_STACK_ATTR, unwrappedRequest );
+        
+        sh.ensureFailover( rc, attrName, this );
     }
     
     void save( HttpServletRequest request )
     {
-        ScopedServletUtils.setScopedSessionAttr( JPF_STACK_ATTR, this, PageFlowUtils.unwrapMultipart( request ) );
+        ServletContext servletContext = InternalUtils.getServletContext( request );
+        StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
+        HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
+        RequestContext rc = new RequestContext( unwrappedRequest, null );
+        String attrName = ScopedServletUtils.getScopedSessionAttrName( JPF_STACK_ATTR, unwrappedRequest );
+        
+        sh.setAttribute( rc, attrName, this );
     }
     
     PageFlowStack()

Modified: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowUtils.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowUtils.java?rev=171199&r1=171198&r2=171199&view=diff
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowUtils.java (original)
+++ incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowUtils.java Fri May 20 23:23:22 2005
@@ -31,9 +31,12 @@
 import org.apache.beehive.netui.pageflow.internal.AdapterManager;
 import org.apache.beehive.netui.pageflow.internal.PageFlowRequestWrapper;
 import org.apache.beehive.netui.pageflow.internal.URIContextFactory;
+import org.apache.beehive.netui.pageflow.internal.DeferredSessionStorageHandler;
 import org.apache.beehive.netui.pageflow.scoping.ScopedRequest;
 import org.apache.beehive.netui.pageflow.scoping.ScopedResponse;
 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
+import org.apache.beehive.netui.pageflow.handler.StorageHandler;
+import org.apache.beehive.netui.pageflow.handler.Handlers;
 import org.apache.beehive.netui.util.internal.FileUtils;
 import org.apache.beehive.netui.util.internal.ServletUtils;
 import org.apache.beehive.netui.util.config.ConfigUtil;
@@ -244,24 +247,28 @@
      */ 
     public static ActionResolver getCurrentActionResolver( HttpServletRequest request )
     {
+        ServletContext servletContext = InternalUtils.getServletContext( request );
+        StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
+        HttpServletRequest unwrappedRequest = unwrapMultipart( request );
+        RequestContext rc = new RequestContext( unwrappedRequest, null );
+        
         //
         // First see if the current page flow is a long-lived, which is stored in its own attribute.
         //
-        HttpServletRequest unwrappedRequest = unwrapMultipart( request );
-        String currentLongLivedModulePath =
-                ( String ) ScopedServletUtils.getScopedSessionAttr( CURRENT_LONGLIVED_ATTR, unwrappedRequest );
+        String currentLongLivedAttrName =
+                ScopedServletUtils.getScopedSessionAttrName( CURRENT_LONGLIVED_ATTR, unwrappedRequest );
+        String currentLongLivedModulePath = ( String ) sh.getAttribute( rc, currentLongLivedAttrName );
         ActionResolver retVal;
         
         if ( currentLongLivedModulePath != null )
         {
-            retVal = getLongLivedPageFlow( currentLongLivedModulePath, unwrappedRequest );
+            return getLongLivedPageFlow( currentLongLivedModulePath, unwrappedRequest );
         }
         else
         {
-            retVal = ( ActionResolver ) ScopedServletUtils.getScopedSessionAttr( CURRENT_JPF_ATTR, unwrappedRequest );
+            String currentJpfAttrName = ScopedServletUtils.getScopedSessionAttrName( CURRENT_JPF_ATTR, unwrappedRequest );
+            return ( ActionResolver ) sh.getAttribute( rc, currentJpfAttrName );
         }
-        
-        return retVal;
     }
     
     /**
@@ -302,14 +309,12 @@
      */ 
     public static SharedFlowController getSharedFlow( String sharedFlowClassName, HttpServletRequest request )
     {
-        HttpSession session = request.getSession( false );
-        
-        if ( session != null )
-        {
-            return ( SharedFlowController ) session.getAttribute( SHARED_FLOW_ATTR_PREFIX + sharedFlowClassName );
-        }
+        ServletContext servletContext = InternalUtils.getServletContext( request );
+        StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
+        HttpServletRequest unwrappedRequest = unwrapMultipart( request );
+        RequestContext rc = new RequestContext( unwrappedRequest, null );
         
-        return null;
+        return ( SharedFlowController ) sh.getAttribute( rc, SHARED_FLOW_ATTR_PREFIX + sharedFlowClassName );
     }
     
     /**
@@ -319,8 +324,11 @@
      */ 
     public static void removeSharedFlow( String sharedFlowClassName, HttpServletRequest request )
     {
-        HttpSession session = request.getSession( false );
-        if ( session != null ) request.getSession().removeAttribute( SHARED_FLOW_ATTR_PREFIX + sharedFlowClassName );
+        ServletContext servletContext = InternalUtils.getServletContext( request );
+        StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
+        HttpServletRequest unwrappedRequest = unwrapMultipart( request );
+        RequestContext rc = new RequestContext( unwrappedRequest, null );
+        sh.removeAttribute( rc, SHARED_FLOW_ATTR_PREFIX + sharedFlowClassName );
     }
     
     
@@ -332,19 +340,26 @@
      */
     public static void removeLongLivedPageFlow( String modulePath, HttpServletRequest request )
     {
+        ServletContext servletContext = InternalUtils.getServletContext( request );
+        StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
         HttpServletRequest unwrappedRequest = unwrapMultipart( request );
+        RequestContext rc = new RequestContext( unwrappedRequest, null );
+        
         String attrName = InternalUtils.getLongLivedFlowAttr( modulePath );
-        ScopedServletUtils.removeScopedSessionAttr( attrName, unwrappedRequest );
+        attrName = ScopedServletUtils.getScopedSessionAttrName( attrName, unwrappedRequest );
+        sh.removeAttribute( rc, attrName );
 
         //
         // Now, if the current page flow is long-lived, remove the reference.
         //
+        String currentLongLivedAttrName =
+                ScopedServletUtils.getScopedSessionAttrName( CURRENT_LONGLIVED_ATTR, unwrappedRequest );
         String currentLongLivedModulePath =
-                ( String ) ScopedServletUtils.getScopedSessionAttr( CURRENT_LONGLIVED_ATTR, unwrappedRequest );
+                ( String ) sh.getAttribute( rc, currentLongLivedAttrName );
         
         if ( modulePath.equals( currentLongLivedModulePath ) )
         {
-            ScopedServletUtils.removeScopedSessionAttr( CURRENT_LONGLIVED_ATTR, unwrappedRequest );
+            sh.removeAttribute( rc, currentLongLivedAttrName );
         }
     }
     
@@ -357,9 +372,14 @@
      */ 
     public static PageFlowController getLongLivedPageFlow( String modulePath, HttpServletRequest request )
     {
-        String attr = InternalUtils.getLongLivedFlowAttr( modulePath );
-        PageFlowController retVal =  ( PageFlowController )
-                ScopedServletUtils.getScopedSessionAttr( attr, unwrapMultipart( request ) );
+        ServletContext servletContext = InternalUtils.getServletContext( request );
+        StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
+        HttpServletRequest unwrappedRequest = unwrapMultipart( request );
+        RequestContext rc = new RequestContext( unwrappedRequest, null );
+        
+        String attrName = InternalUtils.getLongLivedFlowAttr( modulePath );
+        attrName = ScopedServletUtils.getScopedSessionAttrName( attrName, unwrappedRequest );
+        PageFlowController retVal =  ( PageFlowController ) sh.getAttribute( rc, attrName );
         return retVal;
     }
     
@@ -1031,6 +1051,8 @@
             returnURI = scopedResponse.getRedirectURI();
         }
         
+        DeferredSessionStorageHandler.applyChanges( scopedRequest, context );
+        
         if ( returnURI != null )
         {
             return new ActionResultImpl( returnURI, scopedResponse.didRedirect(), scopedResponse.getStatusCode(),
@@ -1258,7 +1280,8 @@
      */ 
     public static void setCurrentActionResolver( ActionResolver resolver, HttpServletRequest request )
     {
-        InternalUtils.setCurrentActionResolver( resolver, request );
+        ServletContext servletContext = InternalUtils.getServletContext( request ); 
+        InternalUtils.setCurrentActionResolver( resolver, request, servletContext );
     }
 
     /**

Modified: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/SharedFlowController.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/SharedFlowController.java?rev=171199&r1=171198&r2=171199&view=diff
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/SharedFlowController.java (original)
+++ incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/SharedFlowController.java Fri May 20 23:23:22 2005
@@ -28,6 +28,10 @@
 
 import org.apache.beehive.netui.pageflow.internal.AdapterManager;
 import org.apache.beehive.netui.pageflow.internal.InternalConstants;
+import org.apache.beehive.netui.pageflow.internal.InternalUtils;
+import org.apache.beehive.netui.pageflow.handler.Handlers;
+import org.apache.beehive.netui.pageflow.handler.StorageHandler;
+import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
 
 
 /**
@@ -114,7 +118,11 @@
      */ 
     public void persistInSession( HttpServletRequest request, HttpServletResponse response )
     {
-        request.getSession().setAttribute( InternalConstants.SHARED_FLOW_ATTR_PREFIX + getClass().getName(), this );
+        ServletContext servletContext = InternalUtils.getServletContext( request );
+        StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
+        HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
+        RequestContext rc = new RequestContext( unwrappedRequest, null );
+        sh.setAttribute( rc, InternalConstants.SHARED_FLOW_ATTR_PREFIX + getClass().getName(), this );
     }
     
     /**
@@ -127,8 +135,10 @@
      */ 
     public void ensureFailover( HttpServletRequest request )
     {
-        ServletContainerAdapter servletContainerAdapter = AdapterManager.getServletContainerAdapter( getServletContext() );
-        servletContainerAdapter.ensureFailover( InternalConstants.SHARED_FLOW_ATTR_PREFIX + getClass().getName(), this, request );
+        StorageHandler sh = Handlers.get( getServletContext() ).getStorageHandler();
+        HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
+        RequestContext rc = new RequestContext( unwrappedRequest, null );
+        sh.ensureFailover( rc, InternalConstants.SHARED_FLOW_ATTR_PREFIX + getClass().getName(), this );
     }
     
     /**

Modified: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/StrutsModuleFactory.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/StrutsModuleFactory.java?rev=171199&r1=171198&r2=171199&view=diff
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/StrutsModuleFactory.java (original)
+++ incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/StrutsModuleFactory.java Fri May 20 23:23:22 2005
@@ -27,11 +27,10 @@
  */ 
 public class StrutsModuleFactory
 {
-    public static ActionResolver getStrutsModule( String strutsModulePath,
-                                                  HttpServletRequest request )
+    public static ActionResolver getStrutsModule( String strutsModulePath, HttpServletRequest request )
     {
         ActionResolver strutsModule = new StrutsModule( strutsModulePath );
-        InternalUtils.setCurrentActionResolver( strutsModule, request );
+        InternalUtils.setCurrentActionResolver( strutsModule, request, InternalUtils.getServletContext( request ) );
         return strutsModule;
     }
 }

Modified: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/Handlers.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/Handlers.java?rev=171199&r1=171198&r2=171199&view=diff
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/Handlers.java (original)
+++ incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/Handlers.java Fri May 20 23:23:22 2005
@@ -30,6 +30,8 @@
 import org.apache.beehive.netui.pageflow.internal.DefaultExceptionsHandler;
 import org.apache.beehive.netui.pageflow.internal.DefaultActionForwardHandler;
 import org.apache.beehive.netui.pageflow.internal.DefaultHandler;
+import org.apache.beehive.netui.pageflow.internal.SimpleSessionStorageHandler;
+import org.apache.beehive.netui.pageflow.internal.DeferredSessionStorageHandler;
 import org.apache.beehive.netui.pageflow.PageFlowActionServlet;
 import org.apache.beehive.netui.pageflow.PageFlowContextListener;
 
@@ -50,6 +52,7 @@
     private ExceptionsHandler _exceptionsHandler = null;
     private ForwardRedirectHandler _forwardRedirectHandler = null;
     private LoginHandler _loginHandler = null;
+    private StorageHandler _storageHandler = null;
     private ReloadableClassHandler _reloadableClassHandler = null;
     private transient ServletContext _servletContext;
     
@@ -99,6 +102,7 @@
         DefaultHandler defaultExceptionsHandler = new DefaultExceptionsHandler( servletContext );
         DefaultHandler defaultForwardRedirectHandler = new DefaultForwardRedirectHandler( servletContext );
         DefaultHandler defaultLoginHandler = new DefaultLoginHandler( servletContext );
+        DefaultHandler defaultStorageHandler = new DeferredSessionStorageHandler( servletContext );
         DefaultHandler defaultReloadableClassHandler = new DefaultReloadableClassHandler( servletContext );
         
         _actionForwardHandler = ( ActionForwardHandler )
@@ -117,6 +121,10 @@
                 adaptHandler( handlers != null ? handlers.getLoginHandlerArray() : null, defaultLoginHandler,
                               LoginHandler.class, servletContext );
         
+        _storageHandler = ( StorageHandler )
+                adaptHandler( handlers != null ? handlers.getStorageHandlerArray() : null, defaultStorageHandler,
+                              StorageHandler.class, servletContext );
+        
         _reloadableClassHandler = ( ReloadableClassHandler )
                 adaptHandler( handlers != null ? handlers.getReloadableClassHandlerArray() : null,
                               defaultReloadableClassHandler, ReloadableClassHandler.class, servletContext );
@@ -131,6 +139,7 @@
             _exceptionsHandler.reinit( servletContext );
             _forwardRedirectHandler.reinit( servletContext );
             _loginHandler.reinit( servletContext );
+            _storageHandler.reinit( servletContext );
             _reloadableClassHandler.reinit( servletContext );
         }
     }
@@ -153,6 +162,11 @@
     public LoginHandler getLoginHandler()
     {
         return _loginHandler;
+    }
+    
+    public StorageHandler getStorageHandler()
+    {
+        return _storageHandler;
     }
     
     public ReloadableClassHandler getReloadableClassHandler()

Added: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/StorageHandler.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/StorageHandler.java?rev=171199&view=auto
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/StorageHandler.java (added)
+++ incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/StorageHandler.java Fri May 20 23:23:22 2005
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.
+ *
+ * $Header:$
+ */
+package org.apache.beehive.netui.pageflow.handler;
+
+import org.apache.beehive.netui.pageflow.RequestContext;
+
+/**
+ * Handler for storing Page Flow objects.
+ */ 
+public interface StorageHandler
+        extends Handler
+{
+    /**
+     * Set a named attribute.
+     * 
+     * @param context the current RequestContext.
+     * @param attributeName the name of the attribute to set.
+     * @param value the attribute value.
+     */ 
+    public void setAttribute( RequestContext context, String attributeName, Object value );
+    
+    /**
+     * Remove a named attribute.
+     * 
+     * @param context the current RequestContext.
+     * @param attributeName the name of the attribute to remove.
+     */ 
+    public void removeAttribute( RequestContext context, String attributeName );
+    
+    /**
+     * Get a named attribute.
+     * 
+     * @param context the current RequestContext.
+     * @param attributeName the name of the attribute to get.
+     * @return the attribute, or <code>null</code> if there is no such named attribute.
+     */ 
+    public Object getAttribute( RequestContext context, String attributeName );
+    
+    /**
+     * Ensure that the given named attribute is replicated in a cluster for session failover, if appropriate.
+     * 
+     * @param context the current request context.
+     * @param attributeName the name of the attribute for which failover should be ensured.
+     * @param value the value of the attribute for which failover should be ensured.
+     */ 
+    public void ensureFailover( RequestContext context, String attributeName, Object value );
+    
+    /**
+     * Tell whether a given binding event should be allowed to occur.  This is mainly useful in cases when this
+     * handler writes data to some underlying storage (like the <code>HttpSession</code>) at some time other than
+     * when {@link #setAttribute} is called, in which case a binding event would be misleading.  Only
+     * {@link org.apache.beehive.netui.pageflow.PageFlowManagedObject}s pay attention to this.
+     * 
+     * @param event the binding event, e.g., <code>javax.servlet.http.HttpSessionBindingEvent</code>
+     * @return <code>true</code> if the event should be processed.
+     */ 
+    public boolean allowBindingEvent( Object event );
+}

Propchange: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/StorageHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DefaultActionForwardHandler.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DefaultActionForwardHandler.java?rev=171199&r1=171198&r2=171199&view=diff
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DefaultActionForwardHandler.java (original)
+++ incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DefaultActionForwardHandler.java Fri May 20 23:23:22 2005
@@ -480,7 +480,7 @@
             _log.debug( "Popped PageFlowController " + poppedPageFlow + " from the nesting stack" );
         }
 
-        InternalUtils.setCurrentPageFlow( poppedPageFlow, request );
+        InternalUtils.setCurrentPageFlow( poppedPageFlow, request, getServletContext() );
 
                 
         //

Added: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DeferredSessionStorageHandler.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DeferredSessionStorageHandler.java?rev=171199&view=auto
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DeferredSessionStorageHandler.java (added)
+++ incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DeferredSessionStorageHandler.java Fri May 20 23:23:22 2005
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.
+ *
+ * $Header:$
+ */
+package org.apache.beehive.netui.pageflow.internal;
+
+import org.apache.beehive.netui.pageflow.handler.StorageHandler;
+import org.apache.beehive.netui.pageflow.RequestContext;
+import org.apache.beehive.netui.pageflow.ServletContainerAdapter;
+import org.apache.beehive.netui.pageflow.PageFlowManagedObject;
+import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionBindingListener;
+import javax.servlet.http.HttpSessionBindingEvent;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * This alternate session storage handler does not write any attribute into the session until the very end of a chain
+ * of forwarded requests (i.e., not even at the end of an inner forwarded request).  This allows it to handle multiple
+ * concurrent forwarded requests, each of which is modifying the same data, in a more reasonable way.  Basically,
+ * each request works in its own snapshot of the session, and the last one to commit is the one whose snapshot wins.
+ * This is a better alternative thatn allowing them to interfere with each other in the middle of the request chain.
+ */ 
+public class DeferredSessionStorageHandler
+        extends DefaultHandler
+        implements StorageHandler
+{
+    private static final String CHANGELIST_ATTR = InternalConstants.ATTR_PREFIX + "changedAttrs";
+    private static final String FAILOVER_MAP_ATTR = InternalConstants.ATTR_PREFIX + "failoverAttrs";
+    
+    private static ThreadLocal _isCommittingChanges =
+            new ThreadLocal()
+            {
+                public Object initialValue()
+                {
+                    return Boolean.FALSE;
+                }
+            };
+    
+    public DeferredSessionStorageHandler( ServletContext servletContext )
+    {
+        init( null, null, servletContext );
+    }
+    
+    private static final class SessionBindingEvent
+        extends HttpSessionBindingEvent
+    {
+        public SessionBindingEvent( HttpSession httpSession, String attrName )
+        {
+            super( httpSession, attrName );
+        }
+
+        public SessionBindingEvent( HttpSession httpSession, String attrName, Object attrVal )
+        {
+            super( httpSession, attrName, attrVal );
+        }
+    }
+    
+    public void setAttribute( RequestContext context, String attrName, Object value )
+    {
+        HttpServletRequest request = ScopedServletUtils.getOuterRequest( ( HttpServletRequest ) context.getRequest() );
+        Object currentValue = request.getAttribute( attrName );
+        
+        //
+        // Emulate a setAttribute on the session: if the value is an HttpSessionBindingListener, invoke its
+        // valueUnbound().  Note that we don't currently care about calling valueBound().
+        //
+        if ( currentValue != null && currentValue != value && currentValue instanceof HttpSessionBindingListener )
+        {
+            HttpSessionBindingEvent event = new SessionBindingEvent( request.getSession( false ), attrName, value );
+            ( ( HttpSessionBindingListener ) currentValue ).valueUnbound( event );
+        }
+        
+        request.setAttribute( attrName, value );
+        getChangedAttributesList( request, true, false ).add( attrName );
+    }
+    
+    public void removeAttribute( RequestContext context, String attributeName )
+    {
+        ServletRequest request = ScopedServletUtils.getOuterServletRequest( context.getRequest() );
+        request.removeAttribute( attributeName );
+        getChangedAttributesList( request, true, false ).add( attributeName );
+    }
+    
+    public Object getAttribute( RequestContext context, String attributeName )
+    {
+        HttpServletRequest request = ScopedServletUtils.getOuterRequest( ( HttpServletRequest ) context.getRequest() );
+        Object val = request.getAttribute( attributeName );
+        if ( val != null ) return val;
+        //
+        // If the attribute isn't present in the request and is in the list of changed attrs, then it was removed.
+        // Don't fall back to the session attribute in that case.
+        //
+        HashSet changedAttrs = getChangedAttributesList( request, false, false );
+        if ( changedAttrs != null && changedAttrs.contains( attributeName ) ) return null;
+        
+        
+        //
+        // Get the attribute out of the session, and put it into the request.  Until applyChanges is called, this is
+        // the value we'll use.
+        //
+        HttpSession session = request.getSession( false );
+        if ( session != null )
+        {
+            val = session.getAttribute( attributeName );
+            if ( val != null ) request.setAttribute( attributeName, val );
+        }
+        
+        return val;
+    }
+    
+    public static void applyChanges( HttpServletRequest request, ServletContext servletContext )
+    {
+        request = ScopedServletUtils.getOuterRequest( request );
+        HashSet changedAttrs = getChangedAttributesList( request, false, true );
+        
+        if ( changedAttrs != null )
+        {
+            HttpSession session = request.getSession();
+            
+            //
+            // Go through each changed attribute, and either write it to the session or remove it to the session,
+            // depending on whether or not it exists in the request.
+            //
+            for ( Iterator i = changedAttrs.iterator(); i.hasNext(); )
+            {
+                String attrName = ( String ) i.next();
+                Object val = request.getAttribute( attrName );
+                
+                if ( val != null )
+                {
+                    //
+                    // Write it to the session, but only if the current value isn't already this value.
+                    //
+                    Object currentValue = session.getAttribute( attrName );
+                    
+                    if ( currentValue != val )
+                    {
+                        //
+                        // This ThreadLocal value allows others (e.g., an HttpSessionBindingListener like
+                        // PageFlowManagedObject) that we're in the middle of committing changes to the session.
+                        //
+                        _isCommittingChanges.set( Boolean.TRUE );
+                        
+                        try
+                        {
+                            session.setAttribute( attrName, val );
+                        }
+                        finally
+                        {
+                            _isCommittingChanges.set( Boolean.FALSE );
+                        }
+                    }
+                }
+                else
+                {
+                    //
+                    // This ThreadLocal value allows others (e.g., an HttpSessionBindingListener like
+                    // PageFlowManagedObject) that we're in the middle of committing changes to the session.
+                    //
+                    _isCommittingChanges.set( Boolean.TRUE );
+                    
+                    try
+                    {
+                        session.removeAttribute( attrName );
+                    }
+                    finally
+                    {
+                        _isCommittingChanges.set( Boolean.FALSE );
+                    }
+                }
+            }
+        }
+        
+        
+        //
+        // Now go through the attributes we need to ensure-failover on.
+        //
+        HashMap failoverAttrs = getFailoverAttributesMap( request, false, true );
+        
+        if ( failoverAttrs != null )
+        {
+            ServletContainerAdapter sa = AdapterManager.getServletContainerAdapter( servletContext );
+            
+            for ( Iterator i = failoverAttrs.entrySet().iterator(); i.hasNext(); )
+            {
+                Map.Entry entry = ( Map.Entry ) i.next();
+                sa.ensureFailover( ( String ) entry.getKey(), entry.getValue(), request );
+            }
+        }
+    }
+    
+    public void ensureFailover( RequestContext context, String attributeName, Object value )
+    {
+        getFailoverAttributesMap( context.getRequest(), true, false ).put( attributeName, value );
+    }
+    
+    private static HashSet getChangedAttributesList( ServletRequest request, boolean create, boolean remove )
+    {
+        HashSet set = ( HashSet ) request.getAttribute( CHANGELIST_ATTR );
+        
+        if ( set == null && create )
+        {
+            set = new HashSet();
+            request.setAttribute( CHANGELIST_ATTR, set );
+        }
+        
+        if ( set!= null && remove ) request.removeAttribute( CHANGELIST_ATTR );
+        
+        return set;
+    }
+    
+    private static HashMap getFailoverAttributesMap( ServletRequest request, boolean create, boolean remove )
+    {
+        HashMap map = ( HashMap ) request.getAttribute( FAILOVER_MAP_ATTR );
+        
+        if ( map == null && create )
+        {
+            map = new HashMap();
+            request.setAttribute( FAILOVER_MAP_ATTR, map );
+        }
+        
+        if ( map != null && remove ) request.removeAttribute( FAILOVER_MAP_ATTR );
+        
+        return map;
+    }
+
+    public boolean allowBindingEvent( Object event )
+    {
+        return ! ( ( Boolean ) _isCommittingChanges.get() ).booleanValue();
+    }
+}
\ No newline at end of file

Propchange: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DeferredSessionStorageHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/FacesBackingBeanFactory.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/FacesBackingBeanFactory.java?rev=171199&r1=171198&r2=171199&view=diff
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/FacesBackingBeanFactory.java (original)
+++ incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/FacesBackingBeanFactory.java Fri May 20 23:23:22 2005
@@ -85,8 +85,7 @@
             //
             // We didn't create a backing bean.  If there's one in the session (an inappropriate one), remove it.
             //
-            HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
-            ScopedServletUtils.removeScopedSessionAttr( FACES_BACKING_ATTR, unwrappedRequest );
+            InternalUtils.removeCurrentFacesBackingBean( request, servletContext );
         }
         else if ( currentBean != null )
         {

Modified: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/InternalUtils.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/InternalUtils.java?rev=171199&r1=171198&r2=171199&view=diff
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/InternalUtils.java (original)
+++ incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/InternalUtils.java Fri May 20 23:23:22 2005
@@ -25,6 +25,7 @@
 import org.apache.beehive.netui.pageflow.config.PageFlowActionFormBean;
 import org.apache.beehive.netui.pageflow.handler.Handlers;
 import org.apache.beehive.netui.pageflow.handler.ReloadableClassHandler;
+import org.apache.beehive.netui.pageflow.handler.StorageHandler;
 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
 import org.apache.beehive.netui.util.Bundle;
 import org.apache.beehive.netui.util.internal.ServletUtils;
@@ -286,16 +287,33 @@
         return LONGLIVED_PAGEFLOWS_ATTR_PREFIX + modulePath;
     }
     
-    public static void setCurrentPageFlow( PageFlowController jpf, HttpServletRequest request )
+    public static void setCurrentPageFlow( PageFlowController jpf, HttpServletRequest request,
+                                           ServletContext servletContext )
     {
-        setCurrentActionResolver( jpf, request );
+        setCurrentActionResolver( jpf, request, servletContext );
     }
     
-    public static void removeCurrentPageFlow( HttpServletRequest request )
+    public static void removeCurrentPageFlow( HttpServletRequest request, ServletContext servletContext )
     {
+        StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
         HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
-        ScopedServletUtils.removeScopedSessionAttr( CURRENT_JPF_ATTR, unwrappedRequest );
-        ScopedServletUtils.removeScopedSessionAttr( CURRENT_LONGLIVED_ATTR, unwrappedRequest );
+        RequestContext rc = new RequestContext( unwrappedRequest, null );
+        String currentJpfAttrName = ScopedServletUtils.getScopedSessionAttrName( CURRENT_JPF_ATTR, unwrappedRequest );
+        String currentLongLivedAttrName =
+                ScopedServletUtils.getScopedSessionAttrName( CURRENT_LONGLIVED_ATTR, unwrappedRequest );
+        
+        sh.removeAttribute( rc, currentJpfAttrName );
+        sh.removeAttribute( rc, currentLongLivedAttrName );
+    }
+    
+    public static void removeCurrentFacesBackingBean( HttpServletRequest request, ServletContext servletContext )
+    {
+        StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
+        HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
+        RequestContext rc = new RequestContext( unwrappedRequest, null );
+        String attrName = ScopedServletUtils.getScopedSessionAttrName( FACES_BACKING_ATTR, unwrappedRequest );
+        
+        sh.removeAttribute( rc, attrName );
     }
     
     public static String getDecodedURI( HttpServletRequest request )
@@ -576,16 +594,21 @@
      * Set the current ActionResolver ({@link PageFlowController}) in the user session.
      * 
      * @param resolver the ActionResolver to set as the current one in the user session.
-     * @param request the current HttpServletRequest.
      */ 
-    public static void setCurrentActionResolver( ActionResolver resolver, HttpServletRequest request )
+    public static void setCurrentActionResolver( ActionResolver resolver, HttpServletRequest request,
+                                                 ServletContext servletContext )
     {
+        StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
         HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
+        RequestContext rc = new RequestContext( unwrappedRequest, null );
+        String currentJpfAttrName = ScopedServletUtils.getScopedSessionAttrName( CURRENT_JPF_ATTR, unwrappedRequest );
+        String currentLongLivedJpfAttrName =
+                ScopedServletUtils.getScopedSessionAttrName( CURRENT_LONGLIVED_ATTR, unwrappedRequest );
         
         if ( resolver == null )
         {
-            ScopedServletUtils.removeScopedSessionAttr( CURRENT_JPF_ATTR, unwrappedRequest );
-            ScopedServletUtils.removeScopedSessionAttr( CURRENT_LONGLIVED_ATTR, unwrappedRequest );
+            sh.removeAttribute( rc, currentJpfAttrName );
+            sh.removeAttribute( rc, currentLongLivedJpfAttrName );
             return;
         }
         
@@ -595,20 +618,22 @@
         if ( resolver.isPageFlow() && isLongLived( ( ( PageFlowController ) resolver ).getModuleConfig() ) )
         {
             String longLivedAttrName = getLongLivedFlowAttr( resolver.getModulePath() );
+            longLivedAttrName = ScopedServletUtils.getScopedSessionAttrName( longLivedAttrName, unwrappedRequest );
             
             // Only set this attribute if it's not already there.  We want to avoid our onDestroy() callback that's
             // invoked when the page flow's session attribute is unbound.
-            if ( ScopedServletUtils.getScopedSessionAttr( longLivedAttrName, request ) != resolver )
+            if ( sh.getAttribute( rc, longLivedAttrName ) != resolver )
             {
-                ScopedServletUtils.setScopedSessionAttr( longLivedAttrName, resolver, unwrappedRequest );
+                sh.setAttribute( rc, longLivedAttrName, resolver );
             }
-            ScopedServletUtils.setScopedSessionAttr( CURRENT_LONGLIVED_ATTR, resolver.getModulePath(), unwrappedRequest );
-            ScopedServletUtils.removeScopedSessionAttr( CURRENT_JPF_ATTR, unwrappedRequest );
+            
+            sh.setAttribute( rc, currentLongLivedJpfAttrName, resolver.getModulePath() );
+            sh.removeAttribute( rc, currentJpfAttrName );
         }
         else
         {
-            ScopedServletUtils.setScopedSessionAttr( CURRENT_JPF_ATTR, resolver, unwrappedRequest );
-            ScopedServletUtils.removeScopedSessionAttr( CURRENT_LONGLIVED_ATTR, unwrappedRequest );
+            sh.setAttribute( rc, currentJpfAttrName, resolver );
+            sh.removeAttribute( rc, currentLongLivedJpfAttrName );
         }
     }
     
@@ -665,8 +690,12 @@
     {
         if ( request instanceof HttpServletRequest )
         {
+            ServletContext servletContext = getServletContext( request );
+            StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
             HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( ( HttpServletRequest ) request );
-            return ( FacesBackingBean ) ScopedServletUtils.getScopedSessionAttr( FACES_BACKING_ATTR, unwrappedRequest );
+            RequestContext rc = new RequestContext( unwrappedRequest, null );
+            String attrName = ScopedServletUtils.getScopedSessionAttrName( FACES_BACKING_ATTR, unwrappedRequest );
+            return ( FacesBackingBean ) sh.getAttribute( rc, attrName );
         }
         
         return null;
@@ -676,15 +705,19 @@
     {
         if ( request instanceof HttpServletRequest )
         {
+            ServletContext servletContext = getServletContext( request );
+            StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
             HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( ( HttpServletRequest ) request );
+            RequestContext rc = new RequestContext( unwrappedRequest, null );
+            String attrName = ScopedServletUtils.getScopedSessionAttrName( FACES_BACKING_ATTR, unwrappedRequest );
             
             if ( bean == null )
             {
-                ScopedServletUtils.removeScopedSessionAttr( FACES_BACKING_ATTR, unwrappedRequest );
+                sh.removeAttribute( rc, attrName );
             }
             else
             {
-                ScopedServletUtils.setScopedSessionAttr( FACES_BACKING_ATTR, bean, unwrappedRequest );
+                sh.setAttribute( rc, attrName, bean );
             }
         }
     }

Added: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/SimpleSessionStorageHandler.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/SimpleSessionStorageHandler.java?rev=171199&view=auto
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/SimpleSessionStorageHandler.java (added)
+++ incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/SimpleSessionStorageHandler.java Fri May 20 23:23:22 2005
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.
+ *
+ * $Header:$
+ */
+package org.apache.beehive.netui.pageflow.internal;
+
+import org.apache.beehive.netui.pageflow.handler.StorageHandler;
+import org.apache.beehive.netui.pageflow.RequestContext;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import javax.servlet.ServletContext;
+
+/**
+ * This storage handler simply puts/gets attributes in the session.  It does not do anything to support multiple
+ * concurrent forwarded requests that are simultaneously modifying session data.
+ * 
+ * @see DeferredSessionStorageHandler
+ */ 
+public class SimpleSessionStorageHandler
+        extends DefaultHandler
+        implements StorageHandler
+{
+    public SimpleSessionStorageHandler( ServletContext servletContext )
+    {
+        init( null, null, servletContext );
+    }
+    
+    public void setAttribute( RequestContext context, String attributeName, Object value )
+    {
+        ( ( HttpServletRequest ) context.getRequest() ).getSession().setAttribute( attributeName, value ); 
+    }
+
+    public void removeAttribute( RequestContext context, String attributeName )
+    {
+        HttpSession session = ( ( HttpServletRequest ) context.getRequest() ).getSession( false );
+        if ( session != null ) session.removeAttribute( attributeName );
+    }
+
+    public Object getAttribute( RequestContext context, String attributeName )
+    {
+        HttpSession session = ( ( HttpServletRequest ) context.getRequest() ).getSession( false );
+        return session != null ? session.getAttribute( attributeName ) : null;
+    }
+
+    public void ensureFailover( RequestContext context, String attributeName, Object value )
+    {
+        HttpServletRequest request = ( HttpServletRequest ) context.getRequest();
+        AdapterManager.getServletContainerAdapter( getServletContext() ).ensureFailover( attributeName, value, request );
+    }
+
+    public boolean allowBindingEvent( Object event )
+    {
+        return true;
+    }
+}

Propchange: incubator/beehive/branches/rich-vnext/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/SimpleSessionStorageHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/beehive/branches/rich-vnext/netui/src/util/schema/netui-config/netui-config.xsd
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/src/util/schema/netui-config/netui-config.xsd?rev=171199&r1=171198&r2=171199&view=diff
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/src/util/schema/netui-config/netui-config.xsd (original)
+++ incubator/beehive/branches/rich-vnext/netui/src/util/schema/netui-config/netui-config.xsd Fri May 20 23:23:22 2005
@@ -100,6 +100,7 @@
             <xsd:element name="exceptions-handler" type="netui:handler" minOccurs="0" maxOccurs="unbounded"/>
             <xsd:element name="forward-redirect-handler" type="netui:handler" minOccurs="0" maxOccurs="unbounded"/>
             <xsd:element name="login-handler" type="netui:handler" minOccurs="0" maxOccurs="unbounded"/>
+            <xsd:element name="storage-handler" type="netui:handler" minOccurs="0" maxOccurs="unbounded"/>
             <xsd:element name="reloadable-class-handler" type="netui:handler" minOccurs="0" maxOccurs="unbounded"/>
         </xsd:sequence>
     </xsd:complexType>

Added: incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/Controller.jpf
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/Controller.jpf?rev=171199&view=auto
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/Controller.jpf (added)
+++ incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/Controller.jpf Fri May 20 23:23:22 2005
@@ -0,0 +1,60 @@
+package miniTests.nestReturnSingleRequest.first;
+
+import org.apache.beehive.netui.pageflow.*;
+import org.apache.beehive.netui.pageflow.annotations.*;
+import javax.servlet.http.HttpSession;
+import java.util.*;
+
+@Jpf.Controller(
+    simpleActions={
+        @Jpf.SimpleAction(name="begin", path="index.jsp"),
+        @Jpf.SimpleAction(name="goNested", path="/miniTests/nestReturnSingleRequest/nested/Controller.jpf"),
+        @Jpf.SimpleAction(name="goNestedWithDelay", path="/miniTests/nestReturnSingleRequest/nested/beginWithDelay.do")
+    }
+)
+public class Controller extends PageFlowController
+{
+    @Jpf.Action(
+        forwards={
+            @Jpf.Forward(name="success", path="success.jsp")
+        }
+    )
+    public Forward nestedDone( String retVal )
+    {
+        return new Forward( "success", "retVal", retVal );
+    }
+
+    protected void onCreate()
+    {
+        addMessage( getRequest().getSession(), "in onCreate" );
+    }
+
+    protected void onDestroy( HttpSession session )
+    {
+        addMessage( session, "in onDestroy" );
+    }
+
+    @Jpf.Action(
+        forwards={
+            @Jpf.Forward(name="index", path="index.jsp")
+        }
+    )
+    public Forward clearMessages( String retVal )
+    {
+        getSession().removeAttribute( "messages" );
+        return new Forward( "index" );
+    }
+
+    private void addMessage( HttpSession session, String msg )
+    {
+        List messages = ( List ) session.getAttribute( "messages" );
+
+        if ( messages == null )
+        {
+            messages = new ArrayList();
+            session.setAttribute( "messages", messages );
+        }
+
+        messages.add( getClass().getName() + ": " + msg );
+    }
+}

Propchange: incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/Controller.jpf
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/index.jsp
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/index.jsp?rev=171199&view=auto
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/index.jsp (added)
+++ incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/index.jsp Fri May 20 23:23:22 2005
@@ -0,0 +1,38 @@
+<%@ page language="java" contentType="text/html;charset=UTF-8"%>
+<%@ taglib prefix="netui" uri="http://beehive.apache.org/netui/tags-html-1.0"%>
+<%@ taglib prefix="netui-data" uri="http://beehive.apache.org/netui/tags-databinding-1.0"%>
+<%@ taglib prefix="netui-template" uri="http://beehive.apache.org/netui/tags-template-1.0"%>
+
+
+<netui:html>
+    <head>
+        <netui:base/>
+    </head>
+    <netui:body>
+        <h3>${pageFlow.URI}</h3>
+
+        <netui:anchor action="goNested">goNested</netui:anchor>
+            - should produce an onCreate and an onDestroy for the nested page flow.
+        <br/>
+        <netui:anchor action="goNestedWithDelay">goNestedWithDelay</netui:anchor>
+            - this is for a manual test of rapid-clicking the link.  Should produce a bunch of
+              onCreates, then a bunch of onDestroys.
+        <br/>
+        <netui:anchor action="clearMessages">clear messages</netui:anchor>
+        <br/>
+        <netui:anchor action="begin">refresh</netui:anchor>
+
+        <br/>
+        <br/>
+        <hr/>
+        Lifecycle:<br/>
+        <ul>
+        <netui-data:repeater dataSource="sessionScope.messages">
+            <netui-data:repeaterItem><li>${container.item}</li></netui-data:repeaterItem>
+        </netui-data:repeater>
+        </ul>
+    </netui:body>
+</netui:html>
+
+  
+

Propchange: incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/index.jsp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/success.jsp
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/success.jsp?rev=171199&view=auto
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/success.jsp (added)
+++ incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/success.jsp Fri May 20 23:23:22 2005
@@ -0,0 +1,31 @@
+<%@ page language="java" contentType="text/html;charset=UTF-8"%>
+<%@ taglib prefix="netui" uri="http://beehive.apache.org/netui/tags-html-1.0"%>
+<%@ taglib prefix="netui-data" uri="http://beehive.apache.org/netui/tags-databinding-1.0"%>
+<%@ taglib prefix="netui-template" uri="http://beehive.apache.org/netui/tags-template-1.0"%>
+
+
+<netui:html>
+    <head>
+        <netui:base/>
+    </head>
+    <netui:body>
+        <h3>${pageFlow.URI}</h3>
+
+        return val from nested page flow: <b>${pageInput.retVal}</b>
+        <br/>
+        <netui:anchor action="begin">start over</netui:anchor>
+
+        <br/>
+        <br/>
+        <hr/>
+        Lifecycle:<br/>
+        <ul>
+        <netui-data:repeater dataSource="sessionScope.messages">
+            <netui-data:repeaterItem><li>${container.item}</li></netui-data:repeaterItem>
+        </netui-data:repeater>
+        </ul>
+    </netui:body>
+</netui:html>
+
+  
+

Propchange: incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/first/success.jsp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/index.jsp
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/index.jsp?rev=171199&view=auto
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/index.jsp (added)
+++ incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/index.jsp Fri May 20 23:23:22 2005
@@ -0,0 +1,21 @@
+<%@ page language="java" contentType="text/html;charset=UTF-8"%>
+<%@ taglib uri="http://beehive.apache.org/netui/tags-databinding-1.0" prefix="netui-data"%>
+<%@ taglib uri="http://beehive.apache.org/netui/tags-html-1.0" prefix="netui"%>
+<%@ taglib uri="http://beehive.apache.org/netui/tags-template-1.0" prefix="netui-template"%>
+
+<netui:html>
+    <head>
+        <title>
+            NestReturnSingleRequest
+        </title>
+    </head>
+    <body>
+        <h3>NestReturnSingleRequest</h3>
+        
+        <% request.getSession().removeAttribute( "messages" ); %>
+        (This page clears the "messages" attribute which is used in the test.)
+        <br/>
+        <br/>
+        <a href="first/Controller.jpf">start the test</a>
+    </body>
+</netui:html>

Propchange: incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/index.jsp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/nested/Controller.jpf
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/nested/Controller.jpf?rev=171199&view=auto
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/nested/Controller.jpf (added)
+++ incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/nested/Controller.jpf Fri May 20 23:23:22 2005
@@ -0,0 +1,58 @@
+package miniTests.nestReturnSingleRequest.nested;
+
+import org.apache.beehive.netui.pageflow.*;
+import org.apache.beehive.netui.pageflow.annotations.*;
+import javax.servlet.http.HttpSession;
+import java.util.*;
+
+@Jpf.Controller(
+    nested=true
+)
+public class Controller extends PageFlowController
+{
+    @Jpf.Action(
+        forwards={
+            @Jpf.Forward(name="done", returnAction="nestedDone", outputFormBeanType=String.class)
+        }
+    )
+    public Forward begin()
+        throws InterruptedException
+    {
+        return new Forward( "done", "GOT IT!" );
+    }
+
+    @Jpf.Action(
+        forwards={
+            @Jpf.Forward(name="done", returnAction="nestedDone", outputFormBeanType=String.class)
+        }
+    )
+    public Forward beginWithDelay()
+        throws InterruptedException
+    {
+        Thread.sleep( 3000 );
+        return new Forward( "done", "GOT IT!" );
+    }
+
+    protected void onCreate()
+    {
+        addMessage( getRequest().getSession(), "in onCreate" );
+    }
+
+    protected void onDestroy( HttpSession session )
+    {
+        addMessage( session, "in onDestroy" );
+    }
+
+    private void addMessage( HttpSession session, String msg )
+    {
+        List messages = ( List ) session.getAttribute( "messages" );
+
+        if ( messages == null )
+        {
+            messages = new ArrayList();
+            session.setAttribute( "messages", messages );
+        }
+
+        messages.add( getClass().getName() + ": " + msg );
+    }
+}

Propchange: incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/coreWeb/miniTests/nestReturnSingleRequest/nested/Controller.jpf
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/testRecorder/config/testRecorder-tests.xml
URL: http://svn.apache.org/viewcvs/incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/testRecorder/config/testRecorder-tests.xml?rev=171199&r1=171198&r2=171199&view=diff
==============================================================================
--- incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/testRecorder/config/testRecorder-tests.xml (original)
+++ incubator/beehive/branches/rich-vnext/netui/test/webapps/drt/testRecorder/config/testRecorder-tests.xml Fri May 20 23:23:22 2005
@@ -5070,6 +5070,21 @@
          </features>
       </test>
       <test>
+         <name>NestReturnSingleRequest</name>
+         <description>Test to ensure that the right lifecycle methods are called when nesting/returning within a single request.</description>
+         <webapp>coreWeb</webapp>
+         <categories>
+            <category>bvt</category>
+            <category>bvt.struts11</category>
+            <category>corePageFlow</category>
+         </categories>
+         <features>
+            <feature>PageFlow</feature>
+            <feature>Nesting</feature>
+            <feature>Lifecycle</feature>
+         </features>
+      </test>
+      <test>
          <name>NonNormalizedPath</name>
          <description>Test forwarding to paths that contain '.' and '..'.  Note: there is an EXPECTED 404 response in this test.</description>
          <webapp>coreWeb</webapp>