JAX London 2014: A retrospective
Working with REAL Java Objects

Tutorial – Apache Wicket: The Fun Web Framework

JeremyThomerson
apache-wicket

Apache Wicket guru Jeremy Thomerson takes us on a tour of component-oriented Java UI web framework and when best to use it.

There is no lack of variety when choosing your Java technology stack. In attempts to get away from both the “roll your own [everything]” thinking that so many companies fall prey to, as well as the “everything must be a standard” philosophy of others, a wide range of varying approaches to each layer of the Java architecture has sprung up over the past years. The UI layer is no stranger to the struggle of competing technologies. With all of the options that you are presented with, how are you ever to choose? While no writer can make that choice for you, what we can do is introduce you to another option that you may want to consider, with the hopes that it will intrigue you enough to try it out. In this article, I’ll introduce you to Apache Wicket.

As you may suspect by the article’s title, Wicket is my preferred UI framework for most of the applications I write. Whether you end up sharing that same passion for this great framework – or whether it fits the type of application you desire to write – is up to you and your circumstances. But, read on and you may find another great technology to add to your “go-to” stack.

What is Wicket?

Wicket is a component-oriented Java web framework, which focuses on making it easy to write reusable code. It requires no XML configuration (aside from a few lines in your standard web.xml deployment descriptor), making it refreshing to work with. It encourages a clean separation between your logic and your markup, appealing to most programmers’ desire for a sense of order. With Wicket your code is “just Java” and your markup is “just HTML”. This makes it much easier for “HTML guys” to assist with the project without fear of messing something up and without having to learn a complex templating language, parameter names and values, et cetera.

Wicket appeals to a person who loves object-oriented programming. Each component on your page is a real Java object. It can hold state and perform useful functions just like any Java object. The nice thing about this is that this state persists through web requests to abstract the complexities of the stateless hyper-text transfer protocol from you. Imagine that you have a page that has an accordion-style panel in the side navigation bar, as well as a complex data table in the main content area. A user comes to this page and expands a section of the accordion. In your code, you may call setExpandedSection(index), or you may have setExpanded(true) on it and false on the others. However it is that you model your component, you can store that user-selection as a regular Java member variable inside your accordion component or one of its children. Now, when the user clicks a link to restore your complex data table, the table itself does not need to know about the state of the accordion component – or any other component on the page. But, the accordion component, as well as all the others, automatically retain their state throughout the various other requests that the user makes.

How does it work?

To achieve the level of UI complexity described above, many methodologies require that each component on the page has some level of knowledge of the other components on the page. In these other technologies, when I click a link in one component, it needs to embed the state of the other components into its request. Perhaps this goes in the URL, or perhaps it is stored in the session. Maybe each component has a cookie prefix and stores its state in a cookie. Or, perhaps your programmers get to spend most of their time configuring interactions between components in a complex XML file that ties the inputs and outputs of various components together. Whatever the case, it’s not simple programming – some of it isn’t even programming at all – and it requires a constant awareness of the fact that you are writing a stateful application on a stateless protocol.

Wicket gets around this by introducing a sort-of state engine to the HTTP interactions of our web applications. When a user first visits a page, an instance of a Java class is instantiated. When constructing that class, you construct its components just like you would instantiate any other Java class, i.e. new MyComponent(“SomeID”).

When the state of those components change, they store that state within themselves as real variables with real types. After that initial page render, though, Wicket does not discard the page object that was instantiated. The entire component hierarchy is stored in the user’s session (as well as disk in an efficient manner not detailed in this article). So, when they click a link to take some action on the page, submit a form, et cetera, all of that state is still contained in those classes. This is what makes it so simple (and fun!) to work with.

Now, the first thing that most people think is “won’t that use a ton of memory?” The answer is no! Many people have fallen for the trap of assuming that this method is a memory-waster, but then find that this amounts to premature optimization. That’s not to say that you can’t kick yourself while using Wicket – you can certainly do things that will make your session size explode. We will discuss more about that below in the section “What Are Models?”. If you’re really concerned about being able to validate my assertion that Wicket will not use more memory than other frameworks, you may want to check out this post and another post for a more elaborate comparison of Wicket versus several alternative frameworks (both written by Peter Thomas). If you can just trust me for now, continue on.

               

How to get started

Without further ado, how do you jump right in and try Wicket out? If you have Maven installed, it could not be any easier. Simply jump over to http://wicket.apache.org/start/quickstart.html, fill in your desired package group and artifact ID’s and run the provided command. A working quick-start application will be generated for you. Running mvn eclipse:eclipse (or the equivalent for your IDE) will set up the project dependencies. If you are using Eclipse go to the file menu, select Import, then Import an existing project and select the directory where your quickstart was generated. Find the Start.java file, open it, and run it. Navigate to http://localhost:8080 and you will see your “hello world” application in action. By running the Start class in your IDE’s debug mode (Eclipse: Debug as | Java application) instead of the normal run mode, you will be able to set breakpoints and debug your application to see how it works. For more complex quick-start applications featuring Spring, Guice, JPA, et cetera, see jWeekend’s excellent LegUp resources.

