You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2008/01/15 00:16:52 UTC

svn commit: r611966 [1/2] - in /tapestry/tapestry5/trunk: tapestry-core/src/main/java/org/apache/tapestry/ tapestry-core/src/main/java/org/apache/tapestry/internal/ tapestry-core/src/main/java/org/apache/tapestry/internal/bindings/ tapestry-core/src/ma...

Author: hlship
Date: Mon Jan 14 15:16:45 2008
New Revision: 611966

URL: http://svn.apache.org/viewvc?rev=611966&view=rev
Log:
TAPESTRY-2042: Make it possible to merge action requests with rendering, as with Tapestry 4

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ActionRenderResponseGenerator.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ActionRenderResponseGeneratorImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ImmediateActionRenderResponseFilter.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ImmediateActionRenderResponseGenerator.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/app4/
    tapestry/tapestry5/trunk/tapestry-core/src/test/app4/Destination.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/app4/Start.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/app4/WEB-INF/
    tapestry/tapestry5/trunk/tapestry-core/src/test/app4/WEB-INF/web.xml
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/ImmediateModeTests.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app4/
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app4/pages/
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app4/pages/Destination.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app4/pages/Start.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app4/services/
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app4/services/AppModule.java
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/Asset.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/TapestryConstants.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/bindings/AssetBindingFactory.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CachedPage.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClassResultProcessor.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClasspathAssetFactory.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionRequestHandlerImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInstanceResultProcessor.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DefaultRequestExceptionHandler.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PagePoolCache.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PagePoolImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderRequestHandlerImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRenderer.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRendererImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ResponseRendererImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/StringResultProcessor.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/PageLinkInvoker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PageRenderRequestHandler.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/conf.apt
    tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/lifecycle.apt
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ClasspathAssetFactoryTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ComponentInstanceResultProcessorTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/PageRenderDispatcherTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/RequestPathOptimizerImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ResponseRendererImplTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Scope.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/AbstractServiceCreator.java

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/Asset.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/Asset.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/Asset.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/Asset.java Mon Jan 14 15:16:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2008 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.
@@ -17,18 +17,20 @@
 import org.apache.tapestry.ioc.Resource;
 
 /**
- * An Asset is any kind of resource that can be exposed to the client web browser. Although quite
- * often an Asset is a resource in a web application's context folder, within Tapestry, Assets may
- * also be resources on the classpath (i.e., packaged inside JARs).
+ * An Asset is any kind of resource that can be exposed to the client web browser. Although quite often an Asset is a
+ * resource in a web application's context folder, within Tapestry, Assets may also be resources on the classpath (i.e.,
+ * packaged inside JARs).
  * <p/>
- * An Asset's toString() will return the URL for the resource (the same value as
- * {@link #toClientURL()}).
+ * An Asset's toString() will return the URL for the resource (the same value as {@link #toClientURL()}).
  */
 public interface Asset
 {
     /**
-     * Returns a URL that can be passed, unchanged, to the client in order for it to access the
-     * resource.
+     * Returns a URL that can be passed, unchanged, to the client in order for it to access the resource. The same value
+     * is returned from <code>toString()</code>.
+     * <p/>
+     * Note that the returned value may be {@linkplain org.apache.tapestry.TapestryConstants#FORCE_FULL_URIS_SYMBOL
+     * request dependent}. You may cache instances of Asset, but do not cache the client URL path as it may change.
      */
     String toClientURL();
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/TapestryConstants.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/TapestryConstants.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/TapestryConstants.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/TapestryConstants.java Mon Jan 14 15:16:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 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.
@@ -25,15 +25,15 @@
     public static final String ACTION_EVENT = "action";
 
     /**
-     * Event triggered when a page is activated (for rendering). The component event handler will be
-     * passed the context provided by the passivate event.
+     * Event triggered when a page is activated (for rendering). The component event handler will be passed the context
+     * provided by the passivate event.
      */
     public static final String ACTIVATE_EVENT = "activate";
 
     /**
-     * Event triggered when a link for a page is generated. The event handler for the page may
-     * provide an object, or an array of objects, as the context for the page. These values will
-     * become part of the page's context, and will be provided back when the page is activated.
+     * Event triggered when a link for a page is generated. The event handler for the page may provide an object, or an
+     * array of objects, as the context for the page. These values will become part of the page's context, and will be
+     * provided back when the page is activated.
      */
     public static final String PASSIVATE_EVENT = "passivate";
 
@@ -53,16 +53,15 @@
     public static final String PROP_BINDING_PREFIX = "prop";
 
     /**
-     * Meta data key applied to pages that sets the response content type. A factory default
-     * provides the value "text/html" when not overridden.
+     * Meta data key applied to pages that sets the response content type. A factory default provides the value
+     * "text/html" when not overridden.
      */
     public static final String RESPONSE_CONTENT_TYPE = "tapestry.response-content-type";
 
     /**
-     * Meta data key applied to pages that sets the response encoding. A factory default provides
-     * the value "UTF-8" when not overriden. Content type may also be specified in the
-     * {@link #RESPONSE_CONTENT_TYPE content type} as parameter "charset", i.e.,
-     * "text/html;charset=UTF-8".
+     * Meta data key applied to pages that sets the response encoding. A factory default provides the value "UTF-8" when
+     * not overriden. Content type may also be specified in the {@link #RESPONSE_CONTENT_TYPE content type} as parameter
+     * "charset", i.e., "text/html;charset=UTF-8".
      */
     public static final String RESPONSE_ENCODING = "tapestry.response-encoding";
 
@@ -80,6 +79,19 @@
      * Symbol which may be set to "true" to force the use of full URIs (not relative URIs) exclusively.
      */
     public static final String FORCE_FULL_URIS_SYMBOL = "tapestry.force-full-uris";
+
+
+    /**
+     * If set to true, then action requests will render a page markup response immediately, rather than sending a
+     * redirect to render the response.
+     */
+    public static final String SUPPRESS_REDIRECT_FROM_ACTION_REQUESTS_SYMBOL = "tapestry.suppress-redirect-from-action-requests";
+
+    /**
+     * The list of locales supported by the application; locales identified in the incoming request are "narrowed" to
+     * one of these values.
+     */
+    public static final String SUPPORTED_LOCALES_SYMBOL = "tapestry.supported-locales";
 
     private TapestryConstants()
     {

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java Mon Jan 14 15:16:45 2008
@@ -19,32 +19,31 @@
 public final class InternalConstants
 {
     /**
-     * Init parameter used to identify the package from which application classes are loaded. Such
-     * classes are in the pages, components and mixins sub-packages.
+     * Init parameter used to identify the package from which application classes are loaded. Such classes are in the
+     * pages, components and mixins sub-packages.
      */
     public static final String TAPESTRY_APP_PACKAGE_PARAM = "tapestry.app-package";
 
     /**
-     * The application mode, generally "servlet", used to select the correct contributions to the
-     * {@link Alias} service.
+     * The application mode, generally "servlet", used to select the correct contributions to the {@link Alias}
+     * service.
      */
     public static final String TAPESTRY_ALIAS_MODE_SYMBOL = "tapestry.alias-mode";
 
     /**
-     * The name of the application (i.e., the name of the application filter). Used, for example, to
-     * select additional resources related to the application.
+     * The name of the application (i.e., the name of the application filter). Used, for example, to select additional
+     * resources related to the application.
      */
     public static final String TAPESTRY_APP_NAME_SYMBOL = "tapestry.app-name";
 
     /**
-     * The extension used for Tapestry component template files, <em>T</em>apestry <em>M</em>arkup
-     * <em>L</em>anguage. Template files are well-formed XML files.
+     * The extension used for Tapestry component template files, <em>T</em>apestry <em>M</em>arkup <em>L</em>anguage.
+     * Template files are well-formed XML files.
      */
     public static final String TEMPLATE_EXTENSION = "tml";
 
     /**
-     * The name of the query parameter that stores the page activation context inside an action
-     * request.
+     * The name of the query parameter that stores the page activation context inside an action request.
      */
     public static final String PAGE_CONTEXT_NAME = "t:ac";
 
@@ -57,11 +56,18 @@
 
 
     /**
-     * Used in some Ajax scenarios to set the content type for the response early, when the Page instance
-     * (the authority on content types) is known. The value is of type {@link org.apache.tapestry.ContentType}.
+     * Used in some Ajax scenarios to set the content type for the response early, when the Page instance (the authority
+     * on content types) is known. The value is of type {@link org.apache.tapestry.ContentType}.
      */
     public static final String CONTENT_TYPE_ATTRIBUTE_NAME = "content-type";
     public static final String CHARSET_CONTENT_TYPE_PARAMETER = "charset";
+
+    /**
+     * Request attribute that stores a {@link org.apache.tapestry.internal.structure.Page} instance that will be
+     * rendered as the {@linkplain org.apache.tapestry.TapestryConstants#SUPPRESS_REDIRECT_FROM_ACTION_REQUESTS_SYMBOL
+     * immediate mode response}.
+     */
+    public static final String IMMEDIATE_RESPONSE_PAGE_ATTRIBUTE = "tapestry.immediate-response-page";
 
     private InternalConstants()
     {

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/bindings/AssetBindingFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/bindings/AssetBindingFactory.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/bindings/AssetBindingFactory.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/bindings/AssetBindingFactory.java Mon Jan 14 15:16:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 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.
@@ -17,8 +17,10 @@
 import org.apache.tapestry.Asset;
 import org.apache.tapestry.Binding;
 import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.TapestryConstants;
 import org.apache.tapestry.ioc.Location;
 import org.apache.tapestry.ioc.Resource;
+import org.apache.tapestry.ioc.annotations.Symbol;
 import org.apache.tapestry.services.AssetSource;
 import org.apache.tapestry.services.BindingFactory;
 
@@ -31,19 +33,63 @@
 {
     private final AssetSource _source;
 
-    public AssetBindingFactory(final AssetSource source)
+    private final boolean _forceFullURIs;
+
+    public class AssetBinding extends AbstractBinding
+    {
+        private final String _description;
+
+        private final Asset _asset;
+
+        protected AssetBinding(String description, Asset asset, Location location)
+        {
+            super(location);
+
+            _description = description;
+            _asset = asset;
+        }
+
+        public Object get()
+        {
+            return _asset;
+        }
+
+        /**
+         * Asset bindings are invariant only if full URIs are being used.  This is complicated ... basically, if the
+         * Asset is invariant, then any value coerced from the Asset is also invariant (such as a String version of an
+         * Asset's path).  Thus, the invariant String gets cached inside component parameter fields.  However, when the
+         * path is dynamic (i.e., because of {@link org.apache.tapestry.internal.services.RequestPathOptimizer}), we
+         * need to ensure that the Assets aren't cached.
+         *
+         * @return true if full URIs are enabled, false otherwise
+         */
+        @Override
+        public boolean isInvariant()
+        {
+            return _forceFullURIs;
+        }
+
+        @Override
+        public String toString()
+        {
+            return String.format("AssetBinding[%s: %s]", _description, _asset);
+        }
+    }
+
+    public AssetBindingFactory(AssetSource source,
+                               @Symbol(TapestryConstants.FORCE_FULL_URIS_SYMBOL)boolean forceFullURIs)
     {
         _source = source;
+        _forceFullURIs = forceFullURIs;
     }
 
-    public Binding newBinding(String description, ComponentResources container,
-                              ComponentResources component, String expression, Location location)
+    public Binding newBinding(String description, ComponentResources container, ComponentResources component,
+                              String expression, Location location)
     {
         Resource baseResource = container.getBaseResource();
 
         Asset asset = _source.findAsset(baseResource, expression, container.getLocale());
 
-        return new LiteralBinding(description, asset, location);
-
+        return new AssetBinding(description, asset, location);
     }
 }

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ActionRenderResponseGenerator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ActionRenderResponseGenerator.java?rev=611966&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ActionRenderResponseGenerator.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ActionRenderResponseGenerator.java Mon Jan 14 15:16:45 2008
@@ -0,0 +1,27 @@
+// Copyright 2008 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.
+
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.internal.structure.Page;
+
+import java.io.IOException;
+
+/**
+ * Used to produce the normal response to an action request: a redirect to a particular page.
+ */
+public interface ActionRenderResponseGenerator
+{
+    void generateResponse(Page page) throws IOException;
+}

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ActionRenderResponseGeneratorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ActionRenderResponseGeneratorImpl.java?rev=611966&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ActionRenderResponseGeneratorImpl.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ActionRenderResponseGeneratorImpl.java Mon Jan 14 15:16:45 2008
@@ -0,0 +1,47 @@
+// Copyright 2008 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.
+
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.Link;
+import org.apache.tapestry.internal.structure.Page;
+import org.apache.tapestry.services.Response;
+
+import java.io.IOException;
+
+/**
+ * Simply uses the {@link org.apache.tapestry.internal.services.LinkFactory} to generate a link which is then
+ * {@linkplain org.apache.tapestry.services.Response#sendRedirect(org.apache.tapestry.Link)} sent as a redirect}.
+ */
+public class ActionRenderResponseGeneratorImpl implements ActionRenderResponseGenerator
+{
+    private final LinkFactory _linkFactory;
+
+    private final Response _response;
+
+    public ActionRenderResponseGeneratorImpl(LinkFactory linkFactory, Response response
+
+    )
+    {
+        _linkFactory = linkFactory;
+        _response = response;
+    }
+
+    public void generateResponse(Page page) throws IOException
+    {
+        Link link = _linkFactory.createPageLink(page, false);
+
+        _response.sendRedirect(link);
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CachedPage.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CachedPage.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CachedPage.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CachedPage.java Mon Jan 14 15:16:45 2008
@@ -16,21 +16,24 @@
 
 import org.apache.tapestry.internal.structure.Page;
 
-import java.lang.ref.SoftReference;
-
 /**
- * Tracks the usage of a page instance using a soft reference.  The soft reference will be reclaimed whenever the
- * garbage collector requires it.
+ * Tracks the usage of a page instance, allowing a last access property to be associated with the page. CachedPage
+ * instances are only accessed from within a {@link PagePoolCache}, which handles synchronization concerns.
+ * <p/>
+ * An earlier version of this code used <soft references>, but those seem to be problematic (the test suite started
+ * behaving erratically and response time suffered).  Perhaps that could be addressed via tuning of the VM, but for the
+ * meantime, we use hard references and rely more on the soft and hard limits and the culling of unused pages
+ * periodically.
  */
-public class CachedPage
+class CachedPage
 {
-    private final SoftReference<Page> _ref;
+    private final Page _page;
 
     private long _lastAccess;
 
     CachedPage(Page page)
     {
-        _ref = new SoftReference<Page>(page);
+        _page = page;
     }
 
     /**
@@ -40,7 +43,7 @@
      */
     Page get()
     {
-        return _ref.get();
+        return _page;
     }
 
     /**

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClassResultProcessor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClassResultProcessor.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClassResultProcessor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClassResultProcessor.java Mon Jan 14 15:16:45 2008
@@ -1,31 +1,29 @@
-// Copyright 2007 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.
-
+// Copyright 2007, 2008 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.
+
 package org.apache.tapestry.internal.services;
 
-import org.apache.tapestry.Link;
 import org.apache.tapestry.internal.structure.Page;
 import org.apache.tapestry.runtime.Component;
 import org.apache.tapestry.services.ComponentClassResolver;
 import org.apache.tapestry.services.ComponentEventResultProcessor;
-import org.apache.tapestry.services.Response;
 
 import java.io.IOException;
 
 /**
- * Used when a component event handler returns a class value. The value is interpreted as the page
- * class. A link to the page will be sent.
+ * Used when a component event handler returns a class value. The value is interpreted as the page class. A link to the
+ * page will be sent.
  */
 public class ClassResultProcessor implements ComponentEventResultProcessor<Class>
 {
@@ -33,17 +31,14 @@
 
     private final RequestPageCache _requestPageCache;
 
-    private final LinkFactory _linkFactory;
-
-    private final Response _response;
+    private final ActionRenderResponseGenerator _generator;
 
     public ClassResultProcessor(ComponentClassResolver resolver, RequestPageCache requestPageCache,
-                                LinkFactory linkFactory, Response response)
+                                ActionRenderResponseGenerator generator)
     {
         _resolver = resolver;
         _requestPageCache = requestPageCache;
-        _linkFactory = linkFactory;
-        _response = response;
+        _generator = generator;
     }
 
     public void processComponentEvent(Class value, Component component, String methodDescripion) throws IOException
@@ -53,9 +48,7 @@
 
         Page page = _requestPageCache.get(pageName);
 
-        Link link = _linkFactory.createPageLink(page, false);
-
-        _response.sendRedirect(link);
+        _generator.generateResponse(page);
     }
 
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClasspathAssetFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClasspathAssetFactory.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClasspathAssetFactory.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClasspathAssetFactory.java Mon Jan 14 15:16:45 2008
@@ -25,8 +25,8 @@
 import java.util.Map;
 
 /**
- * Generates Assets for files on the classpath. Caches generated client URLs internally, and clears
- * that cache when notified to do so by the {@link ResourceCache}.
+ * Generates Assets for files on the classpath. Caches generated client URLs internally, and clears that cache when
+ * notified to do so by the {@link ResourceCache}.
  *
  * @see AssetDispatcher
  */
@@ -38,8 +38,7 @@
 
     private final Map<Resource, String> _resourceToClientURL = newConcurrentMap();
 
-    public ClasspathAssetFactory(final ResourceCache cache,
-                                 final ClasspathAssetAliasManager aliasManager)
+    public ClasspathAssetFactory(final ResourceCache cache, final ClasspathAssetAliasManager aliasManager)
     {
         _cache = cache;
         _aliasManager = aliasManager;
@@ -60,7 +59,10 @@
             _resourceToClientURL.put(resource, clientURL);
         }
 
-        return clientURL;
+        // The path generated is partially request-dependent and therefore can't be cached, it will even
+        // vary from request to the next.
+
+        return _aliasManager.toClientURL(clientURL);
     }
 
     private String buildClientURL(Resource resource)
@@ -75,21 +77,14 @@
 
             int lastdotx = path.lastIndexOf('.');
 
-            String revisedPath = path.substring(0, lastdotx + 1) + _cache.getDigest(resource)
-                    + path.substring(lastdotx);
-
-            return _aliasManager.toClientURL(revisedPath);
+            path = path.substring(0, lastdotx + 1) + _cache.getDigest(resource) + path.substring(lastdotx);
         }
 
-        return _aliasManager.toClientURL(path);
+        return path;
     }
 
     public Asset createAsset(final Resource resource)
     {
-        // TODO: Assets will eventually have a kind of symbolic link used
-        // to shorten the path. Some assets may need to have a checksum embedded
-        // in the path as well.
-
         return new Asset()
         {
             public Resource getResource()

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionRequestHandlerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionRequestHandlerImpl.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionRequestHandlerImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionRequestHandlerImpl.java Mon Jan 14 15:16:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 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.
@@ -15,7 +15,6 @@
 package org.apache.tapestry.internal.services;
 
 import org.apache.tapestry.ComponentEventHandler;
-import org.apache.tapestry.Link;
 import org.apache.tapestry.TapestryConstants;
 import org.apache.tapestry.internal.structure.ComponentPageElement;
 import org.apache.tapestry.internal.structure.Page;
@@ -34,17 +33,18 @@
 
     private final RequestPageCache _cache;
 
-    private final LinkFactory _linkFactory;
-
     private final Response _response;
 
+    private final ActionRenderResponseGenerator _generator;
+
     public ComponentActionRequestHandlerImpl(@Traditional ComponentEventResultProcessor resultProcessor,
-                                             RequestPageCache cache, LinkFactory linkFactory, Response response)
+                                             RequestPageCache cache, Response response,
+                                             ActionRenderResponseGenerator generator)
     {
         _resultProcessor = resultProcessor;
         _cache = cache;
-        _linkFactory = linkFactory;
         _response = response;
+        _generator = generator;
     }
 
     public void handle(String logicalPageName, String nestedComponentId, String eventType, String[] context,
@@ -57,6 +57,7 @@
         ComponentPageElement element = page.getComponentElementByNestedId(nestedComponentId);
 
         final Holder<Boolean> holder = Holder.create();
+        final Holder<IOException> exceptionHolder = Holder.create();
 
         ComponentEventHandler handler = new ComponentEventHandler()
         {
@@ -69,7 +70,7 @@
                 }
                 catch (IOException ex)
                 {
-                    throw new RuntimeException(ex);
+                    exceptionHolder.put(ex);
                 }
 
                 holder.put(true);
@@ -83,17 +84,16 @@
 
         page.getRootElement().triggerEvent(TapestryConstants.ACTIVATE_EVENT, activationContext, handler);
 
+        if (exceptionHolder.hasValue()) throw exceptionHolder.get();
+
         if (holder.hasValue()) return;
 
         element.triggerEvent(eventType, context, handler);
 
-        if (holder.hasValue()) return;
+        if (exceptionHolder.hasValue()) throw exceptionHolder.get();
 
-        if (!_response.isCommitted())
-        {
-            Link link = _linkFactory.createPageLink(page, false);
+        if (holder.hasValue()) return;
 
-            _response.sendRedirect(link);
-        }
+        if (!_response.isCommitted()) _generator.generateResponse(page);
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInstanceResultProcessor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInstanceResultProcessor.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInstanceResultProcessor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInstanceResultProcessor.java Mon Jan 14 15:16:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 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.
@@ -15,11 +15,9 @@
 package org.apache.tapestry.internal.services;
 
 import org.apache.tapestry.ComponentResources;
-import org.apache.tapestry.Link;
 import org.apache.tapestry.internal.structure.Page;
 import org.apache.tapestry.runtime.Component;
 import org.apache.tapestry.services.ComponentEventResultProcessor;
-import org.apache.tapestry.services.Response;
 import org.slf4j.Logger;
 
 import java.io.IOException;
@@ -28,19 +26,16 @@
 {
     private final RequestPageCache _requestPageCache;
 
-    private final LinkFactory _linkFactory;
-
     private final Logger _logger;
 
-    private final Response _response;
+    private final ActionRenderResponseGenerator _generator;
 
-    public ComponentInstanceResultProcessor(Logger logger, Response response, RequestPageCache requestPageCache,
-                                            LinkFactory linkFactory)
+    public ComponentInstanceResultProcessor(Logger logger, RequestPageCache requestPageCache,
+                                            ActionRenderResponseGenerator generator)
     {
-        _response = response;
         _requestPageCache = requestPageCache;
-        _linkFactory = linkFactory;
         _logger = logger;
+        _generator = generator;
     }
 
     public void processComponentEvent(Component value, Component component, String methodDescription) throws IOException
@@ -55,8 +50,6 @@
 
         Page page = _requestPageCache.get(resources.getPageName());
 
-        Link link = _linkFactory.createPageLink(page, false);
-
-        _response.sendRedirect(link);
+        _generator.generateResponse(page);
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DefaultRequestExceptionHandler.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DefaultRequestExceptionHandler.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DefaultRequestExceptionHandler.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/DefaultRequestExceptionHandler.java Mon Jan 14 15:16:45 2008
@@ -23,8 +23,8 @@
 import java.io.IOException;
 
 /**
- * Default implementation of {@link RequestExceptionHandler} that displays the standard
- * ExceptionReport page. The page must implement the {@link ExceptionReporter} interface.
+ * Default implementation of {@link RequestExceptionHandler} that displays the standard ExceptionReport page. The page
+ * must implement the {@link ExceptionReporter} interface.
  */
 public class DefaultRequestExceptionHandler implements RequestExceptionHandler
 {
@@ -36,8 +36,8 @@
 
     private final Logger _logger;
 
-    public DefaultRequestExceptionHandler(RequestPageCache pageCache,
-                                          PageResponseRenderer renderer, Response response, Logger logger)
+    public DefaultRequestExceptionHandler(RequestPageCache pageCache, PageResponseRenderer renderer, Response response,
+                                          Logger logger)
     {
         _pageCache = pageCache;
         _renderer = renderer;
@@ -57,6 +57,6 @@
 
         rootComponent.reportException(exception);
 
-        _renderer.renderPageResponse(page, _response);
+        _renderer.renderPageResponse(page);
     }
 }

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ImmediateActionRenderResponseFilter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ImmediateActionRenderResponseFilter.java?rev=611966&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ImmediateActionRenderResponseFilter.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ImmediateActionRenderResponseFilter.java Mon Jan 14 15:16:45 2008
@@ -0,0 +1,69 @@
+// Copyright 2008 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.
+
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.TapestryConstants;
+import org.apache.tapestry.internal.InternalConstants;
+import org.apache.tapestry.internal.structure.Page;
+import org.apache.tapestry.services.ComponentActionRequestFilter;
+import org.apache.tapestry.services.ComponentActionRequestHandler;
+import org.apache.tapestry.services.Request;
+import org.apache.tapestry.services.Response;
+
+import java.io.IOException;
+
+public class ImmediateActionRenderResponseFilter implements ComponentActionRequestFilter
+{
+    private final Request _request;
+
+    private final Response _response;
+
+    private final PageResponseRenderer _renderer;
+
+    public ImmediateActionRenderResponseFilter(Request request, PageResponseRenderer renderer, Response response)
+    {
+        _request = request;
+        _renderer = renderer;
+        _response = response;
+    }
+
+    public void handle(String logicalPageName, String nestedComponentId, String eventType, String[] context,
+                       String[] activationContext, ComponentActionRequestHandler handler) throws IOException
+    {
+        handler.handle(logicalPageName, nestedComponentId, eventType, context, activationContext);
+
+        // If markup or a redirect has already been generated, then we're good.
+
+        if (_response.isCommitted()) return;
+
+        // Otherwise, we should be operating in immediate mode.  Figure out which page
+        // was selected to render.
+
+        Page page = (Page) _request.getAttribute(InternalConstants.IMMEDIATE_RESPONSE_PAGE_ATTRIBUTE);
+
+        if (page != null)
+        {
+            // We don't have a context to provide but this still nags me as not the right thing to do.
+
+            page.getRootElement().triggerEvent(TapestryConstants.ACTIVATE_EVENT, new Object[0], null);
+
+            _renderer.renderPageResponse(page);
+            return;
+        }
+
+        throw new IllegalStateException(
+                "Sanity check - neither a stream response nor a redirect response was generated for this action request.");
+    }
+}

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ImmediateActionRenderResponseGenerator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ImmediateActionRenderResponseGenerator.java?rev=611966&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ImmediateActionRenderResponseGenerator.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ImmediateActionRenderResponseGenerator.java Mon Jan 14 15:16:45 2008
@@ -0,0 +1,54 @@
+// Copyright 2008 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.
+
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.internal.InternalConstants;
+import org.apache.tapestry.internal.structure.Page;
+import org.apache.tapestry.ioc.internal.util.Defense;
+import org.apache.tapestry.services.Request;
+
+import java.io.IOException;
+
+/**
+ * Alternative implementation, used when {@link org.apache.tapestry.TapestryConstants#SUPPRESS_REDIRECT_FROM_ACTION_REQUESTS_SYMBOL}
+ * is set to true.
+ */
+public class ImmediateActionRenderResponseGenerator implements ActionRenderResponseGenerator
+{
+    private final Request _request;
+
+    public ImmediateActionRenderResponseGenerator(Request request)
+    {
+        _request = request;
+    }
+
+    public void generateResponse(Page page) throws IOException
+    {
+        Defense.notNull(page, "page");
+
+        // This can happen when the ComponentActionRequestHandlerImpl notices that the response
+        // is not yet committed, and sets up to render a default response for the page containing
+        // the component.
+        if (_request.getAttribute(InternalConstants.IMMEDIATE_RESPONSE_PAGE_ATTRIBUTE) != null) return;
+
+        // We are somewhere in the middle of processing an action request, possibly something
+        // complicated like a form submission.  Tapestry components are not re-entrant, so we
+        // can't render the request right now, instead we record that we need to render
+        // a response as an attribute, and let a filter on the ComponentActionRequestHandler service
+        // do the work.
+
+        _request.setAttribute(InternalConstants.IMMEDIATE_RESPONSE_PAGE_ATTRIBUTE, page);
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PagePoolCache.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PagePoolCache.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PagePoolCache.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PagePoolCache.java Mon Jan 14 15:16:45 2008
@@ -211,33 +211,14 @@
      */
     private Page findAvailablePage()
     {
-        CachedPage cachedPage = null;
 
-        ListIterator<CachedPage> i = _available.listIterator();
+        if (_available.isEmpty()) return null;
 
-        while (i.hasNext())
-        {
-            cachedPage = i.next();
-
-            // The CachePage should be removed, either because
-            // it is a valid page being moved to the in use list,
-            // or because it the soft reference has been reclaimed
-            // and it is no good to anyone.
-
-            i.remove();
-
-            Page page = cachedPage.get();
+        CachedPage cachedPage = _available.removeFirst();
 
-            if (page != null)
-            {
-                _inUse.addFirst(cachedPage);
-
-                return page;
-            }
+        _inUse.addFirst(cachedPage);
 
-        }
-
-        return null;
+        return cachedPage.get();
     }
 
     /**
@@ -320,7 +301,7 @@
 
     /**
      * Finds any cached pages whose last modified time is beyond the active window, meaning they haven't been used in
-     * some amount of time.  In addition, culls out any CachedPages that have been reclaimed by the garbage collector.
+     * some amount of time., and releases them to the garbage collector.
      */
     void cleanup()
     {
@@ -336,12 +317,6 @@
             while (i.hasNext())
             {
                 CachedPage cached = i.next();
-
-                if (cached.get() == null)
-                {
-                    i.remove();
-                    continue;
-                }
 
                 if (cached.getLastAccess() < cutoff) i.remove();
             }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PagePoolImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PagePoolImpl.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PagePoolImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PagePoolImpl.java Mon Jan 14 15:16:45 2008
@@ -30,8 +30,7 @@
 
 /**
  * Registered as an invalidation listener with the page loader, the component messages source, and the component
- * template source. Any time any of those notice a change, then the entire page pool is wiped. In addition, only soft
- * references to pages are maintained, so when memory gets tight, page instances may be arbitrarily discarded.
+ * template source. Any time any of those notice a change, then the entire page pool is wiped.
  * <p/>
  * The master page pool is, itself, divided into individual sub-pools, one for each combination of
  * <p/>
@@ -147,7 +146,7 @@
     }
 
     /**
-     * Any time templates, classes or messages change, we through out all instances.
+     * Any time templates, classes or messages change, we throw out all instances.
      */
     public synchronized void objectWasInvalidated()
     {

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderRequestHandlerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderRequestHandlerImpl.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderRequestHandlerImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderRequestHandlerImpl.java Mon Jan 14 15:16:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 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.
@@ -27,8 +27,7 @@
 import java.io.IOException;
 
 /**
- * Handles a PageLink as specified by a PageLinkPathSource by activating and then rendering the
- * page.
+ * Handles a PageLink as specified by a PageLinkPathSource by activating and then rendering the page.
  */
 public class PageRenderRequestHandlerImpl implements PageRenderRequestHandler
 {
@@ -50,11 +49,12 @@
         _response = response;
     }
 
-    public void handle(String logicalPageName, String[] context)
+    public void handle(String logicalPageName, String[] context) throws IOException
     {
         Page page = _cache.get(logicalPageName);
 
         final Holder<Boolean> holder = Holder.create();
+        final Holder<IOException> exceptionHolder = Holder.create();
 
         ComponentEventHandler handler = new ComponentEventHandler()
         {
@@ -65,9 +65,9 @@
                 {
                     _resultProcessor.processComponentEvent(result, component, methodDescription);
                 }
-                catch (IOException e)
+                catch (IOException ex)
                 {
-                    throw new RuntimeException(e);
+                    exceptionHolder.put(ex);
                 }
 
                 holder.put(true);
@@ -80,16 +80,10 @@
 
         // The handler will have asked the result processor to send a response.
 
-        if (holder.hasValue()) return;
+        if (exceptionHolder.hasValue()) throw exceptionHolder.get();
 
-        try
-        {
-            _pageResponseRenderer.renderPageResponse(page, _response);
-        }
-        catch (IOException ex)
-        {
-            throw new RuntimeException(ex);
-        }
+        if (holder.hasValue()) return;
 
+        _pageResponseRenderer.renderPageResponse(page);
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRenderer.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRenderer.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRenderer.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRenderer.java Mon Jan 14 15:16:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 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.
@@ -15,7 +15,6 @@
 package org.apache.tapestry.internal.services;
 
 import org.apache.tapestry.internal.structure.Page;
-import org.apache.tapestry.services.Response;
 
 import java.io.IOException;
 
@@ -24,5 +23,5 @@
  */
 public interface PageResponseRenderer
 {
-    void renderPageResponse(Page page, Response response) throws IOException;
+    void renderPageResponse(Page page) throws IOException;
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRendererImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRendererImpl.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRendererImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRendererImpl.java Mon Jan 14 15:16:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 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.
@@ -17,6 +17,7 @@
 import org.apache.tapestry.ContentType;
 import org.apache.tapestry.MarkupWriter;
 import org.apache.tapestry.internal.structure.Page;
+import org.apache.tapestry.ioc.internal.util.Defense;
 import org.apache.tapestry.services.MarkupWriterFactory;
 import org.apache.tapestry.services.Response;
 
@@ -31,16 +32,21 @@
 
     private final PageContentTypeAnalyzer _pageContentTypeAnalyzer;
 
+    private final Response _response;
+
     public PageResponseRendererImpl(MarkupWriterFactory markupWriterFactory, PageMarkupRenderer markupRenderer,
-                                    PageContentTypeAnalyzer pageContentTypeAnalyzer)
+                                    PageContentTypeAnalyzer pageContentTypeAnalyzer, Response response)
     {
         _markupWriterFactory = markupWriterFactory;
         _markupRenderer = markupRenderer;
         _pageContentTypeAnalyzer = pageContentTypeAnalyzer;
+        _response = response;
     }
 
-    public void renderPageResponse(Page page, Response response) throws IOException
+    public void renderPageResponse(Page page) throws IOException
     {
+        Defense.notNull(page, "page");
+
         ContentType contentType = _pageContentTypeAnalyzer.findContentType(page);
 
         // For the moment, the content type is all that's used determine the model for the markup writer.
@@ -50,7 +56,7 @@
 
         _markupRenderer.renderPageMarkup(page, writer);
 
-        PrintWriter pw = response.getPrintWriter(contentType.toString());
+        PrintWriter pw = _response.getPrintWriter(contentType.toString());
 
         writer.toMarkup(pw);
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ResponseRendererImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ResponseRendererImpl.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ResponseRendererImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ResponseRendererImpl.java Mon Jan 14 15:16:45 2008
@@ -56,6 +56,6 @@
     {
         Page page = _pageCache.get(pageName);
 
-        _renderer.renderPageResponse(page, _response);
+        _renderer.renderPageResponse(page);
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/StringResultProcessor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/StringResultProcessor.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/StringResultProcessor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/StringResultProcessor.java Mon Jan 14 15:16:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 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.
@@ -14,40 +14,33 @@
 
 package org.apache.tapestry.internal.services;
 
-import org.apache.tapestry.Link;
 import org.apache.tapestry.internal.structure.Page;
 import org.apache.tapestry.runtime.Component;
 import org.apache.tapestry.services.ComponentEventResultProcessor;
-import org.apache.tapestry.services.Response;
 
 import java.io.IOException;
 
 /**
- * Used when a component event handler returns a string value. The value is interpreted as the
- * logical name of a page. A link to the page will be sent as a redirect.
+ * Used when a component event handler returns a string value. The value is interpreted as the logical name of a page. A
+ * link to the page will be sent as a redirect.
  */
 public class StringResultProcessor implements ComponentEventResultProcessor<String>
 {
     private final RequestPageCache _requestPageCache;
 
-    private final LinkFactory _linkFactory;
+    private final ActionRenderResponseGenerator _generator;
 
-    private final Response _response;
-
-    public StringResultProcessor(RequestPageCache requestPageCache, LinkFactory linkFactory, Response response)
+    public StringResultProcessor(RequestPageCache requestPageCache, ActionRenderResponseGenerator generator)
     {
         _requestPageCache = requestPageCache;
-        _linkFactory = linkFactory;
-        _response = response;
+        _generator = generator;
     }
 
     public void processComponentEvent(String value, Component component, String methodDescripion) throws IOException
     {
         Page page = _requestPageCache.get(value);
 
-        Link link = _linkFactory.createPageLink(page, false);
-
-        _response.sendRedirect(link);
+        _generator.generateResponse(page);
     }
 
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java Mon Jan 14 15:16:45 2008
@@ -470,8 +470,8 @@
     }
 
     /**
-     * Reads the content of a file into a string. Each line is trimmed of line separators and
-     * leading/trailing whitespace.
+     * Reads the content of a file into a string. Each line is trimmed of line separators and leading/trailing
+     * whitespace.
      *
      * @param trim trim each line of whitespace
      */
@@ -567,5 +567,10 @@
     protected final void train_optimizePath(RequestPathOptimizer optimizer, String path, String optimizedPath)
     {
         expect(optimizer.optimizePath(path)).andReturn(optimizedPath);
+    }
+
+    protected final ActionRenderResponseGenerator mockActionRenderResponseGenerator()
+    {
+        return newMock(ActionRenderResponseGenerator.class);
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/PageLinkInvoker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/PageLinkInvoker.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/PageLinkInvoker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/PageLinkInvoker.java Mon Jan 14 15:16:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 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.
@@ -21,6 +21,8 @@
 import org.apache.tapestry.ioc.Registry;
 import org.apache.tapestry.services.PageRenderRequestHandler;
 
+import java.io.IOException;
+
 /**
  * Simulates a click on a page link.
  */
@@ -60,12 +62,17 @@
 
             return _markupWriterFactory.getLatestMarkupWriter().getDocument();
         }
+        catch (IOException ex)
+        {
+            throw new RuntimeException(ex);
+        }
         finally
         {
             _response.clear();
 
             _registry.cleanupThread();
         }
+
     }
 
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PageRenderRequestHandler.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PageRenderRequestHandler.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PageRenderRequestHandler.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PageRenderRequestHandler.java Mon Jan 14 15:16:45 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 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.
@@ -14,6 +14,8 @@
 
 package org.apache.tapestry.services;
 
+import java.io.IOException;
+
 /**
  * Handles a invocation related to rendering out a pages complete content.
  *
@@ -22,12 +24,12 @@
 public interface PageRenderRequestHandler
 {
     /**
-     * Invoked to activate and render a page. In certain cases, based on values returned when
-     * activating the page, a {@link org.apache.tapestry.services.ComponentEventResultProcessor} may be used
-     * to send an alternate response (typically, a redirect).
+     * Invoked to activate and render a page. In certain cases, based on values returned when activating the page, a
+     * {@link org.apache.tapestry.services.ComponentEventResultProcessor} may be used to send an alternate response
+     * (typically, a redirect).
      *
      * @param logicalPageName the logical name of the page to activate and render
      * @param context         context data, supplied by the page at render time, extracted from the render URL
      */
-    void handle(String logicalPageName, String[] context);
+    void handle(String logicalPageName, String[] context) throws IOException;
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java Mon Jan 14 15:16:45 2008
@@ -154,7 +154,9 @@
 
                                                FieldValidatorSource fieldValidatorSource,
 
-                                               TranslatorSource translatorSource)
+                                               TranslatorSource translatorSource,
+
+                                               ObjectLocator locator)
     {
         configuration.add(TapestryConstants.LITERAL_BINDING_PREFIX, new LiteralBindingFactory());
         configuration.add(TapestryConstants.PROP_BINDING_PREFIX, propBindingFactory);
@@ -164,7 +166,7 @@
         configuration.add("validate", new ValidateBindingFactory(fieldValidatorSource));
         configuration.add("translate", new TranslateBindingFactory(translatorSource));
         configuration.add("block", new BlockBindingFactory());
-        configuration.add("asset", new AssetBindingFactory(assetSource));
+        configuration.add("asset", locator.autobuild(AssetBindingFactory.class));
         configuration.add("var", new RenderVariableBindingFactory());
     }
 
@@ -222,9 +224,7 @@
 
             RequestPageCache requestPageCache,
 
-            BindingSource bindingsource,
-
-            ApplicationStateManager applicationStateManager)
+            BindingSource bindingsource)
     {
         // TODO: Proper scheduling of all of this. Since a given field or method should
         // only have a single annotation, the order doesn't matter so much, as long as
@@ -690,6 +690,8 @@
 
     private final RequestGlobals _requestGlobals;
 
+    private final ActionRenderResponseGenerator _actionRenderResponseGenerator;
+
     public TapestryModule(PipelineBuilder pipelineBuilder,
 
                           PropertyShadowBuilder shadowBuilder,
@@ -722,7 +724,9 @@
 
                           Response response,
 
-                          ThreadLocale threadLocale)
+                          ThreadLocale threadLocale,
+
+                          ActionRenderResponseGenerator actionRenderResponseGenerator)
     {
         _pipelineBuilder = pipelineBuilder;
         _shadowBuilder = shadowBuilder;
@@ -743,6 +747,7 @@
         _request = request;
         _response = response;
         _threadLocale = threadLocale;
+        _actionRenderResponseGenerator = actionRenderResponseGenerator;
     }
 
     public Context build(ApplicationGlobals globals)
@@ -1104,10 +1109,10 @@
             }
         });
 
-        configuration.add(String.class, new StringResultProcessor(_requestPageCache, _linkFactory, _response));
+        configuration.add(String.class, new StringResultProcessor(_requestPageCache, _actionRenderResponseGenerator));
 
-        configuration.add(Class.class,
-                          new ClassResultProcessor(componentClassResolver, _requestPageCache, _linkFactory, _response));
+        configuration.add(Class.class, new ClassResultProcessor(componentClassResolver, _requestPageCache,
+                                                                _actionRenderResponseGenerator));
 
         configuration.add(Component.class, componentInstanceProcessor);
 
@@ -1615,7 +1620,7 @@
         configuration.add("tapestry.file-check-update-timeout", "50 ms");
 
         // This should be overridden for particular applications.
-        configuration.add("tapestry.supported-locales", "en,it,zh_CN");
+        configuration.add(TapestryConstants.SUPPORTED_LOCALES_SYMBOL, "en,it,zh_CN");
 
         configuration.add("tapestry.default-cookie-max-age", "7 d");
 
@@ -1628,19 +1633,21 @@
         configuration.add("tapestry.page-pool.hard-limit", "20");
         configuration.add("tapestry.page-pool.active-window", "10 m");
 
+        configuration.add(TapestryConstants.SUPPRESS_REDIRECT_FROM_ACTION_REQUESTS_SYMBOL, "false");
+
         configuration.add(TapestryConstants.FORCE_FULL_URIS_SYMBOL, "false");
 
-// This is designed to make it easy to keep synchronized with script.aculo.ous. As we
-// support a new version, we create a new folder, and update the path entry. We can then
-// delete the old version folder (or keep it around). This should be more manageable than
-// overwriting the local copy with updates (it's too easy for files deleted between scriptaculous
-// releases to be accidentally left lying around). There's also a ClasspathAliasManager
-// contribution based on the path.
+        // This is designed to make it easy to keep synchronized with script.aculo.ous. As we
+        // support a new version, we create a new folder, and update the path entry. We can then
+        // delete the old version folder (or keep it around). This should be more manageable than
+        // overwriting the local copy with updates (it's too easy for files deleted between scriptaculous
+        // releases to be accidentally left lying around). There's also a ClasspathAliasManager
+        // contribution based on the path.
 
         configuration.add("tapestry.scriptaculous", "classpath:${tapestry.scriptaculous.path}");
         configuration.add("tapestry.scriptaculous.path", "org/apache/tapestry/scriptaculous_1_8");
 
-// Likewise for jscalendar, currently version 1.0
+        // Likewise for jscalendar, currently version 1.0
 
         configuration.add("tapestry.jscalendar.path", "org/apache/tapestry/jscalendar-1.0");
         configuration.add("tapestry.jscalendar", "classpath:${tapestry.jscalendar.path}");
@@ -1997,9 +2004,17 @@
         return service;
     }
 
+    /**
+     * Contributes filters: <dl> <dt>SetRequestEncode</dt> <dd>Sets the request encoding (before:*)</dd> <dt>Ajax</dt>
+     * <dd>Determines if the request is Ajax oriented, and redirects to an alternative handler if so</dd>
+     * <dt>ImmediateRender</dt> <dd>When {@linkplain org.apache.tapestry.TapestryConstants#SUPPRESS_REDIRECT_FROM_ACTION_REQUESTS_SYMBOL
+     * immediate action response rendering} is enabled, generates the markup response (instead of a page redirect
+     * response, which is the normal behavior) </dd> </dl>
+     */
     public void contributeComponentActionRequestHandler(
             OrderedConfiguration<ComponentActionRequestFilter> configuration,
-            final RequestEncodingInitializer encodingInitializer, @Ajax ComponentActionRequestHandler ajaxHandler)
+            final RequestEncodingInitializer encodingInitializer, @Ajax ComponentActionRequestHandler ajaxHandler,
+            ObjectLocator locator)
     {
         ComponentActionRequestFilter requestEncodingFilter = new ComponentActionRequestFilter()
         {
@@ -2016,6 +2031,8 @@
         configuration.add("SetRequestEncoding", requestEncodingFilter, "before:*");
 
         configuration.add("Ajax", new AjaxFilter(_request, ajaxHandler));
+
+        configuration.add("ImmediateRender", locator.autobuild(ImmediateActionRenderResponseFilter.class));
     }
 
     public ComponentClassCache buildComponentClassCache(@ComponentLayer ClassFactory classFactory)
@@ -2025,5 +2042,20 @@
         _componentInstantiatorSource.addInvalidationListener(service);
 
         return service;
+    }
+
+    /**
+     * Chooses one of two implementations, based on the configured mode.
+     */
+    public ActionRenderResponseGenerator buildActionRenderResponseGenerator(
+
+            @Symbol(TapestryConstants.SUPPRESS_REDIRECT_FROM_ACTION_REQUESTS_SYMBOL)
+            boolean immediateMode,
+
+            ObjectLocator locator)
+    {
+        if (immediateMode) return locator.autobuild(ImmediateActionRenderResponseGenerator.class);
+
+        return locator.autobuild(ActionRenderResponseGeneratorImpl.class);
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/conf.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/conf.apt?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/conf.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/conf.apt Mon Jan 14 15:16:45 2008
@@ -123,7 +123,8 @@
 
   [tapestry.scriptaculous]
     The path to the embedded copy of {{{http://script.aculo.us/}script.aculo.us}} packaged with Tapestry. This value may be overridden
-    to use a different version of the script.aculo.us library. Tapestry's default version is 1.7.0 (including Prototype 1.5.0).
+    to use a different version of the script.aculo.us library. Tapestry's default version is 1.8.0
+    (including Prototype 1.6.0).
 
   [tapestry.page-pool.active-window]
     The time interval that an instantiated page instance may be cached before being removed. As pages are
@@ -156,9 +157,6 @@
     The time interval that Tapestry will wait for a page instance to come available before deciding whether to create
     a new instance.  The default is "10 ms".
 
-
-
-
   [tapestry.start-page-name]
     The logical name of the start page, the page that is rendered for the <root URL>.  This is normally "start".
     
@@ -170,3 +168,14 @@
     The default is (currently) "en,it,zn_CH".  As the community contributes new localizations of the necessary messages files,
     this list will expand.  Note that the Tapestry quickstart archetype overrides the factory default, forcing the
     application to be localized only for "en".
+
+  [tapestry.suppress-redirect-from-action-requests]
+    Normally, Tapestry responds to action requests (such as form submissions) by sending a client-side redirect
+    to the renderring page.  This has a lot of benefits in terms of improving browser navigation, making sure
+    URLs are bookmarkable, and so forth.  However, it has a cost: more data stored persistently in the session,
+    and a double-request for each user action (one action request, one render request).
+
+    Setting this symbol to "true" changes the Tapestry behavior to make it more like Tapestry 4: a markup response
+    is sent directly for the action request, no redirect in the middle. This option should be used with care,
+    and only in cases where you are certain that the benefits outweigh the disadvantages.
+

Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/lifecycle.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/lifecycle.apt?rev=611966&r1=611965&r2=611966&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/lifecycle.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/lifecycle.apt Mon Jan 14 15:16:45 2008
@@ -36,6 +36,14 @@
    The end result is that all pages in the pool are entirely equivalent to each other; it doesn't matter which
    instance is used for processing any particular request.
 
+   Remember that the page instance is just the tip of the iceberg: a page instance encompasses the page component,
+   its templates, all of its parameter bindings, tokens read from its template and (recursively) the same
+   thing for all components inside the page. It adds up.
+
+   A page instance will be "checked out" of the pool for a short period of time: a few milliseconds
+   to service a typical request. Because of this, it is generally the case that Tapestry
+   can handle a large number of end users with a relatively small pool of page instances.
+
 Comparison to JavaServer Pages
 
    JSPs also use a caching mechanism; the JSP itself is compiled into a Java servlet class, and acts as a singleton.
@@ -72,7 +80,7 @@
      attached to the request.
 
    * If the soft limit has been reached, Tapestry will wait for a short period of time for
-     a page instance to become available.
+     a page instance to become available before creating a new page instance.
 
    * If the hard limit has been reached, Tapestry will throw an exception rather than create a new page instance.
 
@@ -88,19 +96,20 @@
    hard limit is reached.
 
    Remember that all these configuration values are  per key: the combination of page name and locale.
-   Thus even with a hard limit of 20, you may have 20 start page instances for locale en and 20 start page
-   instances for locale fr (if you application is configured to support English and French).  Likewise,
+   Thus even with a hard limit of 20, you may eventually find that Tapestry
+   has created 20 start page instances for locale "en" <and> 20 start page
+   instances for locale "fr" (if your application is configured to support both English and French).  Likewise,
    you may have 20 instances for the start page, and 20 instances for the newaccount page.
 
-   Pooled pages are stored using <soft references>; this means that the garbage collector is free to reclaim
-   a page instance (that isn't actively being used) at any time. Further, Tapestry will release
-   page instances that haven't been used recently.
+   Tapestry periodically checks its cache for page instances that have not been used recently
+   (within a configurable window).  Unused page instances are release to the garbage collector.
 
    The end result is that you have quite a degree of tuning control over the process.  If memory is a limitation
    and throughput can be sacrificed, try lowering the soft and hard limit and increasing the soft wait.
 
    If performance is absolute and you have lots of memory, then increase the soft and hard limit and reduce 
-   the soft wait.
+   the soft wait.  This encourages Tapestry to create more page instances and not wait as long to re-use
+   existing instances.
 
 Page Lifecycle Methods
 

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/app4/Destination.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app4/Destination.tml?rev=611966&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app4/Destination.tml (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app4/Destination.tml Mon Jan 14 15:16:45 2008
@@ -0,0 +1,27 @@
+<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+    <head>
+        <title>Destination</title>
+    </head>
+
+    <body>
+
+
+        <dl>
+            <dt>message</dt>
+            <dd>${message}</dd>
+
+            <dt>value</dt>
+            <dd>${value}</dd>
+        </dl>
+
+        <hr/>
+
+        <t:pagelink page="destination">refresh page</t:pagelink>
+
+        <hr/>
+
+        <t:actionlink>refresh via action</t:actionlink>
+
+    </body>
+
+</html>
\ No newline at end of file

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/app4/Start.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app4/Start.tml?rev=611966&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app4/Start.tml (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app4/Start.tml Mon Jan 14 15:16:45 2008
@@ -0,0 +1,21 @@
+<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+    <head>
+        <title>Start</title>
+    </head>
+
+    <body>
+
+        <h1>Start</h1>
+
+        <t:beaneditform object="this"/>
+
+        <hr/>
+
+        <p>
+            Click
+            <t:actionlink t:id="bypass">here</t:actionlink>
+            to bypass the form.
+        </p>
+    </body>
+
+</html>
\ No newline at end of file

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/app4/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app4/WEB-INF/web.xml?rev=611966&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app4/WEB-INF/web.xml (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app4/WEB-INF/web.xml Mon Jan 14 15:16:45 2008
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2008 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.
+-->
+
+<!DOCTYPE web-app
+        PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+        "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+    <display-name>Integration Test App 4</display-name>
+    <context-param>
+        <param-name>tapestry.app-package</param-name>
+        <param-value>org.apache.tapestry.integration.app4</param-value>
+    </context-param>
+    <filter>
+        <filter-name>app</filter-name>
+        <filter-class>org.apache.tapestry.TapestryFilter</filter-class>
+    </filter>
+    <filter-mapping>
+        <filter-name>app</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>
+</web-app>

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/ImmediateModeTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/ImmediateModeTests.java?rev=611966&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/ImmediateModeTests.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/ImmediateModeTests.java Mon Jan 14 15:16:45 2008
@@ -0,0 +1,76 @@
+// Copyright 2008 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.
+
+package org.apache.tapestry.integration;
+
+import org.apache.tapestry.test.AbstractIntegrationTestSuite;
+import org.testng.annotations.Test;
+
+/**
+ * Tests for immediate mode (aka T4 mode, aka {@linkplain org.apache.tapestry.TapestryConstants#SUPPRESS_REDIRECT_FROM_ACTION_REQUESTS_SYMBOL
+ * redirects suppressed} mode).
+ */
+@Test(timeOut = 50000, sequential = true, groups = {"integration"})
+public class ImmediateModeTests extends AbstractIntegrationTestSuite
+{
+    public ImmediateModeTests()
+    {
+        super("src/test/app4");
+    }
+
+    @Test
+    public void action_link()
+    {
+        start("here");
+
+        assertTextSeries("//dd[%d]", 1, "onActivate() invoked", "automatic value");
+
+        clickAndWait("link=refresh page");
+
+        assertTextSeries("//dd[%d]", 1, "onActivate(String) invoked - onActivate() invoked", "automatic value");
+
+        clickAndWait("link=refresh via action");
+
+        // The last onActivate() is due to the "default" rendering of the page for the action link (on the same page).
+
+        assertTextSeries("//dd[%d]", 1, "onActivate(String) invoked - onActivate() invoked - onActivate() invoked",
+                         "automatic value");
+    }
+
+    @Test
+    public void form_submission()
+    {
+        open(BASE_URL);
+
+        type("input", "immediate mode");
+
+        clickAndWait(SUBMIT);
+
+        assertTextSeries("//dd[%d]", 1, "onActivate() invoked", "immediate mode");
+
+        clickAndWait("link=refresh page");
+
+        assertTextSeries("//dd[%d]", 1, "onActivate(String) invoked - onActivate() invoked", "immediate mode");
+
+        clickAndWait("link=refresh via action");
+
+        // The last onActivate() is due to the "default" rendering of the page for the action link (on the same page).
+
+        assertTextSeries("//dd[%d]", 1, "onActivate(String) invoked - onActivate() invoked - onActivate() invoked",
+                         "immediate mode");
+
+    }
+
+
+}

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app4/pages/Destination.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app4/pages/Destination.java?rev=611966&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app4/pages/Destination.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app4/pages/Destination.java Mon Jan 14 15:16:45 2008
@@ -0,0 +1,67 @@
+// Copyright 2008 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.
+
+package org.apache.tapestry.integration.app4.pages;
+
+public class Destination
+{
+    private String _message;
+
+    private String _value;
+
+    public String getMessage()
+    {
+        return _message;
+    }
+
+    public String getValue()
+    {
+        return _value;
+    }
+
+    public void setValue(String value)
+    {
+        _value = value;
+    }
+
+    String onPassivate()
+    {
+        return _value;
+    }
+
+    void onActivate(String value)
+    {
+        addMessage("onActivate(String) invoked");
+
+        _value = value;
+    }
+
+    void onActivate()
+    {
+        addMessage("onActivate() invoked");
+    }
+
+    private void addMessage(String text)
+    {
+        if (_message == null)
+        {
+            _message = text;
+            return;
+        }
+
+        _message += " - " + text;
+    }
+
+
+}