You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2008/02/23 03:36:17 UTC

svn commit: r630378 - in /tapestry/tapestry5/trunk/tapestry-core/src: main/java/org/apache/tapestry/ main/java/org/apache/tapestry/internal/ main/java/org/apache/tapestry/internal/services/ main/java/org/apache/tapestry/internal/structure/ main/java/or...

Author: hlship
Date: Fri Feb 22 18:36:14 2008
New Revision: 630378

URL: http://svn.apache.org/viewvc?rev=630378&view=rev
Log:
TAPESTRY-1475: Tapestry is missing an API for clearing out persistent properties of a particular pag

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManager.java
      - copied, changed from r630031, tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PersistentFieldManager.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PersistentDemo.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PersistentDemo.java
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/ComponentResources.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStrategy.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderProcessor.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManagerImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/InternalComponentResourcesImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/Page.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/PageImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PersistentFieldStrategy.java
    tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/persist.apt
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/PersistentFieldManagerImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategyTest.java

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/ComponentResources.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/ComponentResources.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/ComponentResources.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/ComponentResources.java Fri Feb 22 18:36:14 2008
@@ -174,4 +174,11 @@
      *                 target paget
      */
     Link createPageLink(String pageName, boolean override, Object... context);
+
+    /**
+     * Discards all persistent field changes for the page containing the component.  Changes are eliminated from
+     * persistent storage (such as the {@link org.apache.tapestry.services.Session}) which will take effect in the
+     * <em>next</em> request (the attached page instance is not affected).
+     */
+    void discardPersistentFieldChanges();
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalComponentResources.java Fri Feb 22 18:36:14 2008
@@ -15,13 +15,13 @@
 package org.apache.tapestry.internal;
 
 import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.internal.services.PersistentFieldManager;
 import org.apache.tapestry.internal.structure.Page;
 import org.apache.tapestry.runtime.RenderQueue;
