Stateful? Stateless? Wicket accommodates both kinds of applications Wicket is a lightweight, component-oriented framework that does much to bring the easy, intuitive interfaces found in desktop applications to Java Web development. In this series Nathan Hamblen introduces key aspects of Wicket that differentiate it from other Web application frameworks. If you’re new to Wicket, this series will serve as an accessible and engaging introduction; if you’re already using the framework you’ll have fun with the well-crafted, hands-on exercises. This first article investigates Wicket’s virtual state, demonstrating the many ways Wicket accommodates both stateless and stateful Web application development.Wicket is a Java Web framework with an ambitious mission: supporting desktop-style application development for the Web. This goal has a two separate implications: not only should Wicket Web applications work as much like desktop apps as possible, but writing a Web app with Wicket should feel like writing a desktop app as well. Conceived and written by Jonathan Locke in 2004, the open source framework quickly attracted a cadre of contributors, steered itself towards Apache membership, and in 2007 became a top-level Apache project. Along the way, Wicket’s feature set grew in two directions: better integration with the traditional Web of static resources and locators, and support for the dynamic new Web emerging in Ajax technologies. Wicket’s judicious use of abstraction has allowed it to take on these divergent ends without entangling users in complexity.This series is written for those starting out in Wicket — or thinking about starting out — with insights for experienced users as well. I’ll explore the features that differentiate Wicket from other Java Web application frameworks, beginning in this article with the virtual application state that makes it all possible. How is stateful Wicket programming different from traditional Web programming? What are the advantages and disadvantages of stateful development, how is it best leveraged in an application, and how can it be eliminated if necessary? To answer these questions, we will walk through the creation of a stateful Wicket application, then mercilessly eliminate the application’s server-side state, to see what we’re left with. Overview of the Wicket engineIn typical desktop GUI programming, visual components of interfaces are modeled by software components that have individual state. To mimic this style, a Web framework must maintain a virtual application state for every user of the application. Extensive server-side state of any kind runs contrary to some trends in Web programming — those bound up in REST particularly — but Wicket supports virtual state in such a way that the costs are minimized, the benefits are maximized, and the degree of server-side state maintained is entirely up to the programmer. While it may not be right for every Web app, it is certainly better than extensive ad hoc use of the Web session in applications that require it.Because Wicket has always supported virtualized state and has been optimizing it over the course of several years, state management in version 1.3 of the framework is slightly more cryptic than in earlier versions, but also more efficient. When a user interacts with a stateful Wicket page, that page is retained in the server’s memory as an instance of a WebPage subclass. The objects for previous pages that the user has visited have been serialized to disk (under the default configuration) and can be reloaded should the user request them. This is separate from page versioning, the mechanism that maintains state within a page, which is activated by logging changes made to the page’s state. Don’t worry if these points seem a bit dense; they will all take shape in the example application.The page templateSketching out the interface is a good place to start. Because this is a Wicket application you’ll also be able to leverage all of the HTML from the sketch for the final runtime. This article’s sample application (you can download the source code from the Resources section) is a calculator that resembles those shipping with most operating systems, which in turn resemble those sitting on many physical desktops. The calculator will support basic operations through addition, subtraction, multiplication, and division buttons, as well as equals and clear buttons that operate in the traditional way. A text field will serve as the numeric input between operations, with a separate block for the display. Listing 1 shows the basic HTML, Figure 1 the rendering.Listing 1. Calculator markup<form> <div> 0 </div> <div> <input value="0" type="text" /> <input value="=" type="submit" /> <input value="c" type="submit" /> </div><div> <input value="÷" type="submit" /> <input value="×" type="submit" /> <input value="-" type="submit" /> <input value="+" type="submit" /> </div> </form> Figure 1. Calculator rendering preview (click to enlarge)Notice that the code includes non-ASCII characters for some of the buttons. Modern Web browsers will have no problems displaying these labels. Furthermore, as long as the Wicket template begins with a correct encoding in the leading XML tag, these symbols will be read in and translated to whatever the request’s output encoding is.Now that you’ve laid out the interface the next step is to start binding it to executable code. The WebPage subclassAll regular Wicket Web pages subclass WebPage. They have the option of presenting a constructor that takes page parameters as arguments, or a default constructor that expects no parameters. In building the sample application, you’ll take the default constructor shown in Listing 2.Listing 2. Page constructor taking no parameterspublic StatefulPage() { add(new CalcForm("form")); } This is going to be the stateful page; later, you’ll create a separate page that doesn’t require server-side state. CalcForm is a subclass of Wicket’s Form base; it will add in all of its child components in its own constructor. The first string parameter passed to a component constructor is always the component identifier. In this case you are calling the form form and will need to reference it as such on the page template, as in Listing 3.Listing 3. Form with Wicket identifier<form wicket:id="form"> The wicket:id attribute is often the only attribute needed for a tag that is tied to the component hierarchy; in this case, Wicket will add action and method attributes. Now "form" has been added to the top level of the page in its constructor, and in the template it now also appears at the top level. That’s all it takes to tie the Java to the HTML. (I won’t show this step for the remaining components.) Event handlingBecause this calculator is meant to work like a physical calculator, the information needed for each operation will not be contained in the form fields submitted with each request. Consider the following interaction sequence:Enter “45”Press +Enter “4”Press =Each button press is a form submit, but when the equals button is pressed, the number “45” is no longer in the input element. In traditional Web programming, you would find a way to maintain this state in the form, the URL, or the session store. In Wicket, the first choice is to instead keep the value in a field of the page subclass. StatefulPage has three fields, shown in Listing 4.Listing 4. Fields of the StatefulPage classprotected BigDecimal buf = BigDecimal.ZERO; protected BigDecimal input = BigDecimal.ZERO; protected Op op; buf is the buffer that stores the present value in the calculator, the same value that appears in the display block of the template. The input field could have been otherwise represented, but storing it as a field is convenient, as you’ll see later in the example. The op field for the current operation is required for the same reason as buf; the form submit for = does not indicate the operation that should be applied to the current input. Op, shown in Listing 5, is an enum that encapsulates both the operation itself and its type. Listing 5. Op enum describing a calculator operationenum Op { add { @Override BigDecimal eval(BigDecimal a, BigDecimal b) { return a.add(b); } }, sub { @Override BigDecimal eval(BigDecimal a, BigDecimal b) { return a.subtract(b); } }, mult { @Override BigDecimal eval(BigDecimal a, BigDecimal b) { return a.multiply(b); } }, div { @Override BigDecimal eval(BigDecimal a, BigDecimal b) { return a.divide(b, 4, RoundingMode.HALF_UP); } }; abstract BigDecimal eval (BigDecimal a, BigDecimal b); } Using these these three fields, the apply() method performs the calculator’s current operation, as you can see in Listing 6.Listing 6. The apply() method of StatefulPagevoid apply() { if (op == null) buf = input; else buf = op.eval(buf, input); } Form componentsThe state and behavior of the Page class is similar to how a simple calculator might be modeled in a desktop application. The next step is to add in the Wicket components that make it work on the Web. Listing 7 shows the first of these components.Listing 7. Binding the buffer and input fieldsclass CalcForm extends Form { public CalcForm(String id) { super(id); add(new Label("display", new PropertyModel(StatefulPage.this, "buf"))); add(new TextField("input", new PropertyModel(StatefulPage.this, "input"))); Much of the code in Listing 7 might be unfamiliar. First, be aware that the CalcForm class is an inner class of StatefulPage, so it can access the page’s fields directly. It’s common in Wicket programming to subclass Form, even when you’re not overriding any of its methods, to organize the code around the component hierarchy. In this example, several components are inside the form; by adding them in its constructor, you establish that visually and eliminate the need to reference the form for each one. Listing 8 shows essentially the same component hierarchy, built using only the page constructor. Listing 8. Alternative component hierarchy constructionpublic StatefulPage() { Form form = new Form("form"); add(form); form.add(new Label("display", new PropertyModel(this, "buf"))); form.add(new TextField("input", new PropertyModel(this, "input"))); This is a question of individual preference, but as the number of components increases, the case for adding them in a subclass is strengthened.The models are another set of potentially confusing elements here. There are many ways to bind Wicket components to data via the IModel interface. The one selected here, the PropertyModel, binds the component to the named property of an existing object. In this case, that object is the page itself. The property binding can point to any Serializable object and even access private fields of that object. The next step, shown in Listing 9, adds two buttons.Listing 9. Clear and equals buttonsadd(new Button("clear") { @Override public void onSubmit() { buf = BigDecimal.ZERO; input = BigDecimal.ZERO; op = null; } }); add(new Button("eq") { @Override public void onSubmit() { apply(); } }); Anonymous subclasses are common in Wicket programming. The first Button subclass overrides onSubmit() to reset all fields to their original values when the “c” button, identified by "clear" in the code and markup, is pressed. The second applies the current operation to the page instance. The buttons don’t need to tell Listing 8’s Label component, for example, to update. When the object to which a component is bound by its model changes, the new value is reflected when that component renders. The remaining buttons are all operations; their common functionality is factored into the OpButton inner class in Listing 10.Listing 10. OpButton inner classclass OpButton extends Button { private Op myOp; public OpButton(String id, Op myOp) { super(id); this.myOp = myOp; } @Override public void onSubmit() { apply(); op = myOp; } } The only thing these do differently from the equals button is to update the op field after applying the current operation. If this seems strange, consider the following interaction sequence and keep in mind the behavior of a standard desktop calculator. (It might help to have one handy!)Enter “2”Press ×Enter “4”Press +Enter “1”Press =If you had updated the op field before calling apply(), step 2 would result in 0. And at step 4, even though a plus is entered, it’s the multiply operation that should be applied to the input and buffer at that time. The plus is finally applied when the equals button is pressed at step 6. Using the OpButton class, you can handily add the operation components, as shown in Listing 11.Listing 11. Adding operation components to the hierarchyadd(new OpButton("add", Op.add)); add(new OpButton("sub", Op.sub)); add(new OpButton("mult", Op.mult)); add(new OpButton("div", Op.div)); The application packageThat takes care of the functional aspects of this page. At this point, you may want to download the code package and try it out, if you haven’t already. The code leverages some of the techniques presented in my previous JavaWorld article, “Life outside the IDE,” by supplying both Maven and Buildr project files and including an embedded Jetty server. The fastest way to try out the app if you already have Maven installed is to run mvn compile exec:java from the project’s base directory. (See “Life outside the IDE” for more about Maven.)One thing to note in the codebase is that Op is defined in a BasePage class so that it can be easily reused in the next example. Other opportunities for reuse — like the entire page template — will be demonstrated in the next article of this series. But in this example, there is one more item to discuss. Page versioning and change trackingAs mentioned earlier, Wicket does not retain copies of every version of a particular page that a user visits. When working forward, this makes no difference; the application can twiddle any field of any accessible object, and the state will be strictly preserved for the next request. But should the user wish to go backward, there is no snapshot of the object at that time to return to.Components included with Wicket log changes to their state so that those changes can be undone to step back to prior versions. For example, if a user action triggers a change in component visibility, going back to reload the page will return that component to its prior state. But in the calculator example, StatefulPage is in fact a custom component with fields that define a new kind of state. If you want it to be able to work backward, you need to log changes within the component. This is easily done with the inner class shown in Listing 12.Listing 12. CalcChange object to log changes to the page stateprivate class CalcChange extends Change { final BigDecimal oldBuf = buf; final Op oldOp = op; @Override public void undo() { buf = oldBuf; op = oldOp; } } When this class is instantiated, it takes its own reference to the small immutable objects representing the current state. (The input field, being directly bound to a Wicket form component, has its state changes recorded automatically.) Using new instances of CalcChange each time, StatefulPage records existing values before they are overwritten, as in Listing 13. Listing 13. Recording the current state in the clear buttonadd(new Button("clear") { @Override public void onSubmit() { addStateChange(new CalcChange()); buf = BigDecimal.ZERO; input = BigDecimal.ZERO; op = null; } }); I left these calls left out of the original listings because they are so rare in practice. For most custom components, statefulness going forward is good enough. Recording Change objects is the last bit of polish you might add to a widely used component, or in a situation where Back button operation is crucial. In this case, it is a novelty: a calculator that can go backward and forward in time.Affairs of stateThe previous example made full use of the virtualized state that Wicket gives to Web applications. Because of this virtualized state, you could construct the calculator much as if it were a desktop application, with some additional work to support the Web’s notion of universal undo. The cost comes in server memory: each user that visits the page requires a session to hold his or her personal page instance. That same instance must be available to handle callbacks in the next request.It’s as easy to exaggerate the dangers of Wicket’s session use as it is to play them down. (You’ll find examples of both arguments on the Web.) Veteran programmers and managers, who already struggle with memory-hungry Java Web apps, may conclude that Wicket’s use of the session would only increase the departmental pain. But the truth is that many memory-hungry apps are just poorly put together. No one can say if the cost of storing certain things in memory is worthwhile because, too often, no one knows exactly what is eating up all that memory. The stateful side of Wicket works in the opposite direction: use server-side memory — because you’re going to have to anyway — but do it efficiently, transparently, and to maximum effect. What matters is the performance of the application against the user volume it actually faces. Web frameworks don’t support high-volume sites; applications do. In Wicket’s case, it is possible to eliminate the session requirement entirely from pages, and if you’re lucky enough to be generating the content for a URL that sees a million GETs a day, that’s a very good idea. For an internal ordering system, those concerns might be a bit premature.Memory consumption isn’t the only drawback of server-side state, however. As you interact with a stateful page in Wicket, the page location becomes disconnected from the page generated. If users are likely to want to bookmark or share the URL after interacting with a page, it’s better to maintain one that leads to that place, rather than to a session expired message.The next example shows how to dial back the remote state of a Wicket page, whether it’s to save the server’s memory or enhance the user’s satisfaction. The StatelessFormWicket operates in stateless mode by default, with the caveat that using most components will quietly turn this mode off. Any component instance is able to to veto stateless behavior for the page. To understand this, consider a page containing no components at all. There would be no need to retain the page instance to respond to callbacks, and it could be safely discarded at the end of the request. The same would be true if the page only had Label components. But as soon as you add a standard Link that responds in a callback, it becomes necessary to retain the entire page so that its fields and components are available in the future. Link therefore has a “stateless hint” of false, as does Form. But as Listing 14 shows, there is another parent form class.Listing 14. StatelessPage class and nested form subclasspublic class StatelessPage extends BasePage { protected BigDecimal buf = BigDecimal.ZERO; protected BigDecimal input = BigDecimal.ZERO; protected Op op; public StatelessPage() { add(new CalcForm("form")); } class CalcForm extends StatelessForm { The page subclass in Listing 14 is almost exactly like StatefulPage in Listings 2, 4, and 7, but here the form extends StatelessForm rather than Form. The StatelessForm class announces to the framework that all significant state is contained in the elements submitted with the form, and that it’s safe to discard the page instance and rebuild as needed. But we know from the last example that this isn’t correct, that the buf and op fields need to be retained. If you try to use a stateless form without preserving those fields (feel free to do so), no operation can be completed.To solve this problem, think about how you add invisible state to forms of any sessionless Web app: hidden form fields. All you need to do is map the missing state to hidden fields and the page can be fully rebuilt to respond to future requests. First, Listing 15 shows the needed additions to the page template.Listing 15. StatelessPage template with hidden form fields<form wicket:id="form"> <input type="hidden" wicket:id="buf" /> <input type="hidden" wicket:id="op" /> Listing 16 shows the beginning of the form constructor, which takes the opportunity to demonstrate another way of binding model values to components. Listing 16. Adding some components to the stateless formpublic CalcForm(String id) { super(id, new CompoundPropertyModel(StatelessPage.this)); add(new Label("display", new ComponentPropertyModel("buf"))); add(new HiddenField("buf")); While the PropertyModel used in StatefulPage was convenient for the two components that mapped to values, in this version there will be several more. By setting a CompoundPropertyModel, the form implicitly assigns a property model tied to the component identifier to all sub-components that have no models themselves. The buf hidden field component, then, has an implicit model for the buf property of StatelessPage.this. As for the display component, it wants the same property but cannot use the same identifier, so it uses a ComponentPropertyModel that implicitly works against the same base object using whatever property it’s constructed with. (Don’t worry, these model things get much easier over time.)Now the buffer is safely contained in the form and will be passed through from one request to the next; the op field, being a custom enum, is a bit more difficult. Wicket knows how to map a BigDecimal to and from a String in a hidden field, but it isn’t so sure about an Op. As Listing 17 shows, it needs a custom converter.Listing 17. Mapping the operation field with a custom converteradd(new HiddenField("op") { @Override public IConverter getConverter(Class type) { return new IConverter() { public Object convertToObject(String value, Locale locale) { return Strings.isEmpty(value) ? null : Op.valueOf(value); } public String convertToString(Object value, Locale locale) { return value.toString(); } }; } }); If Op were used elsewhere, it would be worthwhile to make this into a global OpConverter, but in-place works as well. Now the form submit includes all the state needed for the calculation. When run (from /calculator/stateless), this calculator looks and works exactly like the previous version. You can even go back to prior states and reload pages, without the need for recording with a CalcChange object. Because the form contains the full state, the browser history is itself the collection of state snapshots.One difference in this version is that the browser will prompt the user to resubmit the form on reloading, and the user must allow that in order for it to work; in contrast, the stateful version used a redirect after submit and doesn’t require form submission to present various page versions.Hey, is this thing on?Before celebrating victory with the stateless page, you’d better make sure that it is not actually creating a user session for some reason. The surest way to check this is to look out for a session cookie. Delete it and the stateful page will recreate when rendering (or give you an expired error if you’re already interacting with it), while the stateless page will not set a cookie or tack any identifier onto the URL throughout its use. Figures 2 and 3 show some cookie verification.Figure 2. Stateful page sets cookie at first rendering (click to enlarge)Figure 3. Stateless page will not set cookie after any interaction (click to enlarge)Stating the case for WicketThe stateless version of this article’s sample application is only a few lines longer than the initial version, hardly losing anything in the translation. It might seem as if every page should be made stateless, with Wicket acting as more of a template engine only — it is a fantastic template engine, as you’ll see in more detail in the next installment in this series. But to have a mandate for statelessness is to throw out half of the goodness in Wicket. Some elements of state cannot be so easily translated into hidden fields, and even for those that can, it’s a layer of conceptual overhead that may not be worth adding: working to eliminate state is a question of costs and benefits.The best way to program in Wicket, for beginners and experts alike, is to produce continuously evolving prototypes. Start with HTML that allows the kind of interaction you would like, then quickly build up an active component hierarchy that leverages the stateful environment. If that works well enough, congratulations: the prototype is the product. If reduced server-side state is required, to save memory or avoid session expirations, refine the prototype so that it uses little or no state.Programming in Wicket isn’t a permanent rejection of the statelessness of HTTP; it’s a license to bend the rules as long as doing so suits your code.Nathan Hamblen is a career software programmer who codes primarily in Java. In his spare, time he works on the Databinder toolkit for Wicket and writes Coderspiel, a programming Weblog. Open SourceWeb DevelopmentJavaSoftware DevelopmentDevelopment Approaches