As I promised in the previous post, today we will focus on transforming our unique name validator in Wicket to generic one. So now, let’s simply list what we are going to achieve;

  • validator should validate any entity object in our project
  • validator should check unique value of any property from validated object
  • error message should be generic too but customization should be easy

Generic DAO element

First thing we need is common query to load any entity with chosen property name and value. So we start with adding findByProperty method to DAO interface:

Next we implement this method in base DAO class named AbstractDAO:

Little explanation to the code above: we are using JPA2 Criteria Api which is one of the coolest new feature in the second edition of Java Persistence Api. As it’s not a main topic of this post, don’t expect detailed information about JPA2 here. I will just try to provide short description of each step:

  1. CritieriaBuilder is a factory for almost every method and object in Critieria API, so we use one here.
  2. CritieriaQuery specifies what we want to get from the database. In this case, we need object of class returned by getClazz() object.  getClazz() is a method from DAO interface which will be implemented in concrete DAO classes such as LocationDAOImpl.
  3. Root represents SQL ‘from’ clause.
  4. Predicates represent elements after SQL ‘where’.  We need only one, similar to ‘’where entity.propertyName = :propertyValue’ so we create it with CriteriaBuilder.
  5. Predicate to do its job, must be added to query.
  6. Finally, we can return found results (or null).

Generic validator

First step to create flexible validator is to rename it to more proper form. So now our class UniqueLocationNameValidator is UniqueEntityValidator. And since we are going to use classes other than only String for a validated property, we now can’t extend StringValidator. Instead of it, we will use  AbstractValidator. But as it’s generic we must introduce generic parameter too and signature of new class will look like this:

Then, as we are going to use any provided DAO instance, now we don’t inject LocationService to the validator but pass  DAO implementing class for validated entity with the constructor. Another thing needed when constructing validator object is property name which will be used in validation process and also by the DAO to try to load existing entity.

Ok, we are almost there. Let’s see how the most important method in our validator look like:

When I started writing this generic validator, I thought that onValidate will be more complicated. But it appeared that it’s very clean and simple solution (like most things in Wicket 🙂 ). We just use findByProperty method from passed with constructor DAO and that’s all.

Generic error message

Every Wicket validator provides two elements that can be shown with error message:  label of validated component and user input. So in our example we create UniqueEntityValidator.properties file and place it next to validator class with one message inside:

Here we can see how label and input elements are used. Wicket in a runtime replaces these placeholders with proper data. Label as a default is a Wicket componentId value, but it can be customized with component.setLabel(new Model(“customLabel”);

Of course this message can be changed in a simple way, we must only override method resourceKey() to return not validator class name but our new validator message key which will be used to find corresponding error message:

New message (key CustomValidator with our custom error message value) should be placed in proper properties file: PageClass.properties or Application.properties in most cases.

And, because we reached end of this post, we could see how new validator is uded in AddLocationPage:

Generic String property allows validator to know that validatable.getValue() in UniqueEntityValidator should return String object and no casting is necessary. This rule applies to any validator we use in this way: unique Integer value, unique Date, etc.

We’re done for today. Source code from this post can be viewed in this changeset in BitBucket repository and complete tutorial source is available here. At this moment I haven’t made a decision what will be the topic of next post. Maybe you can suggest something what you find most interesting in Wicket and I will try to implement such feature in ItemDirectory application 🙂

Thank you for your time!