Web development with Wicket, Part 2: Reducing and re-using code

You think code reuse is an elusive ideal? Wicket says think again

When you're building any kind of complex application, you want to re-use as much code as possible. The problem is, you may find yourself stymied by components that are just different enough that you have to build them from scratch. In this second installment in Nathan Hamblen's introduction to Web development with Wicket, you'll see how this open source, component-based Web application framework gets around such problems, greatly reducing the amount of code you need to cut and paste.

While small-scale code reuse is often impractical in a traditional Web rendering path, Wicket's ambitiously object-oriented rendering engine fosters sharing of both user-interface logic and layout among pages. By encouraging pragmatic, everyday code reuse, Wicket brings the best of desktop application programming to the Web.

This series, which began with an article on stateful and stateless modes of Wicket development, now moves on to the rendering engine that is built on that abstracted state. What does it take to make custom components, and how do they facilitate reuse? To find out, you'll take the sample calculator application from the previous article in this series and refactor it to eliminate its redundant layout code, then proceed to apply permutations of calculators to a pair of application pages.

From pages to panels

A WebPage subclass is itself a custom component: if you've programmed in Wicket, you've authored components in Wicket (no certification required). But pages are pretty monolithic. The most common way to make a portion of one page reusable is to move that part into a panel. Like a page, a Wicket panel has an associated HTML template file. It incorporates chunks of layout and functionality that can be dropped into any page of an application.

In migrating functionality from a page to a panel, the first step is to create a new Panel subclass. As a normal component (not a page), the Panel must be initialized with a component identifier; your subclass constructor must call super() with an ID. For the calculator application, you'll want a base class with two subclasses, similar to the old BasePage hierarchy, but with shared layout. Listing 1 shows the base panel class.

Listing 1. Base calculator panel and constructor

public abstract class CalcPanel extends Panel {
  public CalcPanel(String id) {
    super(id);
  }
  enum Op { ...

The next step is to make subclasses from the two page variants by moving the code en masse to new panels, changing only the constructors. Listing 2 outlines the class declarations and constructors.

Listing 2. Calculator subclasses

public class StatelessCalcPanel extends CalcPanel {
  protected BigDecimal buf = BigDecimal.ZERO;
  protected BigDecimal input = BigDecimal.ZERO;
  protected Op op;

  public StatelessCalcPanel(String id) {
    super(id);
    add(new CalcForm("form"));
  }
  class CalcForm extends StatelessForm {
    ...
  }
}

public class StatelessCalcPanel extends CalcPanel {
  protected BigDecimal buf = BigDecimal.ZERO;
  protected BigDecimal input = BigDecimal.ZERO;
  protected Op op;

  public StatelessCalcPanel(String id) {
    super(id);
    add(new CalcForm("form"));
  }
  class CalcForm extends StatelessForm {
    ...
  }
}

At this point, you could make similarly superficial adjustments to the markup templates and have two panels that replicate the functionality of the original two pages. But instead, in this article you'll see an implementation that will improve on the original with Wicket's markup inheritance, a simple technique for layout reuse that provides an extension point for subclasses.

1 2 3 4 5 Page 1
Page 1 of 5