Wicket dropdowns with mismatched models

Sometimes you have a class containing an id of another (lets say a Machine class containing an owner id rather than an Owner object). The owner id is actually a primary key from the Owner table in the database. Now you want to display the Machine class in a wicket form with a dropdown to select the Owner.

In an ideal world, your Machine class would have “Owner getOwner()” and “setOwner (Owner owner)” methods and your MachineService class would have a static “List getOwners()” method and wicket’s DropDownChoice would just work with:

  final Form<machine> form = new Form<machine>("form", new CompoundPropertyModel<machine>(machine));
  add(form);
  form.add(new DropDownChoice("owner", MachineService.getOwners()));

However, in our Machine class, the owner property is an id of an Owner and not an Owner object. So how do we use the DropDownChoice without changing our Machine class? There are a few different approaches, but a simple one is to use a custom model with the DropDownChoice which converts between object and id representation, as follows:

  final Form<machine> form = new Form<machine>("form", new CompoundPropertyModel<machine>(machine));
  add(form);

  Model<owner> model = new Model<owner>() {
  private static final long serialVersionUID = 1L;
    @Override
    public Owner getObject() {
      if (machine.getOwner() == null)
	return null;
      return new Owner(machine.getOwner());
    }

    @Override
    public void setObject(Owner owner) {
      if (owner == null) {
        machine.setOwner(null);
      } else {
        machine.setOwner(owner.getOwnerNr());
      }
    }
 };
 form.add(new DropDownChoice<owner>("owner", model, ControlCenterService.getOwners()));

So now, when wicket needs to get the current selection, it calls getObject on your custom model and gets an object which it can compare. When it needs to set the selection, it calls setObject which writes the correct id into the machine object. Note: Your Machine class will need to implement toString() for the display in the dropdown. Additionally it will need a constructor which takes an id and an overridden equals() and hashCode() based on the id field.

Leave a Reply