Sunday, August 7, 2011

Wicket state

I heard a question from a colleague on Friday: In Wicket, what is a stateless form? That's easy to answer. It's a form that doesn't have any state. No kidding, really? But how do I know if my form has or has not a state? That's also easy to answer. If you create an instance of the class StatelessForm then your form does not maintain any state. Is it really as simple as that? Well, not exactly... First we need to understand what state means in Wicket.

Being a server-side web framework, Wicket must maintain the state of the web application for every user. When a user interacts with a Wicket web application and accesses a web page an instance of a Page subclass is stored in the memory. Pages visited previously by the user are serialized to the disk and can be loaded later should the user visit them again. But what if a page can have multiple states during a session? Does Wicket serialize every different state of the page to the disk? No, that's not the case. There's another state-handling mechanism, called page versioning, which maintains the current state of the page by logging the changes made to the page. Should the user work only forward only the current state of the pages are important, but should he go backward the previous states and versions become equally important. Both page serialization and versioning happen automatically and every default Wicket component logs the changes to their own state. Custom components on the other hand - like a subclass of the Page class with some declared fields - must implement their own logger by extending the Change class and registering a new instance of this class with the Component.addStateChange(Change) method every time when the page's state changes.

Everything mentioned above, however, is only true for stateful Wicket pages. If the page is stateless then there's no need to version it, to keep it in the session, or to serialize it to the disk, since stateless pages can be instantiated every time when they're needed. So what are the prerequisites of a stateless page? A page is considered stateless if it is bookmarkable and it contains only stateless components. This requires a little bit of explanation.

Bookmarkable page means that a URL can be assigned to the page and this URL does not contain any session-related information, so when the user clicks the link, a new instance of the Page is created. To make a page bookmarkable it must have either a default no-arg constructor, or a constructor that accepts a PageParameters argument, or both. Pages not having such constructors (or these constructors are not public) can only be instantiated from within another page for there's no way Wicket can figure it out what constructor to use with what arguments. When the user first visits a non-bookmarkable page, Wicket serializes it to the session because the only way to recreate the page without the constructors when the user returns to it is to deserialize it. For this reason, every page without the aforementioned two public constructors are considered stateful even if they don't maintain any real state.

Stateless components are components where the stateless hint says they're stateless and the hint of every behavior added to them says the behavior is stateless. Wicket operates in stateless mode by default (as long as the pages have at least one of the two constructors) because most of the Wicket components are stateless. Keep in mind though, that as soon as you add a Link or a Form to your page, or add an AJAX behavior to any of the components contained by the page, Wicket silently switches to stateful mode. If you want to keep your application stateless, you can always use the StatelessForm and StatelssLink components coming with Wicket, which are the same as Form and Link except their stateless hint says they're stateless.

In the first paragraph I asked the question if having a stateless form is really as simple as creating a new instance of the StatelessForm class. I just mentioned that a stateless form only hints that it's stateless but it's still up to you to make it sure that it does not rely on anything else but the data coming from the HTTP request. If the stateless form uses any field from the containing page then it isn't really stateless - unless the page is stateless. Using stateless forms in stateful pages is of course possible, but in my opinion it doesn't make any sense, since the page gets serialized to the session anyway, and stateless forms are meant to help keeping your application stateless.


Post a Comment