-import org.apache.tapestry.services.PersistentFieldManager;
 
 /**
- * An extension of {@link org.apache.tapestry.ComponentResources} that represents additional methods
- * that are private to the framework and not exposed in any public APIs.
+ * An extension of {@link org.apache.tapestry.ComponentResources} that represents additional methods that are private to
+ * the framework and not exposed in any public APIs.
  */
 public interface InternalComponentResources extends ComponentResources, InternalComponentResourcesCommon
 {
@@ -39,10 +39,9 @@
     boolean hasFieldChange(String fieldName);
 
     /**
-     * Posts a change to a persistent field. If the component is still loading, then this change is
-     * ignored. Otherwise, it is propagated, via the
-     * {@link Page#persistFieldChange(org.apache.tapestry.ComponentResources, String, Object) page}
-     * to the {@link PersistentFieldManager}.
+     * Posts a change to a persistent field. If the component is still loading, then this change is ignored. Otherwise,
+     * it is propagated, via the {@link Page#persistFieldChange(org.apache.tapestry.ComponentResources, String, Object)
+     * page} to the {@link PersistentFieldManager}.
      */
     void persistFieldChange(String fieldName, Object newValue);
 
@@ -60,15 +59,15 @@
      * Used by generated component code to read a parameter value.
      *
      * @param parameterName   the name of the parameter to read
-     * @param desiredTypeName the class name of the desired value (classes will be resolved in the
-     *                        component class loader)
+     * @param desiredTypeName the class name of the desired value (classes will be resolved in the component class
+     *                        loader)
      * @return the value coerced to the correct type
      */
     Object readParameter(String parameterName, String desiredTypeName);
 
     /**
-     * Updates a parameter. It is an error to update a parameter which is not bound. The parameter
-     * {@link org.apache.tapestry.Binding binding} may also not support updates.
+     * Updates a parameter. It is an error to update a parameter which is not bound. The parameter {@link
+     * org.apache.tapestry.Binding binding} may also not support updates.
      *
      * @param <T>
      * @param parameterName  of parameter to update
@@ -77,9 +76,8 @@
     <T> void writeParameter(String parameterName, T parameterValue);
 
     /**
-     * Returns true if the named parameter's {@link org.apache.tapestry.Binding} is invariant, false
-     * if otherwise, or if the parameter is not bound. Invariant bindings are cached more
-     * aggressively than variant bindings.
+     * Returns true if the named parameter's {@link org.apache.tapestry.Binding} is invariant, false if otherwise, or if
+     * the parameter is not bound. Invariant bindings are cached more aggressively than variant bindings.
      *
      * @param parameterName the name of parameter to check for invariance
      * @return true if the binding is an invariant, false if the binding has no fixed value

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java Fri Feb 22 18:36:14 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.
@@ -26,8 +26,8 @@
 import java.util.List;
 
 /**
- * Base class for strategies that store their values as keys in the session. Implements a uniform
- * format for the keys, based on a prefix to identify the particular strategy.
+ * Base class for strategies that store their values as keys in the session. Implements a uniform format for the keys,
+ * based on a prefix to identify the particular strategy.
  */
 public abstract class AbstractSessionPersistentFieldStrategy implements PersistentFieldStrategy
 {
@@ -63,9 +63,23 @@
         return result;
     }
 
+    public void discardChanges(String pageName)
+    {
+        Session session = _request.getSession(false);
+
+        if (session == null) return;
+
+        String fullPrefix = _prefix + pageName + ":";
+
+        for (String name : session.getAttributeNames(fullPrefix))
+        {
+            session.setAttribute(name, null);
+        }
+    }
+
     /**
-     * Called after each key is read by {@link #gatherFieldChanges(String)}. This implementation
-     * does nothing, subclasses may override.
+     * Called after each key is read by {@link #gatherFieldChanges(String)}. This implementation does nothing,
+     * subclasses may override.
      *
      * @param session       the session from which a value was just read
      * @param attributeName the name of the attribute used to read a value

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImpl.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImpl.java Fri Feb 22 18:36:14 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.
@@ -32,9 +32,9 @@
 import java.util.Map;
 
 /**
- * Manages client-persistent values on behalf of a {@link ClientPersistentFieldStorageImpl}. Some
- * effort is made to ensure that we don't uncessarily convert between objects and Base64 (the
- * encoding used to record the value on the client).
+ * Manages client-persistent values on behalf of a {@link ClientPersistentFieldStorageImpl}. Some effort is made to
+ * ensure that we don't uncessarily convert between objects and Base64 (the encoding used to record the value on the
+ * client).
  */
 @Scope(PERTHREAD_SCOPE)
 public class ClientPersistentFieldStorageImpl implements ClientPersistentFieldStorage
@@ -150,6 +150,24 @@
         return result;
     }
 
+    public void discardChanges(String pageName)
+    {
+        refreshMap();
+
+        Collection<Key> removedKeys = CollectionFactory.newList();
+
+        for (Key key : _persistedValues.keySet())
+        {
+            if (key._pageName.equals(pageName)) removedKeys.add(key);
+        }
+
+        for (Key key : removedKeys)
+        {
+            _persistedValues.remove(key);
+            _clientData = null;
+        }
+    }
+
     public void postChange(String pageName, String componentId, String fieldName, Object newValue)
     {
         refreshMap();
@@ -170,6 +188,9 @@
         _clientData = null;
     }
 
+    /**
+     * Refreshes the _persistedValues map if it is not up to date.
+     */
     @SuppressWarnings("unchecked")
     private void refreshMap()
     {
@@ -182,6 +203,9 @@
         _mapUptoDate = true;
     }
 