Hello World

The “hello world” part is already done for you by the archetype. So, let’s create a simple example of a link that increments a counter on the page. To get started (assuming you have the simple quickstart above running), find the HomePage.java and HomePage.html files and open them in your editor. Note that unless otherwise mentioned, all examples in this article will be based on the latest stable release, 1.4.18 (at the time of writing)

Let’s look at the HTML first. The first thing that you probably notice is that it is just regular HTML. This is by design. Markup should not contain logic – that’s Wicket’s philosophy. To tie a piece of markup to corresponding Java code that controls it you simply add the wicket:id attribute to it. We had two things in this markup that were dynamic. The most obvious was the link. The second is a span that renders the value of the counter on each page render. We use a span tag simply because we need a markup placeholder for the value to be inserted, and a span tag will not disrupt the structure of our other markup.

HomePage.html

 

<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" >
    <head>  
        <title>Wicket Quickstart Archetype Homepage</title>
    </head>
    <body>
        <strong>Wicket Quickstart Archetype Homepage</strong>
        <br/><br/>
        Click <a href="#" wicket:id="increment">this link</a> to increment 
        the following counter:<br />
        Counter: <span wicket:id="counter">123</span>
    </body>
</html>

 

Now, let’s look at the associated Java code. The first thing you should note is the name and placement of the files. By default, for any Wicket component (pages, as we are using here, are also components, so the same rule applies), Wicket will look in the same package directory on the classpath for a file with the same name, with the extension .html (if you are rendering XML, this would still apply, but with a .xml extension). This behavior can be re-configured, but for this article we will not get into that. There are online resources that can assist you with that if needed.

When you examine the actual code, you will see several parts. The first thing you see is the counterModel. You notice that it implements IModel. Models are extremely important in Wicket. They’re also generally one of the least understood concepts when programmers first adopt Wicket. We’ll discuss them more later. For now, suffice to say that they are a wrapper for retrieving or setting a piece of data, and this AbstractReadOnlyModel, as its name implies, is simply a wrapper for retrieving data. We implement the getObject method to retrieve the current value of counter on every invocation. This model is then passed to a Component. In this case the component is a Label. A label simply takes whatever tag it is associated to in the markup and replaces the body of that tag with the value retrieved from the model it is given. In this case, our span tag will replace “123” (its static body in the markup) with the value of our counter, which on the first page render will be zero.

The next thing you see is the link. It gives you just a glimpse of the power of Wicket. We’re using an anonymous inner class here to implement the link. If you had multiple places in your application that needed to increment an integer, you could replace this with a concrete class simply by extracting the anonymous inner class into a real top-level class.

Now, look at how simple it is to implement an action of any sort on a link. You simply override the onClick method and put your business logic in there. Obviously incrementing a counter is a simple example, but you could just as easily call a service- layer method that deleted or edited something in your domain, sent an email, or made a web service call. Wicket does the hard part for you. You implement the logic and you don’t have to worry about how to get a URL that will indicate to run that small bit of logic. You don’t have to worry about where to store the current state of the counter. All you have to do is write your code that performs the work that your application is designed to do. That’s why I love Wicket!

 HomePage.java

 

public class HomePage extends WebPage {
    private static final long serialVersionUID = 1L;

    private int counter = 0;
    
    public HomePage() {
        IModel<Integer> counterModel = new AbstractReadOnlyModel<Integer>() {
            private static final long serialVersionUID = 1L;

            @Override
            public Integer getObject() {
                return counter;
            }
        };

        Label label = new Label("counter", counterModel);
        add(label);
        
        Link<Void> link = new Link<Void>("increment") {
            private static final long serialVersionUID = 1L;

            @Override
            public void onClick() {
                counter++;
            }
        };
        add(link);
    }
}

 

               What about AJAX?

Okay, so it’s easy to make a link. So what, right? Now watch how easy it is to make that link an AJAX link that fully supports non-AJAX requests. First, we make our label instance final so that we can access it within the anonymous inner class and we call setOutputMarkupId(true) so that its unique ID is rendered in the span tag and it can be found in the DOM on the client-side. We change our Link class to AjaxFallbackLink and change the onClick method signature to match the superclass. The AjaxRequestTarget that is passed in can be thought of as a queue of things to send back in XML to the client side for processing. By adding the label to that queue, it will be re-rendered, streamed across the wire in XML and replaced in the DOM on the client-side. When it is re-rendered, it will use its model (remember counterModel?) to get the up-to-date value to render. All without us writing a line of code that does any transformations or DOM manipulation!

