Author: hlship
Date: Wed Jan 24 16:17:13 2007
New Revision: 499626
URL: http://svn.apache.org/viewvc?view=rev&rev=499626
Log:
Add support for flash persistence (really useful for error or confirmation
messages).
Added:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategy.java
tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/FlashDemo.html
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/FlashDemo.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategyTest.java
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategy.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/persist.apt
tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
Added:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java?view=auto&rev=499626
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java
(added)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AbstractSessionPersistentFieldStrategy.java
Wed Jan 24 16:17:13 2007
@@ -0,0 +1,114 @@
+// 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.
+
+package org.apache.tapestry.internal.services;
+
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
+import static org.apache.tapestry.ioc.internal.util.Defense.notBlank;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.tapestry.services.PersistentFieldChange;
+import org.apache.tapestry.services.PersistentFieldStrategy;
+import org.apache.tapestry.services.Session;
+
+/**
+ * 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
+{
+ private final String _prefix;
+
+ private final SessionHolder _sessionHolder;
+
+ protected AbstractSessionPersistentFieldStrategy(String prefix,
SessionHolder sessionHolder)
+ {
+ _prefix = prefix;
+ _sessionHolder = sessionHolder;
+ }
+
+ public final Collection<PersistentFieldChange> gatherFieldChanges(String
pageName)
+ {
+ Session session = _sessionHolder.getSession(false);
+
+ if (session == null)
+ return Collections.emptyList();
+
+ List<PersistentFieldChange> result = newList();
+
+ String fullPrefix = _prefix + pageName + ":";
+
+ for (String name : session.getAttributeNames(fullPrefix))
+ {
+ PersistentFieldChange change = buildChange(name,
session.getAttribute(name));
+
+ result.add(change);
+
+ didReadChange(session, name);
+ }
+
+ return result;
+ }
+
+ /**
+ * Called after each key is read by [EMAIL PROTECTED]
#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
+ */
+ protected void didReadChange(Session session, String attributeName)
+ {
+ }
+
+ private PersistentFieldChange buildChange(String name, Object attribute)
+ {
+ // TODO: Regexp is probably too expensive for what we need here. Maybe
an IOC InternalUtils
+ // method for this purpose?
+
+ String[] chunks = name.split(":");
+
+ // Will be empty string for the root component
+ String componentId = chunks[2];
+ String fieldName = chunks[3];
+
+ return new PersistentFieldChangeImpl(componentId, fieldName,
attribute);
+ }
+
+ public final void postChange(String pageName, String componentId, String
fieldName,
+ Object newValue)
+ {
+ notBlank(pageName, "pageName");
+ notBlank(fieldName, "fieldName");
+
+ StringBuilder builder = new StringBuilder(_prefix);
+ builder.append(pageName);
+ builder.append(':');
+
+ if (componentId != null)
+ builder.append(componentId);
+
+ builder.append(':');
+ builder.append(fieldName);
+
+ Session session = _sessionHolder.getSession(true);
+
+ session.setAttribute(builder.toString(), newValue);
+ }
+}
Added:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategy.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategy.java?view=auto&rev=499626
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategy.java
(added)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategy.java
Wed Jan 24 16:17:13 2007
@@ -0,0 +1,44 @@
+// 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.
+
+package org.apache.tapestry.internal.services;
+
+import org.apache.tapestry.services.Session;
+
+/**
+ * The "flash" strategy stores data inside the [EMAIL PROTECTED] Session
session}, just like
+ * [EMAIL PROTECTED] SessionPersistentFieldStrategy}, but also removes the
values from the session on first
+ * use. In this way, a short-term value (such as an error message) will
"survive" from an action
+ * request to a render request and then disappear.
+ */
+public class FlashPersistentFieldStrategy extends
AbstractSessionPersistentFieldStrategy
+{
+ /**
+ * Prefix used to identify keys stored in the session.
+ */
+ static final String PREFIX = "flash:";
+
+ public FlashPersistentFieldStrategy(SessionHolder sessionHolder)
+ {
+ super(PREFIX, sessionHolder);
+ }
+
+ @Override
+ protected void didReadChange(Session session, String attributeName)
+ {
+ // For flash persistence, after reading a value, get rid of it.
+ session.setAttribute(attributeName, null);
+ }
+
+}
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategy.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategy.java?view=diff&rev=499626&r1=499625&r2=499626
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategy.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/SessionPersistentFieldStrategy.java
Wed Jan 24 16:17:13 2007
@@ -12,92 +12,27 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.internal.services;
-
-import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
-import static org.apache.tapestry.ioc.internal.util.Defense.notBlank;
+package org.apache.tapestry.internal.services;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.tapestry.services.PersistentFieldChange;
-import org.apache.tapestry.services.PersistentFieldStrategy;
import org.apache.tapestry.services.Session;
-
-/**
- * A strategy for storing persistent page properties into the [EMAIL
PROTECTED] Session session}.
- * <p>
- * Builds attribute names as:
- *
<code>state:<em>page-name</em>:<em>component-id</em>:<em>field-name</em></code>
- */
-
-public class SessionPersistentFieldStrategy implements PersistentFieldStrategy
-{
- /**
- * Prefix used to identify keys stored in the session that are being used
to store persistent
- * field data.
- */
- public static final String PREFIX = "state:";
- private final SessionHolder _sessionHolder;
-
- public SessionPersistentFieldStrategy(final SessionHolder sessionHolder)
- {
- _sessionHolder = sessionHolder;
- }
-
- public Collection<PersistentFieldChange> gatherFieldChanges(String
pageName)
- {
- Session session = _sessionHolder.getSession(false);
-
- if (session == null)
- return Collections.emptyList();
-
- List<PersistentFieldChange> result = newList();
-
- String fullPrefix = PREFIX + pageName + ":";
-
- for (String name : session.getAttributeNames(fullPrefix))
- {
- PersistentFieldChange change = buildChange(name,
session.getAttribute(name));
-
- result.add(change);
- }
-
- return result;
- }
-
- private PersistentFieldChange buildChange(String name, Object attribute)
- {
-
- String[] chunks = name.split(":");
-
- // Will be empty string for the root component
- String componentId = chunks[2];
- String fieldName = chunks[3];
-
- return new PersistentFieldChangeImpl(componentId, fieldName,
attribute);
- }
-
- public void postChange(String pageName, String componentId, String
fieldName, Object newValue)
- {
- notBlank(pageName, "pageName");
- notBlank(fieldName, "fieldName");
-
- StringBuilder builder = new StringBuilder(PREFIX);
- builder.append(pageName);
- builder.append(':');
-
- if (componentId != null)
- builder.append(componentId);
-
- builder.append(':');
- builder.append(fieldName);
-
- Session session = _sessionHolder.getSession(true);
-
- session.setAttribute(builder.toString(), newValue);
- }
-
-}
+/**
+ * A strategy for storing persistent page properties into the [EMAIL
PROTECTED] Session session}.
+ * <p>
+ * Builds attribute names as:
+ *
<code>state:<em>page-name</em>:<em>component-id</em>:<em>field-name</em></code>
+ */
+
+public class SessionPersistentFieldStrategy extends
AbstractSessionPersistentFieldStrategy
+{
+ /**
+ * Prefix used to identify keys stored in the session that are being used
to store persistent
+ * field data.
+ */
+ static final String PREFIX = "state:";
+
+ public SessionPersistentFieldStrategy(SessionHolder sessionHolder)
+ {
+ super(PREFIX, sessionHolder);
+ }
+}
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java?view=diff&rev=499626&r1=499625&r2=499626
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
Wed Jan 24 16:17:13 2007
@@ -77,6 +77,7 @@
import org.apache.tapestry.internal.services.EnvironmentImpl;
import org.apache.tapestry.internal.services.EnvironmentalWorker;
import org.apache.tapestry.internal.services.FieldValidatorSourceImpl;
+import org.apache.tapestry.internal.services.FlashPersistentFieldStrategy;
import org.apache.tapestry.internal.services.HeartbeatImpl;
import org.apache.tapestry.internal.services.InfrastructureImpl;
import org.apache.tapestry.internal.services.InfrastructureManagerImpl;
@@ -827,6 +828,7 @@
SessionHolder sessionHolder)
{
configuration.add("session", new
SessionPersistentFieldStrategy(sessionHolder));
+ configuration.add("flash", new
FlashPersistentFieldStrategy(sessionHolder));
}
public ComponentSource buildComponentSource(
@@ -836,19 +838,6 @@
return new ComponentSourceImpl(pageCache);
}
- /** Contributes handlers for type Component and type String. */
- // private void contributeComponentEventHandler(
- // MappedConfiguration<Class, ComponentEventHandler> configuration,
- // @InjectService("ComponentInstanceEventHandler")
- // ComponentEventHandler componentInstanceEventHandler)
- // {
- // configuration.add(Component.class, componentInstanceEventHandler);
- // configuration.add(String.class, new
StringEventHandler(_requestPageCache));
- // }
- // public ComponentEventHandler buildComponentInstanceEventHandler(Log log)
- // {
- // return new ComponentInstanceEventHandler(_requestPageCache, log);
- // }
public ComponentMessagesSource buildComponentMessagesSource(
@InjectService("tapestry.internal.UpdateListenerHub")
UpdateListenerHub updateListenerHub)
Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/persist.apt
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/persist.apt?view=diff&rev=499626&r1=499625&r2=499626
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/persist.apt
(original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/persist.apt Wed
Jan 24 16:17:13 2007
@@ -43,6 +43,15 @@
A suitably long session attribute name is used; it incorporates the
name of the page, the nested component id, and the name of the field.
+* flash strategy
+
+ The flash strategy stores information in the session as well, just for not
very long. Values are
+ stored into the session, but then deleted from the session as they are first
used to restore
+ a page's state.
+
+ The flash is typically used to store temporary messages that should only be
displayed to the user
+ once.
+
Persistence Search
By default the value for the Persist annotation is the empty string. When
this is true,
Added:
tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/FlashDemo.html
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/FlashDemo.html?view=auto&rev=499626
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/FlashDemo.html
(added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/FlashDemo.html
Wed Jan 24 16:17:13 2007
@@ -0,0 +1,18 @@
+<html t:type="Border"
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+
+ <h1>Flash Demo</h1>
+
+ <p>
+ The message: [${message}]
+ </p>
+
+ <p>
+ Click <a t:type="ActionLink" t:id="show">here</a> to show the message.
+ </p>
+
+ <p>
+ Click <a id="refresh" href="FlashDemo.html">here</a> to refresh the
page. Boy do we need a PageLink component!
+ </p>
+
+
+</html>
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html?view=diff&rev=499626&r1=499625&r2=499626
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html Wed Jan 24
16:17:13 2007
@@ -50,15 +50,13 @@
operations when invoking render phase methods </li>
<li><a href="SimpleForm.html">SimpleForm</a> -- first
pass at writing Form
and TextField components </li>
-
+ <li>
+ <a href="NumberSelect.html">NumberSelect</a> --
passivate/activate page
+ context demo </li>
</ul>
</td>
<td>
- <ul>
- <li>
- <a href="NumberSelect.html">NumberSelect</a> --
passivate/activate page
- context demo </li>
- <li>
+ <ul><li>
<a href="Localization.html">Localization</a> --
accessing localized
messages from the component catalog </li>
<li>
@@ -92,6 +90,9 @@
<li>
<a href="ToDoList.html">ToDo List</a> -- Loops and
Submit inside Form
using a primary key encoder </li>
+ <li>
+ <a href="FlashDemo.html">FlashDemo</a> --
demonstrate "flash" persistence
+ </li>
</ul>
</td>
</tr>
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?view=diff&rev=499626&r1=499625&r2=499626
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
Wed Jan 24 16:17:13 2007
@@ -548,6 +548,25 @@
test_loop_inside_form("ToDo List (Volatile)");
}
+ /** This also verifies the use of meta data to set the default strategy. */
+ @Test
+ public void flash_persistence()
+ {
+ _selenium.open(BASE_URL);
+
+ clickAndWait("link=FlashDemo");
+
+ assertTextPresent("[]");
+
+ clickAndWait("show");
+
+ assertTextPresent("[You clicked the link!]");
+
+ clickAndWait("refresh");
+
+ assertTextPresent("[]");
+ }
+
private void assertSourcePresent(String... expected)
{
String source = _selenium.getHtmlSource();
Added:
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/FlashDemo.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/FlashDemo.java?view=auto&rev=499626
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/FlashDemo.java
(added)
+++
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/FlashDemo.java
Wed Jan 24 16:17:13 2007
@@ -0,0 +1,35 @@
+// 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.
+
+package org.apache.tapestry.integration.app1.pages;
+
+import org.apache.tapestry.annotations.ComponentClass;
+import org.apache.tapestry.annotations.Persist;
+
[EMAIL PROTECTED](meta = "tapestry.persistence-strategy=flash")
+public class FlashDemo
+{
+ @Persist
+ private String _message;
+
+ public String getMessage()
+ {
+ return _message;
+ }
+
+ void onAction()
+ {
+ _message = "You clicked the link!";
+ }
+}
Added:
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategyTest.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategyTest.java?view=auto&rev=499626
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategyTest.java
(added)
+++
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/FlashPersistentFieldStrategyTest.java
Wed Jan 24 16:17:13 2007
@@ -0,0 +1,96 @@
+// 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.
+
+package org.apache.tapestry.internal.services;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.services.PersistentFieldChange;
+import org.apache.tapestry.services.PersistentFieldStrategy;
+import org.apache.tapestry.services.Request;
+import org.apache.tapestry.services.Session;
+import org.testng.annotations.Test;
+
+/**
+ * A more minimal test, since common behavior is already tested by
+ * [EMAIL PROTECTED] SessionPersistentFieldStrategyTest}.
+ */
+public class FlashPersistentFieldStrategyTest extends InternalBaseTestCase
+{
+ @Test
+ public void post_change_to_root_component()
+ {
+ Session session = newSession();
+ Request request = newRequest();
+ Object value = new Object();
+
+ train_getSession(request, true, session);
+
+ session.setAttribute("flash:foo.Bar::field", value);
+
+ replay();
+
+ PersistentFieldStrategy strategy = new
FlashPersistentFieldStrategy(request);
+
+ strategy.postChange("foo.Bar", null, "field", value);
+
+ verify();
+ }
+
+ @Test
+ public void gather_changes_with_active_session()
+ {
+ Session session = newSession();
+ Request request = newRequest();
+
+ train_getSession(request, false, session);
+ train_getAttributeNames(
+ session,
+ "flash:foo.Bar:",
+ "flash:foo.Bar::root",
+ "flash:foo.Bar:nested:down");
+
+ train_getAttribute(session, "flash:foo.Bar::root", "ROOT");
+ session.setAttribute("flash:foo.Bar::root", null);
+
+ train_getAttribute(session, "flash:foo.Bar:nested:down", "DOWN");
+ session.setAttribute("flash:foo.Bar:nested:down", null);
+
+ replay();
+
+ PersistentFieldStrategy strategy = new
FlashPersistentFieldStrategy(request);
+
+ Collection<PersistentFieldChange> changes =
strategy.gatherFieldChanges("foo.Bar");
+
+ assertEquals(changes.size(), 2);
+
+ Iterator<PersistentFieldChange> i = changes.iterator();
+
+ PersistentFieldChange change1 = i.next();
+
+ assertEquals(change1.getComponentId(), "");
+ assertEquals(change1.getFieldName(), "root");
+ assertEquals(change1.getValue(), "ROOT");
+
+ PersistentFieldChange change2 = i.next();
+
+ assertEquals(change2.getComponentId(), "nested");
+ assertEquals(change2.getFieldName(), "down");
+ assertEquals(change2.getValue(), "DOWN");
+
+ verify();
+ }
+}