You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by sv...@apache.org on 2019/03/14 14:24:36 UTC

[wicket] branch WICKET-6563 updated: WICKET-6563 IPageContext methods have a default value now

This is an automated email from the ASF dual-hosted git repository.

svenmeier pushed a commit to branch WICKET-6563
in repository https://gitbox.apache.org/repos/asf/wicket.git


The following commit(s) were added to refs/heads/WICKET-6563 by this push:
     new b6b5b04  WICKET-6563 IPageContext methods have a default value now
b6b5b04 is described below

commit b6b5b04c89dda1d69a45780a11baa7cf4aaa0347
Author: Sven Meier <sv...@apache.org>
AuthorDate: Tue Feb 26 10:37:46 2019 +0100

    WICKET-6563 IPageContext methods have a default value now
    
    ;moved DummyPageContext to MockPageContext
---
 .../org/apache/wicket/mock/MockPageContext.java}   |  65 ++++++-----
 .../pageStore/AbstractPersistentPageStore.java     |  18 +--
 .../wicket/pageStore/AsynchronousPageStore.java    | 127 +++++++++------------
 .../apache/wicket/pageStore/CryptingPageStore.java |   7 +-
 .../wicket/pageStore/DefaultPageContext.java       |  74 ++++++------
 .../apache/wicket/pageStore/GroupingPageStore.java |  83 +++++++-------
 .../org/apache/wicket/pageStore/IPageContext.java  |  83 +++++---------
 .../wicket/pageStore/InSessionPageStore.java       |  15 ++-
 .../apache/wicket/pageStore/RequestPageStore.java  |   9 +-
 .../core/request/mapper/TestMapperContext.java     |   6 +-
 .../wicket/page/PersistentPageManagerTest.java     |  24 ++--
 .../pageStore/AbstractConcurrentPageStoreTest.java |   3 +-
 .../wicket/pageStore/AbstractPageStoreTest.java    |  52 ++++++---
 .../pageStore/AsynchronousDataStoreTest.java       |   3 +-
 .../pageStore/AsynchronousPageStoreTest.java       |  81 +++++--------
 .../wicket/pageStore/CryptingPageStoreTest.java    |   5 +-
 .../wicket/pageStore/GroupingPageStoreTest.java    |  22 ++--
 .../wicket/pageStore/RequestPageStoreTest.java     |   3 +-
 .../wicket/pageStore/SerializingPageStoreTest.java |   3 +-
 19 files changed, 327 insertions(+), 356 deletions(-)

diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/DummyPageContext.java b/wicket-core/src/main/java/org/apache/wicket/mock/MockPageContext.java
similarity index 61%
rename from wicket-core/src/test/java/org/apache/wicket/pageStore/DummyPageContext.java
rename to wicket-core/src/main/java/org/apache/wicket/mock/MockPageContext.java
index a4c8704..061b377 100644
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/DummyPageContext.java
+++ b/wicket-core/src/main/java/org/apache/wicket/mock/MockPageContext.java
@@ -14,20 +14,21 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.wicket.pageStore;
+package org.apache.wicket.mock;
 
 import java.io.Serializable;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.function.Supplier;
 
 import org.apache.wicket.MetaDataEntry;
 import org.apache.wicket.MetaDataKey;
 import org.apache.wicket.pageStore.IPageContext;
 
 /**
- * Dummy implementation of a page context - suitable for a single session only.
+ * Mock implementation of a page context - suitable for a single session only.
  */