Why do we check if the AjaxRequestTarget is null? Because this link will automatically work for you on browsers that do not have JavaScript enabled. In this event, the page would simply re-render just like it did with a regular link. Yes, you heard me – it degrades gracefully without any additional work! Almost too good to be true, right? You’ll find that Wicket works this way for you by default most of the time. Form submissions and even file uploads can be done in either regular HTTP or AJAX with very little, if any, extra work. And in the 1.5 version, a very handy event mechanism is added to make the work of adding components to the AjaxRequestTarget even easier. 

HomePage.java (note: only the constructor is shown)

public HomePage() {
    IModel<Integer> counterModel = new AbstractReadOnlyModel<Integer>() { … }
    // above code folded for brevity

    final Label label = new Label("counter", counterModel);
    add(label.setOutputMarkupId(true));
    
    AjaxFallbackLink<Void> link = new AjaxFallbackLink<Void>("increment") {
        private static final long serialVersionUID = 1L;

        @Override
        public void onClick(AjaxRequestTarget target) {
            counter++;
            if (target != null)
                target.addComponent(label);
        }
    };
    add(link);
}

Working With User Input

In many web applications, a lot of the work to be done in building the app goes into the forms that accept user input. In Wicket, forms are regular objects just like all other components. To see an example, let’s look at a simple form that accepts a user’s name, email, and date of birth

 

Looking at the HTML, you see that there is nothing special about it. Your designers can give you an HTML form and you can add wicket:id attributes to the input fields and the form itself. The div with the wicket:id “feedback” is a placeholder for a built-in Wicket component that shows the user all feedback messages that were generated by the form. In the picture above, the user has just submitted the form with bad data which caused validation messages to appear in our feedback panel component. These can easily be customized to have a feedback panel near each form field that only shows the messages for that particular field – a common requirement in many applications.

Example of a Single Form

<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" >
    <head>  
        <title>Quickstart Homepage</title>
    </head>
    <body>
        Add / Edit Person:
        <div wicket:id="feedback"></div>
        <form wicket:id="form">
            First Name: <input type="text" wicket:id="firstName" /><br />
            Email Address: <input type="text" wicket:id="email" /><br />
            Date of Birth: <input type="text" wicket:id="dob" /><br />
            <input type="submit" value="Save" />
        </form>
    </body>
</html>

Now looking at the Java code, you see that we created two constructors. This is so the form can be used as both an “add person” and an “edit existing person” form. By default, the no-argument constructor is called which makes this an “add person” form because it is using a model that holds a new person. But, a link could easily be written that shows the user an “edit person” page simply by passing a model to the page with an existing person. (Note that we don’t cover that example in this article, but if you were doing this, you would likely want to use a LoadableDetachableModel, which is discussed more in the section on models.)

Next you see that we instantiate our Form object. We implement the onSubmit method and make it contain our business logic – in this case a simple call to a service-layer class. Moving along, you see where we create each field and configure it with our UI rules – which fields are required, and what is required of them (for instance, a valid email address format). What you don’t see is refreshing – no calls to HttpRequest to get strings out, no conversion of strings to dates, no manual retrieval of data from our form post and no manual setting of data on our backing Person object. In long forms, this saves hundreds of lines of copy-and-paste and highly error-prone code. This is because we are dealing with real Java objects – not a bunch of strings that have to be manually manipulated. See the form processing image in the “top ten” list and the link to the full top ten list below for more information.

Note that we are using a service-layer object (IPersonService) to do our persistence. This is a Spring-managed bean, and it is extremely simple to use because of Wicket’s built-in Spring (or Guice, if you prefer) integration.

Form object 

public class HomePage extends WebPage {
    
    @SpringBean
    IPersonService personService;
    
    public HomePage() {
        this(new Model<Person>(new Person()));
    }

    public HomePage(IModel<Person> model) {
        Form<Person> form = new Form<Person>("form", model) {
            protected void onSubmit() {
                Person person = this.getModelObject();
                System.out.println("Saving: " + person);
                personService.savePerson(person);
            }
        };
        
        TextField<String> firstName = new TextField<String>("firstName", new PropertyModel<String>(model, "firstName"));
        firstName.setRequired(true);
        form.add(firstName);
        
        TextField<Date> dob = new TextField<Date>("dob", new PropertyModel<Date>(model, "birthDate"));
        dob.setRequired(true);
        form.add(dob);
        
        TextField<String> email = new TextField<String>("email", new PropertyModel<String>(model, "emailAddress"));
        email.setRequired(true);
        email.add(EmailAddressValidator.getInstance());
        form.add(email);
        
        add(form);
        add(new FeedbackPanel("feedback"));
    }
}

