Skip to content

Apache Wicket

It is a Java web application framework that focuses on making web development more object-oriented and component-based. Unlike traditional web frameworks that rely heavily on HTML templating with logic embedded in tags or scripts, Wicket allows developers to build web pages using pure Java and HTML with a clear separation of concerns.

Key Features of Apache Wicket:

  • Component-Based Architecture: You build your UI using reusable Java components like buttons, forms, panels, etc.Each component is tied to an HTML template file.
  • Pure Java Programming: All the logic is written in Java. No need for XML configuration or scripting inside HTML.
  • Separation of Concerns: HTML templates are clean and contain no Java code, and Java code has no HTML markup — promoting maintainability.
  • Type Safety: Thanks to Java’s strong typing, Wicket apps are often more robust and less error-prone.
  • Stateful by Default: Wicket keeps component state on the server, which can simplify complex interactions, though it can increase memory usage.
  • Built-in AJAX Support: AJAX behaviors can be added easily to components for dynamic content updates without writing JavaScript.
  • Internationalization (i18n): Easy support for localization via properties files and resource bundles.
Further information

Link: Apache Wicket

Apache Wicket – Best Practice

QWickie – Eclipse-Plugin

Eclipse Marketplace QWickie

Allows you to jump to the component in the HTML/JavaCode by Ctrl+Clicking on the WicketId.

jRebel

jRebel

Enables hot deployment in HTML, properties, and Java code. This makes code changes immediately visible without requiring a server restart.

Wicket Models

Models contain the values ​​that should be displayed or edited in the components. They implement the IModel interface, which has only two methods: setObject() and getObject(). Using models ensures that Wicket detects changes to the underlying objects and thus knows which parts of the GUI need to be re-evaluated to generate the final HTML. Furthermore, it is also possible to change the values ​​at a later time. This is not possible if the objects are used directly.

The concrete implementation of the various models differs considerably. The model system corresponds to the facade design pattern. Models are generally serialized and stored in the session, which is why the data must be serializable. However, the data can also be detached if this should be prevented or if it is not serializable.

Data should always be passed and stored in components via models.

It should be noted that models are only updated by FormComponent after both the conversion and validation have been successfully completed.

Static Models

With static models, the contained value does not change.

java
add(new Label("helloMessage", new Model<String>("Hello WicketWorld!")));

or with one of the factory methods:

java
add(new Label("helloMessage", Model.of("Hello WicketWorld!")));

This is a static model because the value in the model does not change. If the component needs to react dynamically, dynamic models must be used.

java
Label label = new Label("name", new Model(person.getName()));

is also a static model. In this case, a change to the person's name would not result in a change to the displayed text.

Dynamic Models

Dynamic models repeatedly evaluate the data as soon as it is changed. This means that the component always displays the current value. There are the following options to achieve this:

IModel Interface

Implementation of the IModel Interface (getObject or setObject)

PropertyModel

This model references a subobject/member of a bean via a property path.

This is done via reflections.

java
Label label = new Label("streetName", new PropertyModel(person, "address.street"));

This model is null-safe. This means that even if the address were null, an empty string would be returned, and no exception would occur. Even the root object can be null.

Access to Arrays, Lists, Maps

java
arrayElement.0.value (returns a value from the first list element)
arrayElement[0].value (returns a value from the first array element)
map[key].value.. (access to maps)

CompoundPropertyModel

With the CompoundPropertyModel, the wicketId (which identifies the element in HTML) is also used as a property expression. e.g.:

java
setDefaultModel(new CompoundPropertyModel(person));
Label label = new Label("address.street");

Furthermore, Wicket searches the component hierarchy until it finds a suitable model, since the component itself hasn't defined one. This makes it difficult to read.

Another disadvantage is that the refactoring problem is now exacerbated by the fact that the property names are now also used in the HTML.

DetachableModel

As described above, models (including the data) are persisted in the session.

If the data is large, the session can grow significantly, limiting the page history (which is also contained in the session).

To work around this, the LoadableDetachable model can be used. A load method must be implemented, which is called when the data needs to be reloaded (normally after each request).

The object is deleted after the detach() call.

Another use case is when you always want to read and display the most recent data, e.g., from a database. With the LoadableDetachableModel, the data is reloaded each time. Alternatively, you can reset the ModelObject in the onConfigure function.

AbstractReadOnlyModel

This model only implements getObject() (setObject() returns a NotImplementedException) and should be used for displays if you want to prevent the underlying object from being modified.

Attention: The getObject() may be called many times within a request – time-consuming operations should not be encapsulated in such a model.

ResourceModels

These models are used when text from a resource file is to be used. They go through the localizer, search for the corresponding text, and fill it with parameters if necessary.

ResourceModel

The ResourceModel takes a key as a parameter and uses it to resolve the text to be displayed.

java
add(new Label("greetings", new ResourceModel("label.greetings")));

To make the text more dynamic, the StringResourceModel can be used.

StringResourceModel

A model can be specified here that will be used to resolve the parameters.

java
add(new Label("greetings", new StringResourceModel("label.greetings", this, new Model(user))));

The corresponding resource property file:

java
label.greetings=Welcome, ${name}!

Wicketeer

Wicketeer

Wicketeer provides a way to use the PropertyModel in a type-safe manner. Example

java
IModel<String> streetModel = model(from(myPersonObject).getAdressData().getHomeAdress().getStreet());

The Wicketeer project should be available in all clients and should be the first choice for model implementation. Caution: If the "myPersonObject" parameter can be null, this will result in NPEs at runtime. To avoid this, the theoretically null object must be wrapped in its own model.

Never pass objects to components

Always wrap objects in models. This makes it possible to subsequently change/replace the object. Objects directly are serialized and cannot be changed afterwards.

Avoid passing components to other components

This creates a dependency between the individual components. If so, this is usually necessary to add one component to the AjaxTarget of another. It's better to use Wicket events.

Always pass the model to the parent component using super(model).

This way, Wicket takes care of the detachment, and the model can be evaluated using the generic getDefaultModel() method.

Typed Panels and Pages

Typed panels and pages make working with models much easier. This saves you a lot of casting and warnings from the IDE.

Do not use factories for components

Factories prevent further inheritance of components.

  • Constructor to prepare the models
  • onInitialize to add the components
  • onConfigure to control visibility, behavior that can change with each request.

Do not override isVisible and isEnabled

These methods are called very frequently during request processing. It is better to set them in onConfigure.

Use a request cache

If multiple identical services are used in individual components and these are rendered on a page, this can potentially lead to performance issues. This can be optimized by, for example, maintaining a cache of the called services in the request scope. However, you must be careful about data changes that would require an update.

Use Wicket:enclosure with care

If the Wicket:enclosure tag is used, it can sometimes lead to the Java code and markup becoming out of sync. The reason is that wicket:container is only considered during rendering. If multiple children are contained in the tag, the visibility will only be correct for the child specified in the tag. This can cause problems, for example, during testing. An alternative is to use EnclosureContainer.

Remove Comments

Comments in HTML should be avoided if they are visible to the end user. However, good documentation in HTML is sometimes very important, even in HTML. Apache Wicket offers two solutions for this.

<wicket:remove>

Everything within this tag is removed during rendering.

Application#getMarkupSettings().setStripComments(true)

This removes all HTML comments before rendering.

Contact: M_Bergmann AT gmx.at