
During request handling, Wicket manages page instances through interface _org.apache.wicket.request.handler.IPageProvider_. This interface creates a new page instance or loads a previously serialized page instance if we provide the corresponding page id. _IPageProvider_ delegates page creation and retrieval to interface _org.apache.wicket.core.request.mapper.IPageSource_.
When page class is provided _IPageSource_ delegates page creation to interface _org.apache.wicket.IPageFactory_, while when page id is provided it uses interface _org.apache.wicket.page.IPageManager_ to load the previously serialized page.

The following workflow diagram summarizes the mechanism seen so far:

image::./img/page-storage.png[]

=== IPageManager

_org.apache.wicket.page.IPageManager_'s task is to manage which pages have been used in a request and store their last state in the backing stores, namely _IPageStore_.
The default implementation _org.apache.wicket.page.PageManager_ uses a chain of _IPageStore_ to collect all stateful pages which have been used in the request cycle and store them for a later use.

NOTE: Keep in mind that more than one page can be used in a single request if, for example, _setResponsePage()_ or _RestartResponseException_ are used.

As said on <<versioningCaching.adoc#_page_caching,paragraph 8.2.4>> stateful pages are stored in a session-relative file using a two-levels cache to speedup the access. This process is made possible by the different implementations of _IPageStore_ that are part of the default chain and that will be introduced in the next paragraph.

NOTE: Wicket gets the default _IPageManager_ using a supplier interface called _IPageManagerProvider_,hence to use a custom _IPageManager_ implementation we must register a specific _IPageManagerProvider_ via _org.apache.wicket.Application.setPageManagerProvider(IPageManagerProvider)_.

=== Default IPageStore chain

_org.apache.wicket.pageStore.IPageStore_'s role is to mediate the storing and loading of page instances. The default chain of _IPageStore_ used by Wicket contains the following ordered list of _IPageStore_:

* *RequestPageStore:* collect all page instances involved in the last request. During the detach stage, stateful pages are passed to the other steps of the chain to be persisted on file.
* *InSessionPageStore:* with _InSessionPageStore_ the default chain keeps the last rendered page instance into the HTTP session for fast access.
* *SerializingPageStore:* _SerializingPageStore_ turns page instances into a more serialization-friendly format represented by class _org.apache.wicket.pageStore.SerializedPage_. This is a struct of:

[source,java]
----
{
   pageType: String,
   pageId : int,
   data : byte[]
}
----

i.e. this is the serialized page instance (data) plus additional information needed to be able to easily find it later (pageId, pageType).

* *AsynchronousPageStore:* The role of _AsynchronousPageStore_ is to detach the http worker thread from waiting for the write of the page bytes to the disk. To disable it use: _org.apache.wicket.settings.StoreSettings.setAsynchronous(false)_. _AsynchronousPageStore_ can delay the storage of page's bytes for at most _org.apache.wicket.settings.StoreSettings.setAsynchronousQueueCapacity(int)_ pages. If this capacity is exceeded then the page's bytes are written synchronously to the backing _IPageStore_.

* *CryptingPageStore:* page instances might contain sensible information, therefore it's important to have the chance to encrypt their content before persist them on disk. _CryptingPageStore_ encrypts _SerializedPage_'s with a 256 bit AES key, held in the session, before passing them to the underlying _DiskPageStore_. By default this stage is disabled and not added to the default chain. To change this behavior we can use _org.apache.wicket.settings.StoreSettings.setEncrypted_. What that encryption protects against depends on the crypter in use - see <<pagestore-choosing-a-crypter,Choosing a crypter for CryptingPageStore>> below.

* *DiskPageStore:* stores _SerializedPage_ on a session-scoped file on disk. The location of the folder where the files are stored is configurable via _org.apache.wicket.settings.StoreSettings.setFileStoreFolder(File)_, by default the web container's work folder is used (ServletContext attribute 'javax.servlet.context.tempdir'). In this folder a sub-folder is created named _'applicationName-filestore'_.
This folder contains a sub-folder for each active http session. This session folder contains a single file named 'data' which contains the bytes for the pages. The size of this 'data' file is configurable via _org.apache.wicket.settings.StoreSettings.setMaxSizePerSession(Bytes)_. When this size is exceeded the newly stored files overwrite the oldest ones.

[#pagestore-choosing-a-crypter]
=== Choosing a crypter for CryptingPageStore

When page store encryption is enabled, the actual encryption is performed by an implementation of _org.apache.wicket.pageStore.crypt.ICrypter_, configurable with _org.apache.wicket.settings.StoreSettings.setCrypter_. Which implementation we pick determines what the encryption protects against, and the difference matters because Wicket deserializes whatever it reads back from the store:

* _DefaultCrypter_ (AES-256-CBC) is the default. It is *not* authenticated, so it provides confidentiality only: the stored pages are unreadable, but CBC ciphertext is malleable and its integrity is not verified on decryption, so someone able to write to the store can still influence what gets deserialized.
* _GCMSIVCrypter_ (AES-256-GCM-SIV) is authenticated. Modified or substituted ciphertext fails to decrypt instead of reaching the deserializer, which makes the stored bytes tamper-evident as well as confidential. It requires Bouncy Castle - an optional dependency of _wicket-core_ that we must add ourselves - and is noticeably slower, which is why it is not the default.

So if we enable encryption because the store lives somewhere we do not fully control, rather than merely to keep page contents private, we should select the authenticated crypter explicitly:

[source,java]
----
getStoreSettings().setEncrypted(true).setCrypter(GCMSIVCrypter::new);
----

In both cases the key is held in the session, so encryption protects the pages against parties who can read or write the stored bytes - not against one who already controls the session. A custom _ICrypter_ only provides tamper detection if the cipher it returns uses an AEAD mode.

=== InMemoryPageStore

An alternative _IPageStore_ we can use in a custom chain is _org.apache.wicket.pageStore.InMemoryPageStore_. This implementation stores pages in a session-relative variable which can be limited by size or by page instance number.

=== DebugBar

Further insights which can be valuable during debugging can be retrieved using the _org.apache.wicket.devutils.debugbar.DebugBar_ from wicket-devutils.jar. It's a panel which you simply add:

Java:
[source,java]
----
add(new DebugBar("debug"));
----

HTML:
[source,html]
----
<span wicket:id="debug"/>
----