What are Models?

In the code examples, you’ve seen several mentions of models, earlier described as “a wrapper for retrieving or setting a piece of data”. So, just what is a model, and why is it so important? As mentioned earlier, Wicket stores your entire component hierarchy (the page and all the components you added to it, as well as components added to those components and so on) in memory, and then to disk so that you have a stateful way of working with Java objects over the stateless HTTP. But these components that display this data do not necessarily need to store the data itself between requests. They only need to store their state – perhaps a flag indicating if they are visible or invisible, enabled or disabled, expanded or collapsed. It is very likely that the actual data they are displaying is already persisted elsewhere – likely in the database, meaning that we don’t really need to save it to the users’ HTTP sessions. This is one reason models exist – to cut down on the amount of memory needed to persist our component hierarchy.

A second, and just as important reason, is to abstract the retrieval and storage of data from the component itself. Think of our simple TextField component in our form example above. It does not need to know if the string that it is editing is coming from the session, from a web service, or from a field on a POJO. It simply needs to be able to get a string from somewhere and set an edited string somewhere. The IModel interface has two methods for this – getObject and setObject – that allow it to do just that. Before you start using Wicket, you should review my resource page on them too

      

Top 10 Things Every Wicket Programmer Should Know

 This is a condensed version of my list of the top ten things that every Wicket programmer should know. For the complete version, see http://wickettraining.com/resources/ten-things-every-wicket-programmer-should-know.html

  1. Models – Really make sure that you understand models before writing any large application in Wicket.
  2. Pull, don’t push – In general, your components should be able to pull their state rather than having some other component push the state on it. The example below demonstrates what this means and why it’s important. The key is that the constructor only runs once, but many things on the page might change state after the constructor is run. If you push your state into components in your constructor, they are out-of-date as soon as another component changes state. The only alternative is that every component must know about all other components that share state – and that’s not “the Wicket way”. Your components should be independent and reusable.
  3. Wicket is a UI framework – Don’t write middle tier or persistence code in Wicket.
  4. Keep markup and code clean and compact – Become familiar with and use the various aspects of Wicket that allow for reusability – panels, markup inheritance, and fragments as examples.
  5. Match your hierarchies – It won’t take you long at all to learn this rule, but the hierarchy of components in your markup (tags with a wicket:id attribute) must match the hierarchy in your Java code.
  6. Form processing lifecycle – When dealing with forms, it is important to understand the order of operations of the form post processing. If any step in the process fails the onError method of your form and submitting button will be called rather than the onSubmit method (picture below)
  7. Java nuances – There are two Java nuances that catch many Wicket newcomers off-guard – serialization and the presence of anonymous inner classes. Become more familiar with both.
  8. Unit testing – Testing your Wicket code is made relatively easy by using WicketTester. Try it out.
  9. i18n – Internationalization is made very easy with Wicket. Become familiar with things like wicket:message and file naming standards for Wicket’s built-in i18n support.
  10. Where to find help – Wicket code is well documented, so reading JavaDocs is a good start. Wicket examples can be viewed online at GitHub. Additionally, Wicket has one of busiest and most helpful mailing lists of any open source project. For more information on the Wicket mailing lists, see http://wicket.apache.org/help/email.html.

Conclusions

I chose Apache Wicket because other frameworks sucked the fun out of web programming (okay, this is subjective, but I can say that I didn’t personally enjoy them). Most of my time seemed to be spent dealing with pushing state around or writing configuration in XML. Every little change required changes in multiple files – many times in XML, Java, and specialized markup files. It was hard to make cohesive reusable components. A few days with Wicket made me see how drastically different it was. I was writing real Java object-oriented code, and easily creating reusable components. I hope that you will give it a few days for your own project or experiment so that you, too can discover how much fun web programming can be.

For more information on Wicket, see http://wickettraining.com/resources

Jeremy Thomerson is a technology enthusiast who loves exploring, learning, and creating new technologies. He has helped numerous companies upgrade their architectures to multi-tier architectures primarily based on the leading Java open source technologies, including Wicket, Spring, Lucene, Hibernate and more. For the past several years, he has owned and operated the leading U.S. company providing Wicket training and consulting services.

This article originally appeared in Java Tech Journal – Java Web Frameworks. You’ll find more of that issue here for download.

Author
JeremyThomerson
Jeremy Thomerson is a technology enthusiast who loves exploring, learning, and creating new technologies. He has helped numerous companies upgrade their architectures to multi-tier architectures primarily based on the leading Java open source technologies, including Wicket, Spring, Lucene, Hibernate and more. For the past several years, he has owned and operated the leading U.S. company, WicketTraining.com providing Wicket training and consulting services.
Comments
comments powered by Disqus