Wicket do's and don'ts

by Erik van OostenSeptember 16, 2009

In the past 2 years I worked in, and visited many development teams to help them implement divers Wicket applications. Some applications were mostly for visualizing stuff, some were full of forms, and some were full of Ajax tricks. This article contains some of the lessons I had to teach, or had to learn myself. I’ll present them as do’s and dont’s. They are:

  • Do use models
  • Don’t use an Ajax library without intimate knowledge of the library
  • Do make sure you understand the repeaters for high performance sites
  • Don’t overuse inheritance
  • Do keep markup in sync with the component code
  • Don’t try to do authorization from a servlet filter
  • Do take your time to override key Wicket features

Do use models

Number 1 on the list of smelly Wicket code is like this:

public IncomePanel(String id, Person person) {<br>
  super(id);<br>
  add(new Label("salary", person.getSalary()); // no model!<br>
}

There is not much wrong with this code, except for one little thing. Suppose that IncomePanel also contains some logic to increase this person’s salary (e.g. a button). Unfortunately, you will never see the new salary as the label got a fixed value during its construction; the label will not look for a new value during a second rendering.

We can correct the situation by passing a model to the label. In addition, it is good practice to use models for your own components (like IncomePanel). With this in mind the code becomes something like this:

public IncomePanel(String id, IModel&lt;Person&gt; personModel) {<br>
  super(id);<br>
  add(new Label("salary", new PropertyModel(personModel, "salary"));<br>
}

Or even this:

public IncomePanel(String id, IModel&lt;Person&gt; personModel) {<br>
  super(id, new CompoundPropertyModel(personModel);<br>
  add(new Label("salary");<br>
}

Don’t use an Ajax library without intimate knowledge of the library

You should never start using Hibernate if you do not know about tables, inner vs. outer joins, indexes, resolution of the datetime type you’re using etc, etc. Every sufficiently complex technology (such as Hibernate) is affected by something called leaky abstractions.

The problem of leaky abstraction can also occur when you use Wicket components that abstract away javascript libraries. In general you know you have leaky abstractions when you suddenly have to worry about implementation details. For example because the component does not work in certain circumstances.

I had such unpleasant experiences with the wicketstuff-yui library. The library has many nice capabilities, but is not very well maintained. Without YUI knowledge it is almost impossible to find the subtle bugs that can prevent all your AJAX components from working completely. We had a similar problem with the wicketstuff-tinymce library.

Do make sure you understand the repeaters for high performance sites

Repeaters are a family of components that allow you to display some HTML multiple times on a page. As you can guess, every web application has repeaters. Using repeaters wrongly can lead to unnecessary memory and CPU usage. Mostly this is not a big problem. For sites that require optimal performance, understanding the different repeaters is essential.

Wicket by default provides the following repeater: Loop, ListView, RepeatingView, RefreshingView, DataTable. This list is not even exhaustive; there are some more variations. Every repeater constructs a transient component for each iteration: the loop item. Every loop item has a Wicket model to look up the item’s data.

Here are some points to consider to choose the most optimal repeater:

  • Moment of data retrieval. Is it during construction only, or for each render again? During a re-render, is all data retrieved at once or one by one?
  • Moment the loop-item’s model is created. First time only, or again for each render, or does it retain existing models and only add/remove models as the underlying data changes (ItemReusePolicy)? Can you control the model creation?
  • Is pagination/sorting needed?

Answering these questions for each of these components is an article in itself. However, if you need every bit of performance, make sure you have someone on the team with this knowledge.

Don’t overuse inheritance

Wicket has a nifty feature which allows you to do markup inheritance. When a component extends a super component you have the option to embed its markup in the markup of the super component. Markup inheritance is extremely useful to provide a common page layout.

Unfortunately I have also seen serious misuse of markup inheritance. Signs you’re in trouble are:

  • common layout turned out to be slightly different on every page,
  • components are created by abstract methods (constructors should not call these),
  • there are getters to your components (breaks data hiding),
  • the constructor of the sub-class replaces a component that was created by the super-class (wasteful and unmaintainable) or
  • you add components while the wicket:id is not in the markup file of the current class (maintenance nightmare).

The remedy is to split of parts of the screen to separate components (e.g. Panels) and manage the complexity there.

Inheritance is probably the most overrated feature of object oriented languages. Most OO power comes from composition and data hiding. Even though Wicket makes extensive use of inheritance (and rightly so), this applies as much to Wicket code as to regular Java code.

Do keep markup in sync with the component code

Nothing is more frustrating then having trouble finding the html element that is associated with a given component or vice versa. Make sure you keep code and markup in sync or you will have maintenance nightmares.

Don’t try to do authorization from a servlet filter

It just won’t work. Wicket is full of generated URLs (yes, even if you mount every page) so authorization based on the URL is a fruitless exercise. You are better off by writing an IAuthorizationStrategy and configuring this in your Wicket application. Study the code of wicket-auth-roles to see how this can work. In addition you’ll get component based authorization, not just page based! (By the way, you’ll have no problems with filter based authentication.)

Do take your time to override key Wicket features

Wicket can be tweaked in all kinds of expected and unexpected ways. For example you can substitute your own resource messages provider, filter and change the markup as it is read from disk or completely override the request cycle handling. However, some of these extension points are not for the faint hearted and not likely to be right immediately. Make sure you have a number of iterations before it needs to be rock solid production ready.

Summary

Although Wicket is easy to work with, you can find yourself in situations that are not optimal, either because you did not find the best solution, or because you are working against the framework. In addition, please be careful when you take Wicket to the extreme.

Further reading: