By nature a page is stateless, i.e. a new instance is created for each request and discarded at the end. A page becomes stateful as soon as a stateful behavior or component is added in the tree. Stateful pages are stored in a storage for later use, i.e. in following requests the same page instance is reused instead of creating a new instance. Technically, the page may be deserialized so it is not always the same JVM instance but the important thing is that any state/data in the page will be preserved.
A Component declares that it needs to be stateful by returning false in #getStatelessHint() method:
protected boolean getStatelessHint()
{
return false;
}
and Behavior by overriding:
public boolean getStatelessHint(Component component)
{
return false;
}
package org.apache.wicket.reference.stateless;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.link.Link;
public class StatefulPage extends WebPage
{
private int counter = 0;
public StatefulPage()
{
add(new Link<Void>("link") {
@Override
public void onClick()
{
counter++;
}
});
}
public int getCounter() {
return counter;
}
}
Click on an Link will lead to a request that will try to find the Page object that contains this link, then find the link itself in that page and finally execute its #onClick() method. The value of counter field will increment for each click on the link.
If StatelessLink is used instead:
package org.apache.wicket.reference.stateless;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.link.StatelessLink;
public class StatelessPage extends WebPage
{
private int counter = 0;
public StatelessPage()
{
add(new StatelessLink<Void>("link") {
@Override
public void onClick()
{
counter++;
}
});
}
public int getCounter() {
return counter;
}
}
then the value of counter field will always be 0 because a new instance of StatelessPage is created for each click on the link.
To make sure that a page is stateless and there is no stateful component/behavior added to it by accident StatelessChecker can be used. If there is a stateful component or behavior then this checker will throw an exception with a message explaining where is the problem.
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket-devutils</artifactId>
<version>${wicket.version}<version>
</dependency>
Register StatelessChecker as a listener that is invoked before rendering the page:
MyApplication.java
@Override
protected void init()
{
super.init();
getComponentPreOnBeforeRenderListeners().add(new org.apache.wicket.devutils.stateless.StatelessChecker());
}
Use StatelessComponent annotation to require the page to be stateless.
@org.apache.wicket.devutils.stateless.StatelessComponent
public class CheckedPage extends WebPage