+    /**
+     * Restores the _persistedValues map from the client data provided in the incoming Request.
+     */
     private void restoreMapFromClientData()
     {
         _persistedValues.clear();

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStrategy.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStrategy.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStrategy.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ClientPersistentFieldStrategy.java Fri Feb 22 18:36:14 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.
@@ -21,10 +21,9 @@
 import java.util.Collection;
 
 /**
- * Implements simple client-persistent properties. Most of the logic is delegated to an instance of
- * {@link ClientPersistentFieldStorage}. This division of layer allows this service to be a true
- * singleton, and a listener to the {@link LinkFactory}, and allow per-request state to be isolated
- * inside the other service.
+ * Implements simple client-persistent properties. Most of the logic is delegated to an instance of {@link
+ * ClientPersistentFieldStorage}. This division of layer allows this service to be a true singleton, and a listener to
+ * the {@link LinkFactory}, and allow per-request state to be isolated inside the other service.
  */
 public class ClientPersistentFieldStrategy implements PersistentFieldStrategy, LinkFactoryListener
 {
@@ -53,5 +52,10 @@
     public void createdPageLink(Link link)
     {
         _storage.updateLink(link);
+    }
+
+    public void discardChanges(String pageName)
+    {
+        _storage.discardChanges(pageName);
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java Fri Feb 22 18:36:14 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.
@@ -18,12 +18,11 @@
 import org.apache.tapestry.internal.events.InvalidationListener;
 import org.apache.tapestry.internal.structure.Page;
 import org.apache.tapestry.services.ComponentClassResolver;
-import org.apache.tapestry.services.PersistentFieldManager;
 
 import java.util.Locale;
 
 public class PageLoaderImpl extends InvalidationEventHubImpl implements PageLoader,
-                                                                        InvalidationListener
+        InvalidationListener
 {
     private final ComponentTemplateSource _templateSource;
 
@@ -61,8 +60,8 @@
     }
 
     /**
-     * When the page loader receives an invalidation event, it respawns the event for its listeners.
-     * Those listeners will include page caches and the like.
+     * When the page loader receives an invalidation event, it respawns the event for its listeners. Those listeners
+     * will include page caches and the like.
      */
     public void objectWasInvalidated()
     {

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderProcessor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderProcessor.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderProcessor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderProcessor.java Fri Feb 22 18:36:14 2008
@@ -34,7 +34,6 @@
 import org.apache.tapestry.model.EmbeddedComponentModel;
 import org.apache.tapestry.runtime.RenderQueue;
 import org.apache.tapestry.services.BindingSource;
-import org.apache.tapestry.services.PersistentFieldManager;
 import org.slf4j.Logger;
 
 import java.util.List;

Copied: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManager.java (from r630031, tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PersistentFieldManager.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManager.java?p2=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManager.java&p1=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PersistentFieldManager.java&r1=630031&r2=630378&rev=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PersistentFieldManager.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManager.java Fri Feb 22 18:36:14 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.
@@ -12,15 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.services;
+package org.apache.tapestry.internal.services;
 
 import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.services.PersistentFieldBundle;
 
 /**
- * Handle persistent property changes. Primarily, delegates to a number of
- * {@link PersistentFieldStrategy} instances.
+ * Handle persistent property changes. Primarily, delegates to a number of {@link org.apache.tapestry.services.PersistentFieldStrategy}
+ * instances.
  *
- * @see org.apache.tapestry.services.TapestryModule#contributePersistentFieldManager(org.apache.tapestry.ioc.MappedConfiguration, Request, PersistentFieldStrategy)
+ * @see org.apache.tapestry.services.TapestryModule#contributePersistentFieldManager(org.apache.tapestry.ioc.MappedConfiguration,
+ *      org.apache.tapestry.services.Request , org.apache.tapestry.services.PersistentFieldStrategy)
  */
 public interface PersistentFieldManager
 {
@@ -28,19 +30,26 @@
      * Posts a change of a persistent property.
      *
      * @param pageName  the logical name of the page containing the component
-     * @param resources the resources for the component or mixin (used to determine the persistence
-     *                  strategy)
+     * @param resources the resources for the component or mixin (used to determine the persistence strategy)
      * @param fieldName the name of the field whose persistent value has changed
      * @param newValue  the new value for the field, possibly null
      */
     void postChange(String pageName, ComponentResources resources, String fieldName, Object newValue);
 
     /**
-     * Locates all persistently stored changes to all properties within the page (for the current
-     * session and request) and gathers them together into a bundle.
+     * Locates all persistently stored changes to all properties within the page (for the current session and request)
+     * and gathers them together into a bundle.
      *
      * @param pageName the logical name of the page to gather changes for
      * @return a bundle identifying all such changes
      */
     PersistentFieldBundle gatherChanges(String pageName);
+
+    /**
+     * Discards all changes for the indicated page. This will not affect pages that have already been attached to this
+     * request, but will affect subsequent page attachments in this and later requests.
+     *
+     * @param pageName logical name of page whose persistent field data is to be discarded
+     */
+    void discardChanges(String pageName);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManagerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManagerImpl.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManagerImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PersistentFieldManagerImpl.java Fri Feb 22 18:36:14 2008
@@ -18,7 +18,10 @@
 import org.apache.tapestry.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
 import org.apache.tapestry.model.ComponentModel;
-import org.apache.tapestry.services.*;
+import org.apache.tapestry.services.MetaDataLocator;
+import org.apache.tapestry.services.PersistentFieldBundle;
+import org.apache.tapestry.services.PersistentFieldChange;
+import org.apache.tapestry.services.PersistentFieldStrategy;
 
 import java.util.Collection;
 import java.util.Map;
@@ -63,6 +66,14 @@
         }
 
         return new PersistentFieldBundleImpl(allChanges);
+    }
+
+    public void discardChanges(String pageName)
+    {
+        for (PersistentFieldStrategy strategy : _strategies.values())
+        {
+            strategy.discardChanges(pageName);
+        }
     }
 
     public void postChange(String pageName, ComponentResources resources, String fieldName,

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/InternalComponentResourcesImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/InternalComponentResourcesImpl.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/InternalComponentResourcesImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/InternalComponentResourcesImpl.java Fri Feb 22 18:36:14 2008
@@ -128,6 +128,11 @@
         return _page.createPageLink(pageName, override, context);
     }
 
+    public void discardPersistentFieldChanges()
+    {
+        _page.discardPersistentFieldChanges();
+    }
+
 
     public String getCompleteId()
     {

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/Page.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/Page.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/Page.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/Page.java Fri Feb 22 18:36:14 2008
@@ -154,4 +154,11 @@
      * Called as a component finishes rendering itself.
      */
     void decrementDirtyCount();
+
+    /**
+     * Discards all persistent field changes for the page containing the component.  Changes are eliminated from
+     * persistent storage (such as the {@link org.apache.tapestry.services.Session}) which will take effect in the
+     * <em>next</em> request (the attached page instance is not affected).
+     */
+    void discardPersistentFieldChanges();
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/PageImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/PageImpl.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/PageImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/PageImpl.java Fri Feb 22 18:36:14 2008
@@ -17,13 +17,13 @@
 import org.apache.tapestry.ComponentResources;
 import org.apache.tapestry.Link;
 import org.apache.tapestry.internal.services.LinkFactory;
+import org.apache.tapestry.internal.services.PersistentFieldManager;
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
 import static org.apache.tapestry.ioc.internal.util.Defense.notNull;
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
 import org.apache.tapestry.runtime.Component;
 import org.apache.tapestry.runtime.PageLifecycleListener;
 import org.apache.tapestry.services.PersistentFieldBundle;
-import org.apache.tapestry.services.PersistentFieldManager;
 import org.slf4j.Logger;
 
 import java.util.List;
@@ -46,8 +46,8 @@
     private int _dirtyCount;
 
     /**
-     * Obtained from the {@link PersistentFieldManager} when first needed, discarded at the end of
-     * the request.
+     * Obtained from the {@link org.apache.tapestry.internal.services.PersistentFieldManager} when first needed,
+     * discarded at the end of the request.
      */
     private PersistentFieldBundle _fieldBundle;
 
@@ -176,6 +176,11 @@
     public void decrementDirtyCount()
     {
         _dirtyCount--;
+    }
+
+    public void discardPersistentFieldChanges()
+    {
+        _persistentFieldManager.discardChanges(_logicalPageName);
     }
 
     public void incrementDirtyCount()

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PersistentFieldStrategy.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PersistentFieldStrategy.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PersistentFieldStrategy.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/PersistentFieldStrategy.java Fri Feb 22 18:36:14 2008
@@ -1,26 +1,25 @@
-// Copyright 2006 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 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.
+// 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.services;
 
 import java.util.Collection;
 
 /**
  * Defines how changes to fields (within components, within pages) may have their values persisted between requests.
- * Different implementations store the field values
- * {@linkplain org.apache.tapestry.internal.services.SessionPersistentFieldStrategy in the session},
- * {@linkplain org.apache.tapestry.internal.services.ClientPersistentFieldStrategy on the client}, or
+ * Different implementations store the field values {@linkplain org.apache.tapestry.internal.services.SessionPersistentFieldStrategy
+ * in the session}, {@linkplain org.apache.tapestry.internal.services.ClientPersistentFieldStrategy on the client}, or
  * elsewhere.
  */
 public interface PersistentFieldStrategy
@@ -36,8 +35,16 @@
     void postChange(String pageName, String componentId, String fieldName, Object newValue);
 
     /**
-     * Finds all persistent changes previously stored for the named page (for the current active
-     * session or client).
+     * Finds all persistent changes previously stored for the named page (for the current active session or client).
      */
     Collection<PersistentFieldChange> gatherFieldChanges(String pageName);
+
+    /**
+     * Discards any saved changes for the name page. There is no expectation that data already gathered from the
+     * strategy and persumably dumped into component instance fields will be affected, but future field access (within
+     * this request or a later one) will show no data for the indicated page.
+     *
+     * @param pageName logical name of page whose field persistent data should be discarded
+     */
+    void discardChanges(String pageName);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/persist.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/persist.apt?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/persist.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/persist.apt Fri Feb 22 18:36:14 2008
@@ -95,4 +95,12 @@
   Servlet API.  Changing a persistent field's value to null <removes> the
   field's attribute from the session. On later requests, the field will reset to its
   default value. Since that is usually null, this is not a problem ... it is only a problem
-  if a field has a non-null default value and may be changed to null. 
\ No newline at end of file
+  if a field has a non-null default value and may be changed to null.
+
+Clearing Persistent Fields
+
+   If you reach a point where you know that all data for a page can be discarded, you can do exactly that.
+
+   The method <<<discardPersistentFieldChanges()>>> of ComponentResources will discard all persistent fields
+   for the page, regardless of which strategy is used to store the property. This will not affect the
+   page in memory, but takes effect for subsequent requests.
\ No newline at end of file

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PersistentDemo.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PersistentDemo.tml?rev=630378&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PersistentDemo.tml (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PersistentDemo.tml Fri Feb 22 18:36:14 2008
@@ -0,0 +1,21 @@
+<html t:type="Border"
+      xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+
+    <p>
+        Message:
+        <span id="message">${message}</span>
+    </p>
+
+    <ul>
+        <li>
+            <t:actionlink t:id="updateMessage" context="literal:updated">Update the message field</t:actionlink>
+        </li>
+        <li>
+            <t:actionlink t:id="discardChanges">Discard persistent field changes</t:actionlink>
+        </li>
+        <li>
+            <t:pagelink page="persistentdemo">Refresh page</t:pagelink>
+        </li>
+    </ul>
+</html>
+

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java Fri Feb 22 18:36:14 2008
@@ -1729,4 +1729,27 @@
 
         assertText("message", "from getActionURL()");
     }
+
+    /**
+     * TAPESTRY-1475
+     */
+    @Test
+    public void discard_persistent_field_changes()
+    {
+        start("Persistent Demo");
+
+        assertText("message", "");
+
+        clickAndWait("link=Update the message field");
+
+        assertText("message", "updated");
+
+        clickAndWait("link=Refresh page");
+
+        assertText("message", "updated");
+
+        clickAndWait("link=Discard persistent field changes");
+
+        assertText("message", "");
+    }
 }

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PersistentDemo.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PersistentDemo.java?rev=630378&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PersistentDemo.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PersistentDemo.java Fri Feb 22 18:36:14 2008
@@ -0,0 +1,43 @@
+// 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.app1.pages;
+
+import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.annotations.Persist;
+import org.apache.tapestry.ioc.annotations.Inject;
+
+public class PersistentDemo
+{
+    @Persist
+    private String _message;
+
+    @Inject
+    private ComponentResources _resources;
+
+    void onActionFromUpdateMessage(String message)
+    {
+        _message = message;
+    }
+
+    void onActionFromDiscardChanges()
+    {
+        _resources.discardPersistentFieldChanges();
+    }
+
+    public String getMessage()
+    {
+        return _message;
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java Fri Feb 22 18:36:14 2008
@@ -62,6 +62,8 @@
     private static final List<Item> ITEMS = CollectionFactory.newList(
             new Item("actionpage", "Action Page", "tests fixture for ActionLink component"),
 
+            new Item("PersistentDemo", "Persistent Demo", "storing and clearing persistent properties"),
+
             new Item("ActionViaLinkDemo", "Action via Link Demo", "tests creating an action link explicitly"),
 
             new Item("FormFragmentDemo", "Form Fragment Demo", "page with dynamic form sections"),

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImplTest.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ClientPersistentFieldStorageImplTest.java Fri Feb 22 18:36:14 2008
@@ -175,6 +175,35 @@
         verify();
     }
 
+    /**
+     * TAPESTRY-1475
+     */
+    @Test
+    public void discard_changes()
+    {
+        Request request = mockRequest(null);
+        Link link = mockLink();
+
+        String pageName = "Foo";
+        String componentId = "bar.baz";
+        String fieldName = "woops";
+
+        replay();
+
+        ClientPersistentFieldStorage storage = new ClientPersistentFieldStorageImpl(request);
+
+        storage.postChange(pageName, componentId, fieldName, 99);
+
+        storage.discardChanges(pageName);
+
+        storage.updateLink(link);
+
+        assertTrue(storage.gatherFieldChanges(pageName).isEmpty());
+
+        verify();
+    }
+
+
     @Test
     public void value_not_serializable()
     {

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/PersistentFieldManagerImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/PersistentFieldManagerImplTest.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/PersistentFieldManagerImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/PersistentFieldManagerImplTest.java Fri Feb 22 18:36:14 2008
@@ -19,7 +19,10 @@
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;
 import org.apache.tapestry.model.ComponentModel;
-import org.apache.tapestry.services.*;
+import org.apache.tapestry.services.MetaDataLocator;
+import org.apache.tapestry.services.PersistentFieldBundle;
+import org.apache.tapestry.services.PersistentFieldChange;
+import org.apache.tapestry.services.PersistentFieldStrategy;
 import org.testng.annotations.Test;
 
 import java.util.Collection;
@@ -60,6 +63,33 @@
                     ex.getMessage(),
                     "\'braveheart\' is not a defined persistent strategy.  Defined strategies: bar, foo.");
         }
+
+        verify();
+    }
+
+    /**
+     * TAPESTRY-1475
+     */
+    @Test
+    public void discard_changes()
+    {
+        PersistentFieldStrategy strat1 = newPersistentFieldStrategy();
+        PersistentFieldStrategy strat2 = newPersistentFieldStrategy();
+
+        Map<String, PersistentFieldStrategy> strategies = newMap();
+        strategies.put("foo", strat1);
+        strategies.put("bar", strat2);
+
+        String pageName = "gnip.gnop";
+
+        strat1.discardChanges(pageName);
+        strat2.discardChanges(pageName);
+
+        replay();
+
+        PersistentFieldManager manager = new PersistentFieldManagerImpl(null, strategies);
+
+        manager.discardChanges(pageName);
 
         verify();
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategyTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategyTest.java?rev=630378&r1=630377&r2=630378&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategyTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategyTest.java Fri Feb 22 18:36:14 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.
@@ -61,6 +61,49 @@
         SessionPersistentFieldStrategy strategy = new SessionPersistentFieldStrategy(request);
 
         strategy.postChange("foo.Bar", "fee.fum", "field", value);
+
+        verify();
+    }
+
+    /**
+     * TAPESTRY-1475
+     */
+    @Test
+    public void discard_changes_with_no_session()
+    {
+        Request request = mockRequest();
+
+        train_getSession(request, false, null);
+
+        replay();
+
+        SessionPersistentFieldStrategy strategy = new SessionPersistentFieldStrategy(request);
+
+        strategy.discardChanges("foo.Bar");
+
+        verify();
+    }
+
+    /**
+     * TAPESTRY-1475
+     */
+    @Test
+    public void discard_changes()
+    {
+        Session session = mockSession();
+        Request request = mockRequest();
+
+        train_getSession(request, false, session);
+
+        train_getAttributeNames(session, "state:foo.Bar:", "state:foo.Bar:baz:field");
+
+        session.setAttribute("state:foo.Bar:baz:field", null);
+
+        replay();
+
+        SessionPersistentFieldStrategy strategy = new SessionPersistentFieldStrategy(request);
+
+        strategy.discardChanges("foo.Bar");
 
         verify();
     }