-public class DummyPageContext implements IPageContext
+public class MockPageContext implements IPageContext
 {
 
 	final String sessionId;
@@ -38,57 +39,61 @@ public class DummyPageContext implements IPageContext
 
 	Map<String, Object> sessionAttributes = new HashMap<>();
 
-	public DummyPageContext()
+	public MockPageContext()
 	{
 		this("dummy_id");
 	}
 
-	public DummyPageContext(String sessionId)
+	public MockPageContext(String sessionId)
 	{
 		this.sessionId = sessionId;
 	}
 
 	@Override
-	public <T> void setRequestData(MetaDataKey<T> key, T value)
+	public <T> T getRequestData(MetaDataKey<T> key, Supplier<T> defaultValue)
 	{
-		requestData = key.set(requestData, value);
-	}
+		T value = key.get(requestData);
+		if (value == null) {
+			value = defaultValue.get();
+			if (value != null) {
+				requestData = key.set(requestData, value);
+			}
+		}
 
-	@Override
-	public <T> T getRequestData(MetaDataKey<T> key)
-	{
-		return key.get(requestData);
+		return value;
 	}
 
 	@Override
-	public <T extends Serializable> void setSessionAttribute(String key, T value)
-	{
-		sessionAttributes.put(key, value);
-	}
-	
-	@SuppressWarnings("unchecked")
-	@Override
-	public <T extends Serializable> T getSessionAttribute(String key)
+	public <T extends Serializable> T getSessionAttribute(String key, Supplier<T> defaultValue)
 	{
-		return (T)sessionAttributes.get(key);
+		@SuppressWarnings("unchecked")
+		T value = (T)sessionAttributes.get(key);
+		if (value == null) {
+			value = defaultValue.get();
+			if (value != null) {
+				sessionAttributes.put(key, value);
+			}
+		}
+		
+		return value;
 	}
 	
 	@Override
-	public <T extends Serializable> T setSessionData(MetaDataKey<T> key, T value)
+	public <T extends Serializable> T getSessionData(MetaDataKey<T> key, Supplier<T> defaultValue)
 	{
-		sessionData = key.set(sessionData, value);
+		T value = key.get(sessionData);
+		if (value == null) {
+			value = defaultValue.get();
+			if (value != null) {
+				sessionData = key.set(sessionData, value);
+			}
+		}
 		
 		return value;
 	}
 
 	@Override
-	public <T extends Serializable> T getSessionData(MetaDataKey<T> key)
-	{
-		return key.get(sessionData);
-	}
-
-	@Override
-	public String getSessionId()
+	public String getSessionId(boolean bind)
 	{
 		return sessionId;
 	}
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPersistentPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPersistentPageStore.java
index 0b6deec..17541ee 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPersistentPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/AbstractPersistentPageStore.java
@@ -146,12 +146,14 @@ public abstract class AbstractPersistentPageStore implements IPageStore
 	{
 		String key = KEY_PREFIX + Classes.simpleName(getClass());
 		
-		SessionAttribute attribute = context.getSessionAttribute(key);
-		if (attribute == null && create)
-		{
-			attribute = new SessionAttribute(storeKey, createSessionIdentifier(context));
-			context.setSessionAttribute(key, attribute);
-		}
+		SessionAttribute attribute = context.getSessionAttribute(key, () -> {
+			if (create)
+			{
+				return new SessionAttribute(storeKey, createSessionIdentifier(context));
+			}
+			
+			return null;
+		});
 		
 		if (attribute == null)
 		{
@@ -170,7 +172,7 @@ public abstract class AbstractPersistentPageStore implements IPageStore
 	 */
 	protected String createSessionIdentifier(IPageContext context)
 	{
-		return context.getSessionId();
+		return context.getSessionId(true);
 	}
 
 	/**
@@ -182,7 +184,7 @@ public abstract class AbstractPersistentPageStore implements IPageStore
 		private final String storeKey;
 
 		/**
-		 * The identifier of the session, must not be equal to {@link Session#getId()}, e.g. when
+		 * The identifier of the session, may not be equal to {@link Session#getId()}, e.g. when
 		 * the container changes the id after authorization.
 		 */
 		public final String sessionIdentifier;
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/AsynchronousPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/AsynchronousPageStore.java
index 42f3233..caf17ce 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/AsynchronousPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/AsynchronousPageStore.java
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
 
 import org.apache.wicket.MetaDataKey;
 import org.apache.wicket.WicketRuntimeException;
@@ -140,7 +141,7 @@ public class AsynchronousPageStore extends DelegatingPageStore
 			this.context = Args.notNull(context, "context");
 			this.page = Args.notNull(page, "page");
 			
-			this.sessionId = context.getSessionId();
+			this.sessionId = context.getSessionId(true);
 		}
 
 		/**
@@ -163,110 +164,81 @@ public class AsynchronousPageStore extends DelegatingPageStore
 		 * Prevents access to request when called asynchronously.
 		 */
 		@Override
-		public <T> void setRequestData(MetaDataKey<T> key, T value)
+		public <T> T getRequestData(MetaDataKey<T> key, Supplier<T> value)
 		{
 			if (asynchronous)
 			{
-				throw new WicketRuntimeException("no request available asynchronuously");
+				throw new WicketRuntimeException("request data not available asynchronuously");
 			}
 			
-			context.setRequestData(key, value);
+			return context.getRequestData(key, value);
 		}
 
 		/**
-		 * Prevents access to request when called asynchronously.
-		 */
-		@Override
-		public <T> T getRequestData(MetaDataKey<T> key)
-		{
-			if (asynchronous)
-			{
-				throw new WicketRuntimeException("no request available asynchronuously");
-			}
-			
-			return context.getRequestData(key);
-		}
-
-		/**
-		 * Prevents access to the session when called asynchronously.
-		 * <p>
-		 * All values set from {@link IPageStore#canBeAsynchronous(IPageContext)} are kept
-		 * for later retrieval.
-		 */
-		@Override
-		public <T extends Serializable> void setSessionAttribute(String key, T value)
-		{
-			if (asynchronous)
-			{
-				throw new WicketRuntimeException("no session available asynchronuously");
-			}
-			
-			if (value != null)
-			{
-				attributeCache.put(key, value);
-			}
-
-			context.setSessionAttribute(key, value);
-		}
-		
-		/**
-		 * Prevents access to the session when called asynchronously.
+		 * Prevents changing of session attributes when called asynchronously.
 		 * <p>
-		 * All values set from {@link IPageStore#canBeAsynchronous(IPageContext)} are still
+		 * All values accessed from {@link IPageStore#canBeAsynchronous(IPageContext)} are still
 		 * available.
 		 */
 		@SuppressWarnings("unchecked")
 		@Override
-		public <T extends Serializable> T getSessionAttribute(String key)
+		public <T extends Serializable> T getSessionAttribute(String key, Supplier<T> defaultValue)
 		{
+			T value;
+			
 			if (asynchronous)
 			{
-				T value = (T)attributeCache.get(key);
+				value = (T)attributeCache.get(key);
+				if (value == null )
+				{
+					if (defaultValue.get() != null)
+					{
+						throw new WicketRuntimeException("session attribute can not be changed asynchronuously");
+					}
+				}
+			} else {
+				value = context.getSessionAttribute(key, defaultValue);
 				if (value != null)
 				{
-					return value;
+					attributeCache.put(key, value);
 				}
-				
-				throw new WicketRuntimeException("no session available asynchronuously");
-			}
-			
-			T value = context.getSessionAttribute(key);
-			if (value != null)
-			{
-				attributeCache.put(key, value);
 			}
 			
 			return value;
 		}
 		
 		/**
-		 * Prevents access to the session when called asynchronously.
+		 * Prevents changing of session data when called asynchronously.
 		 */
 		@Override
-		public <T extends Serializable> T setSessionData(MetaDataKey<T> key, T value)
+		public <T extends Serializable> T getSessionData(MetaDataKey<T> key, Supplier<T> defaultValue)
 		{
+			T value;
+			
 			if (asynchronous)
 			{
-				throw new WicketRuntimeException("no session available asynchronuously");
+				value = context.getSessionData(key, () -> null);
+				if (value == null )
+				{
+					if (defaultValue.get() != null)
+					{
+						throw new WicketRuntimeException("session data can not be changed asynchronuously");
+					}
+				}
+			}
+			else
+			{
+				value = context.getSessionData(key, defaultValue);
 			}
 			
-			return context.setSessionData(key, value);
-		}
-
-		/**
-		 * Gets data from the session.
-		 */
-		@Override
-		public <T extends Serializable> T getSessionData(MetaDataKey<T> key)
-		{
-			return context.getSessionData(key);
+			return value;
 		}
 
 		/**
 		 * Returns id of session.
 		 */
 		@Override
-		public String getSessionId()
+		public String getSessionId(boolean bind)
 		{
 			return sessionId;
 		}
@@ -341,7 +313,12 @@ public class AsynchronousPageStore extends DelegatingPageStore
 	@Override
 	public IManageablePage getPage(IPageContext context, int pageId)
 	{
-		PendingAdd entry = queueMap.get(getKey(context.getSessionId(), pageId));
+		String sessionId = context.getSessionId(false);
+		if (sessionId == null) {
+			return null;
+		}
+		
+		PendingAdd entry = queueMap.get(getKey(sessionId, pageId));
 		if (entry != null)
 		{
 			log.debug("Returning the page of a non-stored entry with page id '{}'", pageId);
@@ -357,7 +334,12 @@ public class AsynchronousPageStore extends DelegatingPageStore
 	@Override
 	public void removePage(IPageContext context, IManageablePage page)
 	{
-		String key = getKey(context.getSessionId(), page.getPageId());
+		String sessionId = context.getSessionId(false);
+		if (sessionId == null) {
+			return;
+		}
+
+		String key = getKey(sessionId, page.getPageId());
 		if (key != null)
 		{
 			PendingAdd entry = queueMap.remove(key);
@@ -408,12 +390,17 @@ public class AsynchronousPageStore extends DelegatingPageStore
 	@Override
 	public void removeAllPages(IPageContext context)
 	{
+		String sessionId = context.getSessionId(false);
+		if (sessionId == null) {
+			return;
+		}
+		
 		Iterator<PendingAdd> iterator = queue.iterator();
 		while (iterator.hasNext())
 		{
 			PendingAdd add = iterator.next(); 
 		
-			if (add.sessionId.equals(context.getSessionId()))
+			if (add.sessionId.equals(sessionId))
 			{
 				iterator.remove();
 			}
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/CryptingPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/CryptingPageStore.java
index 74d7819..74cd289 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/CryptingPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/CryptingPageStore.java
@@ -76,12 +76,7 @@ public class CryptingPageStore extends DelegatingPageStore
 
 	private SessionData getSessionData(IPageContext context)
 	{
-		SessionData data = context.getSessionData(KEY);
-		if (data == null)
-		{
-			data = context.setSessionData(KEY, new SessionData(newCrypter(context)));
-		}
-		return data;
+		return context.getSessionData(KEY, () -> new SessionData(newCrypter(context))); 
 	}
 
 	/**
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageContext.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageContext.java
index c75892b..c831dda 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageContext.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/DefaultPageContext.java
@@ -17,6 +17,7 @@
 package org.apache.wicket.pageStore;
 
 import java.io.Serializable;
+import java.util.function.Supplier;
 
 import org.apache.wicket.MetaDataKey;
 import org.apache.wicket.Session;
@@ -35,73 +36,74 @@ public class DefaultPageContext implements IPageContext
 	 * @see org.apache.wicket.pageStore.IPageContext#getSessionId()
 	 */
 	@Override
-	public String getSessionId()
+	public String getSessionId(boolean bind)
 	{
 		Session session = Session.get();
-		
-		session.bind();
+
+		if (bind) {
+			session.bind();
+		}
 		
 		return session.getId();
 	}
 
 	@SuppressWarnings("unchecked")
 	@Override
-	public <T extends Serializable> T getSessionAttribute(String key)
-	{
-		return (T)Session.get().getAttribute(key);
-	}
-	
-	@Override
-	public <T extends Serializable> void setSessionAttribute(String key, T value)
+	public <T extends Serializable> T getSessionAttribute(String key, Supplier<T> defaultValue)
 	{
 		Session session = Session.get();
-		session.bind();
-		session.setAttribute(key, value);
+
+		synchronized (session)
+		{
+			T value = (T)session.getAttribute(key);
+			if (value == null) {
+				value = defaultValue.get();
+				if (value != null) {
+					session.bind();
+					session.setAttribute(key, value);
+				}
+			}
+			
+			return value;
+		}
 	}
 	
 	@Override
-	public <T extends Serializable> T getSessionData(MetaDataKey<T> key)
-	{
-		return Session.get().getMetaData(key);
-	}
-
-	@Override
-	public <T extends Serializable> T setSessionData(MetaDataKey<T> key, T value)
+	public <T extends Serializable> T getSessionData(MetaDataKey<T> key, Supplier<T> defaultValue)
 	{
 		Session session = Session.get();
 
 		synchronized (session)
 		{
-			T oldValue = session.getMetaData(key);
-			if (oldValue != null) {
-				return oldValue;
+			T value = session.getMetaData(key);
+			if (value != null) {
+				return value;
 			}
 			
-			session.bind();
-			session.setMetaData(key, value);
+			value = defaultValue.get();
+			if (value != null) {
+				session.bind();
+				session.setMetaData(key, value);
+			}
 			return value;
 		}
 	}
 
 	@Override
-	public <T> T getRequestData(MetaDataKey<T> key)
+	public <T> T getRequestData(MetaDataKey<T> key, Supplier<T> defaultValue)
 	{
 		RequestCycle requestCycle = RequestCycle.get();
 		if (requestCycle == null)
 		{
 			throw new IllegalStateException("Not a request thread.");
 		}
-		return requestCycle.getMetaData(key);
-	}
-
-	@Override
-	public <T> void setRequestData(MetaDataKey<T> key, T value)
-	{
-		RequestCycle requestCycle = RequestCycle.get();
-		if (requestCycle == null)
-		{
-			throw new IllegalStateException("Not a request thread.");
+		T value = requestCycle.getMetaData(key);
+		if (value == null) {
+			value = defaultValue.get();
+			if (value != null) {
+				requestCycle.setMetaData(key, value);
+			}
 		}
-		requestCycle.setMetaData(key, value);
+		return value;
 	}
 }
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/GroupingPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/GroupingPageStore.java
index 8662df6..b588df7 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/GroupingPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/GroupingPageStore.java
@@ -20,6 +20,7 @@ import java.io.Serializable;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.Map;
+import java.util.function.Supplier;
 
 import org.apache.wicket.MetaDataEntry;
 import org.apache.wicket.MetaDataKey;
@@ -99,7 +100,7 @@ public abstract class GroupingPageStore extends DelegatingPageStore
 	@Override
 	public void addPage(IPageContext context, IManageablePage page)
 	{
-		SessionData sessionData = getSessionData(context);
+		SessionData sessionData = getSessionData(context, true);
 
 		sessionData.addPage(context, page, getGroupInternal(page), maxGroups, stableGroups, getDelegate());
 	}
@@ -107,7 +108,10 @@ public abstract class GroupingPageStore extends DelegatingPageStore
 	@Override
 	public void removePage(IPageContext context, IManageablePage page)
 	{
-		SessionData sessionData = getSessionData(context);
+		SessionData sessionData = getSessionData(context, false);
+		if (sessionData == null) {
+			return;
+		}
 		
 		sessionData.removePage(context, page, getDelegate());
 	}
@@ -115,7 +119,10 @@ public abstract class GroupingPageStore extends DelegatingPageStore
 	@Override
 	public void removeAllPages(IPageContext context)
 	{
-		SessionData sessionData = getSessionData(context);
+		SessionData sessionData = getSessionData(context, false);
+		if (sessionData == null) {
+			return;
+		}
 
 		sessionData.removeAllPages(context, getDelegate());
 	}
@@ -123,20 +130,26 @@ public abstract class GroupingPageStore extends DelegatingPageStore
 	@Override
 	public IManageablePage getPage(IPageContext context, int id)
 	{
-		SessionData sessionData = getSessionData(context);
+		SessionData sessionData = getSessionData(context, false);
+		if (sessionData == null) {
+			return null;
+		}
 		
 		return sessionData.getPage(context, id, getDelegate());
 	}
 
-	private SessionData getSessionData(IPageContext context)
+	private SessionData getSessionData(IPageContext context, boolean create)
 	{
-		SessionData data = context.getSessionData(KEY);
-		if (data == null)
-		{
-			data = context.setSessionData(KEY, new SessionData());
-		}
-
-		return data;
+		return context.getSessionData(KEY, () -> {
+			if (create)
+			{
+				return new SessionData();
+			}
+			else
+			{
+				return null;
+			}
+		});
 	}
 
 	/**
@@ -234,45 +247,37 @@ public abstract class GroupingPageStore extends DelegatingPageStore
 		}
 
 		@Override
-		public String getSessionId()
+		public String getSessionId(boolean bind)
 		{
-			return context.getSessionId() + "_" + group;
+			return context.getSessionId(true) + "_" + group;
 		}
 
 		@Override
-		public <T extends Serializable> T setSessionData(MetaDataKey<T> key, T value)
+		public <T extends Serializable> T getSessionData(MetaDataKey<T> key, Supplier<T> defaultValue)
 		{
-			sessionData.setMetaData(group, key, value);
-			
-			return value;
-		}
-
-		@Override
-		public <T extends Serializable> T getSessionData(MetaDataKey<T> key)
-		{
-			return sessionData.getMetaData(group, key);
-		}
-
-		@Override
-		public <T extends Serializable> void setSessionAttribute(String key, T value)
-		{
-			context.setSessionAttribute(key + "_" + group, value);
-		}
-
-		@Override
-		public <T extends Serializable> T getSessionAttribute(String key)
-		{
-			return context.getSessionAttribute(key + "_" + group);
+			synchronized (sessionData)
+			{
+				T data = sessionData.getMetaData(group, key);
+				if (data == null) {
+					data = defaultValue.get();
+					
+					if (data != null) {
+						sessionData.setMetaData(group, key, data);
+					}
+				}
+				
+				return data;
+			}
 		}
 
 		@Override
-		public <T> void setRequestData(MetaDataKey<T> key, T data)
+		public <T extends Serializable> T getSessionAttribute(String key, Supplier<T> defaultValue)
 		{
-			throw new WicketRuntimeException("no request available for group");
+			return context.getSessionAttribute(key + "_" + group, defaultValue);
 		}
 
 		@Override
-		public <T> T getRequestData(MetaDataKey<T> key)
+		public <T> T getRequestData(MetaDataKey<T> key, Supplier<T> defaultValue)
 		{
 			throw new WicketRuntimeException("no request available for group");
 		}
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/IPageContext.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/IPageContext.java
index f145375..0cdcd48 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/IPageContext.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/IPageContext.java
@@ -17,13 +17,16 @@
 package org.apache.wicket.pageStore;
 
 import java.io.Serializable;
+import java.util.function.Supplier;
 
 import org.apache.wicket.MetaDataKey;
+import org.apache.wicket.Session;
 import org.apache.wicket.page.IManageablePage;
+import org.apache.wicket.request.cycle.RequestCycle;
 
 /**
- * Context of a {@link IManageablePage} when it is store in a {@link IPageStore}, decoupling it from
- * request cycle and session.
+ * Context of a {@link IManageablePage} when it is stored in an {@link IPageStore}, decoupling it
+ * from request cycle and session.
  * 
  * @author Matej Knopp
  * @author svenmeier
@@ -31,79 +34,51 @@ import org.apache.wicket.page.IManageablePage;
 public interface IPageContext
 {
 	/**
-	 * Set data into the current request.
+	 * Get data from the current request cycle.
 	 * 
 	 * @param key
 	 *            key
-	 * @param value
-	 *            value
+	 * @param defaultValue
+	 *            default value to use if not present
+	 * 
+	 * @see RequestCycle#getMetaData(MetaDataKey)
 	 */
-	<T> void setRequestData(MetaDataKey<T> key, T value);
+	<T> T getRequestData(MetaDataKey<T> key, Supplier<T> defaultValue);
 
 	/**
-	 * Get data from the current request.
+	 * Get an attribute from the session. <br>
+	 * Binds the session if not already set and supplied default value is not <code>null</code>.
 	 * 
 	 * @param key
 	 *            key
+	 * @param defaultValue
+	 *            default value to use if not present
 	 * @return value
-	 */
-	<T> T getRequestData(MetaDataKey<T> key);
-
-	/**
-	 * Set an attribute in the session. Binds the session.
 	 * 
-	 * @param key
-	 *            key
-	 * @param value
-	 *            value
+	 * @see Session#getAttribute(String)
 	 */
-	<T extends Serializable> void setSessionAttribute(String key, T value);
+	<T extends Serializable> T getSessionAttribute(String key, Supplier<T> defaultValue);
 
 	/**
-	 * Get an attribute from the session.
-	 * 
-	 * @param key
-	 *            key
-	 * @param value
-	 *            value
-	 */
-	<T extends Serializable> T getSessionAttribute(String key);
-
-	/**
-	 * Set data into the session - only if it is not set already. Binds the session.
-	 * <p>
-	 * Recommended usage:
-	 * <pre>
-	 * <code>
-	 * SessionData data = context.getSessionData(KEY);
-	 * if (data == null)
-	 * {
-	 *     data = context.setSessionData(KEY, new SessionData());
-	 * }
-	 * </code>
-	 * </pre>
+	 * Get metadata from the session. <br>
+	 * Binds the session if not already set and supplied default value is not <code>null</code>.
 	 *
 	 * @param key
 	 *            key
-	 * @param value
-	 *            value
-	 * @return the old value if already present, or the new value
-	 */
-	<T extends Serializable> T setSessionData(MetaDataKey<T> key, T value);
-
-	/**
-	 * Get data from the session.
-	 * 
-	 * @param key
-	 *            key
+	 * @param defaultValue
+	 *            default value to use if not present
 	 * @return value
+	 * 
+	 * @see Session#getMetaData(MetaDataKey)
 	 */
-	<T extends Serializable> T getSessionData(MetaDataKey<T> key);
+	<T extends Serializable> T getSessionData(MetaDataKey<T> key, Supplier<T> defaultValue);
 
 	/**
-	 * Get the identifier of the session. Binds the session.
+	 * Get the identifier of the session.
 	 * 
-	 * @return session id
+	 * @param bind
+	 *            should the session be bound
+	 * @return session id, might be <code>null</code> if not bound yet
 	 */
-	String getSessionId();
+	String getSessionId(boolean bind);
 }
\ No newline at end of file
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/InSessionPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/InSessionPageStore.java
index b33690c..3f1275e 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/InSessionPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/InSessionPageStore.java
@@ -165,11 +165,16 @@ public class InSessionPageStore extends DelegatingPageStore
 
 	private SessionData getSessionData(IPageContext context, boolean create)
 	{
-		SessionData data = context.getSessionData(KEY);
-		if (data == null && create)
-		{
-			data = context.setSessionData(KEY, dataCreator.get());
-		}
+		SessionData data = context.getSessionData(KEY, () -> {
+			if (create)
+			{
+				return dataCreator.get();
+			}
+			else
+			{
+				return null;
+			}
+		});
 
 		if (data != null && serializer != null)
 		{
diff --git a/wicket-core/src/main/java/org/apache/wicket/pageStore/RequestPageStore.java b/wicket-core/src/main/java/org/apache/wicket/pageStore/RequestPageStore.java
index f7ee6d8..0355774 100644
--- a/wicket-core/src/main/java/org/apache/wicket/pageStore/RequestPageStore.java
+++ b/wicket-core/src/main/java/org/apache/wicket/pageStore/RequestPageStore.java
@@ -106,14 +106,7 @@ public class RequestPageStore extends DelegatingPageStore
 
 	private RequestData getRequestData(IPageContext context)
 	{
-		RequestData requestData = context.getRequestData(KEY);
-		if (requestData == null)
-		{
-			requestData = new RequestData();
-
-			context.setRequestData(KEY, requestData);
-		}
-		return requestData;
+		return context.getRequestData(KEY, () -> new RequestData());
 	}
 	
 	/**
diff --git a/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/TestMapperContext.java b/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/TestMapperContext.java
index 247004c..4129c66 100644
--- a/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/TestMapperContext.java
+++ b/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/TestMapperContext.java
@@ -20,9 +20,9 @@ import org.apache.wicket.MockPage;
 import org.apache.wicket.WicketRuntimeException;
 import org.apache.wicket.core.request.handler.PageProvider;
 import org.apache.wicket.markup.MarkupParser;
+import org.apache.wicket.mock.MockPageContext;
 import org.apache.wicket.page.IPageManager;
 import org.apache.wicket.page.PageManager;
-import org.apache.wicket.pageStore.DummyPageContext;
 import org.apache.wicket.pageStore.IPageContext;
 import org.apache.wicket.pageStore.InMemoryPageStore;
 import org.apache.wicket.pageStore.InSessionPageStore;
@@ -45,7 +45,7 @@ public class TestMapperContext implements IMapperContext
 	private static int count;
 
 	InSessionPageStore pageStore;
-	DummyPageContext pageContext;
+	MockPageContext pageContext;
 	IPageManager pageManager;
 	private String appName;
 	private boolean createMockPageIfInstanceNotFound = true;
@@ -57,7 +57,7 @@ public class TestMapperContext implements IMapperContext
 	{
 		appName = APP_NAME + count++;
 		
-		pageContext = new DummyPageContext();
+		pageContext = new MockPageContext();
 		
 		InMemoryPageStore inMemoryPageStore = new InMemoryPageStore(appName, Integer.MAX_VALUE);
 		pageStore = new InSessionPageStore(inMemoryPageStore, 4, new JavaSerializer(appName));
diff --git a/wicket-core/src/test/java/org/apache/wicket/page/PersistentPageManagerTest.java b/wicket-core/src/test/java/org/apache/wicket/page/PersistentPageManagerTest.java
index 046a1ec..eea83bf 100644
--- a/wicket-core/src/test/java/org/apache/wicket/page/PersistentPageManagerTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/page/PersistentPageManagerTest.java
@@ -23,11 +23,12 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import java.io.IOException;
 import java.io.Serializable;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
 
 import org.apache.wicket.Application;
 import org.apache.wicket.MetaDataKey;
 import org.apache.wicket.ThreadContext;
-import org.apache.wicket.pageStore.DummyPageContext;
+import org.apache.wicket.mock.MockPageContext;
 import org.apache.wicket.pageStore.IPageContext;
 import org.apache.wicket.pageStore.IPageStore;
 import org.apache.wicket.pageStore.InSessionPageStore;
@@ -110,22 +111,19 @@ class PersistentPageManagerTest
 			@Override
 			protected IPageContext createPageContext()
 			{
-				return new DummyPageContext() {
+				return new MockPageContext() {
 					@Override
-					public <T extends Serializable> T setSessionData(MetaDataKey<T> key, T value)
+					public <T extends Serializable> T getSessionData(MetaDataKey<T> key, Supplier<T> defaultValue)
 					{
-						super.setSessionData(key, value);
-						
-						sessionData.set(value);
-						
+						T value = (T)sessionData.get();
+						if (value == null) {
+							value = defaultValue.get();
+							if (value != null) {
+								sessionData.set(value);
+							}
+						}
 						return value;
 					}
-					
-					@Override
-					public <T extends Serializable> T getSessionData(MetaDataKey<T> key)
-					{
-						return (T)sessionData.get();
-					}
 				};
 			}
 		};
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractConcurrentPageStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractConcurrentPageStoreTest.java
index a1fce22..793af30 100644
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractConcurrentPageStoreTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractConcurrentPageStoreTest.java
@@ -29,6 +29,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import org.apache.wicket.mock.MockPageContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -54,7 +55,7 @@ public abstract class AbstractConcurrentPageStoreTest
 
 	private static IPageContext getContext(String sessionId)
 	{
-		IPageContext context = new DummyPageContext(sessionId);
+		IPageContext context = new MockPageContext(sessionId);
 
 		IPageContext existing = contexts.putIfAbsent(sessionId, context);
 		return existing != null ? existing : context;
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractPageStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractPageStoreTest.java
index 37f4e64..91f3066 100644
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractPageStoreTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/AbstractPageStoreTest.java
@@ -21,8 +21,10 @@ import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.fail;
 
 import java.io.Serializable;
+import java.util.function.Supplier;
 
 import org.apache.wicket.MetaDataKey;
+import org.apache.wicket.mock.MockPageContext;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -68,7 +70,7 @@ public abstract class AbstractPageStoreTest
 	@Test
 	void storePage()
 	{
-		IPageContext context = new DummyPageContext(sessionId);
+		IPageContext context = new MockPageContext(sessionId);
 		
 		pageStore.addPage(context, new SerializedPage(pageId, pageData));
 
@@ -83,7 +85,7 @@ public abstract class AbstractPageStoreTest
 	{
 		pageStore.destroy();
 		
-		IPageContext context = new DummyPageContext(sessionId);
+		IPageContext context = new MockPageContext(sessionId);
 		int maxEntries = 10;
 
 		pageStore = createPageStore(maxEntries);
@@ -101,7 +103,7 @@ public abstract class AbstractPageStoreTest
 	@Test
 	void removePage()
 	{
-		IPageContext context = new DummyPageContext(sessionId);
+		IPageContext context = new MockPageContext(sessionId);
 		
 		pageStore.addPage(context, new SerializedPage(pageId, pageData));
 
@@ -118,15 +120,23 @@ public abstract class AbstractPageStoreTest
 	@Test
 	void removeAllPagesDoesNotBindSession()
 	{
-		IPageContext context = new DummyPageContext(sessionId) {
+		IPageContext context = new MockPageContext(sessionId) {
 			@Override
-			public <T extends Serializable> void setSessionAttribute(String key, T value) {
-				fail();
+			public <T extends Serializable> T getSessionAttribute(String key, Supplier<T> value) {
+				if (value.get() != null) {
+					fail();
+				}
+				
+				return null;
 			}
 			
 			@Override
-			public <T extends Serializable> T setSessionData(MetaDataKey<T> key, T value) {
-				return fail();
+			public <T extends Serializable> T getSessionData(MetaDataKey<T> key, Supplier<T> value) {
+				if (value.get() != null) {
+					return fail();
+				}
+				
+				return null;
 			}
 		};
 		
@@ -136,15 +146,23 @@ public abstract class AbstractPageStoreTest
 	@Test
 	void removePageDoesNotBindSession()
 	{
-		IPageContext context = new DummyPageContext(sessionId) {
+		IPageContext context = new MockPageContext(sessionId) {
 			@Override
-			public <T extends Serializable> void setSessionAttribute(String key, T value) {
-				fail();
+			public <T extends Serializable> T getSessionAttribute(String key, Supplier<T> value) {
+				if (value.get() != null) {
+					fail();
+				}
+				
+				return null;
 			}
 			
 			@Override
-			public <T extends Serializable> T setSessionData(MetaDataKey<T> key, T value) {
-				return fail();
+			public <T extends Serializable> T getSessionData(MetaDataKey<T> key, Supplier<T> value) {
+				if (value.get() != null) {
+					return fail();
+				}
+				
+				return null;
 			}
 		};
 		
@@ -154,7 +172,7 @@ public abstract class AbstractPageStoreTest
 	@Test
 	void removeAllPages()
 	{
-		IPageContext context = new DummyPageContext(sessionId);
+		IPageContext context = new MockPageContext(sessionId);
 		
 		pageStore.addPage(context, new SerializedPage(pageId, pageData));
 
@@ -171,7 +189,7 @@ public abstract class AbstractPageStoreTest
 	@Test
 	void maxSizeSameSession()
 	{
-		IPageContext context = new DummyPageContext(sessionId);
+		IPageContext context = new MockPageContext(sessionId);
 		
 		pageStore.addPage(context, new SerializedPage(pageId, pageData));
 
@@ -190,8 +208,8 @@ public abstract class AbstractPageStoreTest
 	@Test
 	void maxSizeDifferentSessions()
 	{
-		IPageContext context = new DummyPageContext(sessionId);
-		IPageContext context2 = new DummyPageContext("0987654321");
+		IPageContext context = new MockPageContext(sessionId);
+		IPageContext context2 = new MockPageContext("0987654321");
 
 		pageStore.addPage(context, new SerializedPage(pageId, pageData));
 
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/AsynchronousDataStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/AsynchronousDataStoreTest.java
index 40da190..a4fd398 100644
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/AsynchronousDataStoreTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/AsynchronousDataStoreTest.java
@@ -22,6 +22,7 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
 import org.apache.wicket.MockPage;
+import org.apache.wicket.mock.MockPageContext;
 import org.apache.wicket.page.IManageablePage;
 import org.junit.jupiter.api.Test;
 
@@ -76,7 +77,7 @@ public class AsynchronousDataStoreTest
 
 	private static IPageContext createContext(String sessionId)
 	{
-		return new DummyPageContext(sessionId);
+		return new MockPageContext(sessionId);
 	}
 
 	private static abstract class AbstractTask implements Runnable
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/AsynchronousPageStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/AsynchronousPageStoreTest.java
index a2bfffe..0dd7cb4 100644
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/AsynchronousPageStoreTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/AsynchronousPageStoreTest.java
@@ -27,11 +27,13 @@ import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.commons.lang3.RandomUtils;
 import org.apache.wicket.MetaDataKey;
 import org.apache.wicket.MockPage;
 import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.mock.MockPageContext;
 import org.apache.wicket.mock.MockPageStore;
 import org.apache.wicket.page.IManageablePage;
 import org.apache.wicket.util.WicketTestTag;
@@ -152,7 +154,7 @@ public class AsynchronousPageStoreTest
 		
 		String sessionId = "sessionId";
 		
-		IPageContext context = new DummyPageContext(sessionId);
+		IPageContext context = new MockPageContext(sessionId);
 
 		SerializedPage page = new SerializedPage(pageId, "", new byte[0]);
 		asyncPageStore.addPage(context, page);
@@ -202,7 +204,7 @@ public class AsynchronousPageStoreTest
 		
 		String sessionId = "sessionId";
 		
-		IPageContext context = new DummyPageContext(sessionId);
+		IPageContext context = new MockPageContext(sessionId);
 
 		SerializedPage page = new SerializedPage(pageId, "", new byte[0]);
 		asyncPageStore.addPage(context, page);
@@ -306,27 +308,26 @@ public class AsynchronousPageStoreTest
 	 * Store does not allow modifications when pages are added asynchronously.
 	 */
 	@Test
-	public void storeAsynchronousContextClosed() throws InterruptedException
+	public void storeAsynchronousContextClosed() throws Throwable
 	{
+		final AtomicReference<Throwable> asyncFail = new AtomicReference<>();
+		
 		IPageStore store = new MockPageStore() {
 			
 			@Override
 			public boolean canBeAsynchronous(IPageContext context)
 			{
 				// can get session id
-				context.getSessionId();
+				context.getSessionId(true);
 				
 				// can access request data
-				context.getRequestData(KEY1);
-				context.setRequestData(KEY1, "value1");
+				assertEquals("value1", context.getRequestData(KEY1, () -> "value1"));
 
 				// can access session data
-				context.getSessionData(KEY1);
-				context.setSessionData(KEY1, "value1");
+				assertEquals("value1", context.getSessionData(KEY1, () -> "value1"));
 
 				// can access session
-				context.getSessionAttribute("key1");
-				context.setSessionAttribute("key1", "value1");
+				context.getSessionAttribute("key1", () -> "value1");
 
 				return true;
 			}
@@ -335,62 +336,36 @@ public class AsynchronousPageStoreTest
 			public synchronized void addPage(IPageContext context, IManageablePage page)
 			{
 				// can get session id
-				context.getSessionId();
+				context.getSessionId(true);
 				
 				// cannot access request
 				try {
-					context.getRequestData(KEY1);
-					fail();
-				} catch (WicketRuntimeException expected) {
-				}
-				try {
-					context.setRequestData(KEY1, "value1");
-					fail();
-				} catch (WicketRuntimeException expected) {
-				}
-				try {
-					context.getRequestData(KEY2);
-					fail();
+					context.getRequestData(KEY1, () -> null);
+					asyncFail.set(new Exception().fillInStackTrace());
 				} catch (WicketRuntimeException expected) {
 				}
 				try {
-					context.setRequestData(KEY2, "value2");
-					fail();
+					context.getRequestData(KEY2, () -> null);
+					asyncFail.set(new Exception().fillInStackTrace());
 				} catch (WicketRuntimeException expected) {
 				}
 
 				// can read session data 
-				context.getSessionData(KEY1);
-				context.getSessionData(KEY2);
+				assertEquals("value1", context.getSessionData(KEY1, () -> "value2"));
+				assertEquals(null, context.getSessionData(KEY2, () -> null));
 				// .. but cannot set
 				try {
-					context.setSessionData(KEY1, "value1");
-					fail();
-				} catch (WicketRuntimeException expected) {
-				}
-				try {
-					context.setSessionData(KEY2, "value2");
-					fail();
+					context.getSessionData(KEY2, () -> "value2");
+					asyncFail.set(new Exception().fillInStackTrace());
 				} catch (WicketRuntimeException expected) {
 				}
 				
-				// can read session already read
-				context.getSessionAttribute("key1");
+				// can read session attribute already read
+				assertEquals("value1", context.getSessionAttribute("key1", () -> null));
 				// .. but nothing new
 				try {
-					context.getSessionAttribute("key2");
-					fail();
-				} catch (WicketRuntimeException expected) {
-				}
-				// .. but cannot set
-				try {
-					context.setSessionAttribute("key1", "value1");
-					fail();
-				} catch (WicketRuntimeException expected) {
-				}
-				try {
-					context.setSessionAttribute("key2", "value2");
-					fail();
+					context.getSessionAttribute("key2", () -> null);
+					asyncFail.set(new Exception().fillInStackTrace());
 				} catch (WicketRuntimeException expected) {
 				}
 			}
@@ -400,11 +375,15 @@ public class AsynchronousPageStoreTest
 
 		MockPage page = new MockPage();
 		
-		IPageContext context = new DummyPageContext();
+		IPageContext context = new MockPageContext();
 		
 		asyncPageStore.addPage(context , page);
 		
 		store.destroy();
+		
+		if (asyncFail.get() != null) {
+			throw asyncFail.get();
+		}
 	}
 	
 	// test run
@@ -477,7 +456,7 @@ public class AsynchronousPageStoreTest
 			for (int i = 1; i <= sessions; i++)
 			{
 				String sessionId = String.valueOf(i);
-				IPageContext context = new DummyPageContext(sessionId);
+				IPageContext context = new MockPageContext(sessionId);
 				Metrics metrics = new Metrics();
 
 				stopwatch.reset();
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/CryptingPageStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/CryptingPageStoreTest.java
index a4b547e..d601d5d 100644
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/CryptingPageStoreTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/CryptingPageStoreTest.java
@@ -23,6 +23,7 @@ import java.security.GeneralSecurityException;
 
 import org.apache.wicket.MockPage;
 import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.mock.MockPageContext;
 import org.apache.wicket.mock.MockPageStore;
 import org.apache.wicket.serialize.java.JavaSerializer;
 import org.junit.jupiter.api.Test;
@@ -41,7 +42,7 @@ public class CryptingPageStoreTest
 		CryptingPageStore store = new CryptingPageStore(new MockPageStore());
 		JavaSerializer serializer = new JavaSerializer("test");
 
-		IPageContext context = new DummyPageContext();
+		IPageContext context = new MockPageContext();
 
 		for (int p = 0; p < 10; p++)
 		{
@@ -61,7 +62,7 @@ public class CryptingPageStoreTest
 		CryptingPageStore store = new CryptingPageStore(new MockPageStore());
 		JavaSerializer serializer = new JavaSerializer("test");
 
-		DummyPageContext context = new DummyPageContext();
+		MockPageContext context = new MockPageContext();
 
 		int p = 42;
 
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/GroupingPageStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/GroupingPageStoreTest.java
index e96aa92..5f2aba1 100644
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/GroupingPageStoreTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/GroupingPageStoreTest.java
@@ -21,9 +21,11 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.Serializable;
+import java.util.function.Supplier;
 
 import org.apache.wicket.MetaDataKey;
 import org.apache.wicket.MockPage;
+import org.apache.wicket.mock.MockPageContext;
 import org.apache.wicket.mock.MockPageStore;
 import org.apache.wicket.page.IManageablePage;
 import org.junit.jupiter.api.Test;
@@ -53,10 +55,10 @@ public class GroupingPageStoreTest
 			
 			public void addPage(IPageContext context, IManageablePage page) {
 
-				context.setSessionAttribute("attribute", "value");
-				context.setSessionData(KEY, VALUE);
+				context.getSessionAttribute("attribute", () -> "value");
+				context.getSessionData(KEY, () -> VALUE);
 
-				assertEquals(sessionId + "_" + group(page), context.getSessionId());
+				assertEquals(sessionId + "_" + group(page), context.getSessionId(true));
 				
 				super.addPage(context, page);
 			}
@@ -64,7 +66,7 @@ public class GroupingPageStoreTest
 			@Override
 			public void removeAllPages(IPageContext context)
 			{
-				assertEquals(sessionId + "_group1", context.getSessionId());
+				assertEquals(sessionId + "_group1", context.getSessionId(true));
 				
 				super.removeAllPages(context);
 			}
@@ -78,21 +80,21 @@ public class GroupingPageStoreTest
 			}
 		};
 		
-		DummyPageContext context = new DummyPageContext(sessionId) {
+		MockPageContext context = new MockPageContext(sessionId) {
 			@Override
-			public <T extends Serializable> T setSessionData(MetaDataKey<T> key, T value)
+			public <T extends Serializable> T getSessionData(MetaDataKey<T> key, Supplier<T> defaultValue)
 			{
-				assertFalse(value == VALUE, "group session data not set directly in session");
+				assertFalse(defaultValue.get() == VALUE, "group session data not set directly in session");
 				
-				return super.setSessionData(key, value);
+				return super.getSessionData(key, defaultValue);
 			}
 			
 			@Override
-			public <T extends Serializable> void setSessionAttribute(String key, T value)
+			public <T extends Serializable> T getSessionAttribute(String key, Supplier<T> value)
 			{
 				assertTrue(key.startsWith("attribute_group"), "group session attribute starts with group");
 				
-				super.setSessionAttribute(key, value);
+				return super.getSessionAttribute(key, value);
 			}
 		};
 		
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/RequestPageStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/RequestPageStoreTest.java
index b7fdf7a..ab7a4bc 100644
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/RequestPageStoreTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/RequestPageStoreTest.java
@@ -21,6 +21,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import org.apache.wicket.MockPage;
+import org.apache.wicket.mock.MockPageContext;
 import org.apache.wicket.mock.MockPageStore;
 import org.junit.jupiter.api.Test;
 
@@ -37,7 +38,7 @@ public class RequestPageStoreTest
 	{
 		MockPageStore mockStore = new MockPageStore();
 		
-		DummyPageContext context = new DummyPageContext();
+		MockPageContext context = new MockPageContext();
 
 		RequestPageStore store = new RequestPageStore(mockStore);
 		
diff --git a/wicket-core/src/test/java/org/apache/wicket/pageStore/SerializingPageStoreTest.java b/wicket-core/src/test/java/org/apache/wicket/pageStore/SerializingPageStoreTest.java
index a72a514..7e29839 100644
--- a/wicket-core/src/test/java/org/apache/wicket/pageStore/SerializingPageStoreTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/pageStore/SerializingPageStoreTest.java
@@ -19,6 +19,7 @@ package org.apache.wicket.pageStore;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import org.apache.wicket.MockPage;
+import org.apache.wicket.mock.MockPageContext;
 import org.apache.wicket.mock.MockPageStore;
 import org.apache.wicket.page.IManageablePage;
 import org.apache.wicket.serialize.java.JavaSerializer;
@@ -33,7 +34,7 @@ public class SerializingPageStoreTest
 	@Test
 	void test()
 	{
-		DummyPageContext context = new DummyPageContext();
+		MockPageContext context = new MockPageContext();
 		
 		MockPageStore mockStore = new MockPageStore();