Wicket in Action

A comprehensive guide for Java developers building Wicket-based web applications

Fixing Wicket Property Models Using Salve

Introduction

Ironically, property models are the most convenient and the most troublesome feature of wicket. Lets use the following code as an example:

new TextField(“zip”, 
    new PropertyModel(person, “addressBook.addresses.0.zip));

They are convenient because they make it trivial to bind components to domain objects using one line of code.

They are troublesome because they create code that is easily broken and whose breakage is not apparent until run time. For example: if the AddressBook#getAddresses() method used in the example above is renamed to AddressBook#getLocations() it will not cause a compilation error, but rather a runtime error when the page is rendered. This is a big problem unless every page of the webapp is covered by a unit test.

Possible Solutions

There are a couple of ways to fix the problem:

  • Do not use property models; instead create models that implement get/setObject methods using plain java code. Advantages: easy, refactor-safe, compile time errors. Disadvantage: extremely verbose, no default null handling in intermediate return values.
  • Use proxies to generate dynamic builders. Advantages: refactor-safe, compile time errors. Disadvantages: runtime overhead (negligible), use of proxies limits code features(cannot intercept final methods, etc), most likely cannot be inlined thus requires at least two lines of code instead of one.
  • Use a source code analyzer to check the expression string at compile time. Advantages: compile time errors, most visibility into code – can take advantage of generic types that are erased at runtime. Disadvantages: not refactor-safe, requires source for all classes used in the expression, extra compilation step.
  • Use apt to generate metadata about classes and use that metadata instead of the expression string. Advantages: transparent code generation in java 6, compile time errors. Disadvantages: not refactor-safe, only works for classes compiled with apt processor.
  • Use a bytecode analyzer to check the expression string at compile time or test time. Advantages: compile or test time errors, no extra compilation step if used in test time. Disadvantages: not refactor-safe.

Salve’s solution

The bytecode analyzer is what I chose to implement as part of Salve. It is implemented as a unit test that scans for use of salve.expr.Pe class that represents property expressions in Salve.

A property model usage with Salve’s Pe class can look something like this:

new TextField(“zip”, 
    new PropertyModel(person,
        new Pe(Person.class, “addressBook.addresses.0.zip).toString()));

While the unit test can be installed by creating a simple subclass of Salve’s PropertyExpressionTest within the project being checked:

public class ExpressionValidatorTest extends PropertyExpressionTest {}

When executed the unit test will scan for .class files in the project folder, look for instantiations of Pe class and check the string expression. Any error will cause the test to fail.

Using Pe class does make the code somewhat longer. The checker supports definitions of custom classes. For example we can create a more convenient version of the PropertyModel like so:

public class PeModel<T> extends PropertyModel<T>
{
    public PeModel(Object modelObject, Class< ? > clazz, String expression)
    {
        // we do not use the clazz param, it is only here for bytecode analyzer
        super(modelObject, expression);
    }
}

With usage:

new TextField(“zip”, 
    new PeModel(person, Person.class, “addressBook.addresses.0.zip));

And let the unit test know about it by specifying a matching rule:

public class ExpressionValidatorTest extends PropertyExpressionTest
{
 
    @Override
    protected Set<Rule> getRules()
    {
        Set<Rule> rules = super.getRules();
       rules.add(new Rule("commons/web/util/model/PeModel", Part.TYPE, Part.PATH));
        return rules;
    }
}

Rules match on the last x parameters. In the above example the rule will match instantiations of the PeModel class with constructor signature of (*,Class rootType, String path).

Another convenient usage pattern is binding components to fields of the parent via: new PropertyModel(this, “name”);. Salve’s checker supports this pattern like so:

    public PeModel(Object modelObject, String expression)
    {
        super(modelObject, expression);
    }
 
    rules.add(new Rule("commons/web/util/model/PeModel", Part.THIS, Part.PATH));

Installing Salve:

svn checkout http://salve.googlecode.com/svn/trunk/ salve
cd salve
mvn install

<dependency>
  <groupId>salve</groupId>
  <artifactId>salve-expr-validator</artifactId>
  <version>0.10-SNAPSHOT</version>
</dependency>

Conclusion

The code to all this is still brand new, raw, unfinished, undocumented, untested, etc. This is mainly a call out for feedback and ideas. Let me know what you think.

With this book, Wicket will become the greatest territory the Dutch have settled since Manhattan.

Nathan Hamblen
Senior Software Engineer, Teachscape Inc.

This is the complete and authoritative guide to Wicket, written and reviewed by the core members of the Apache Wicket team. If there's anything you want to know about Wicket, you are sure to find it in this book.

Jonathan Locke
Founder and Architect of Apache Wicket, Foreword Wicket in Action

Without question, Wicket in Action... is the be-all and end-all when it comes to Wicket.

Geertjan Wielenga, Wicket Netbeans Plugin Author

The tutorial and conversational tone of the writing makes the book very approachable.

Nick Heudecker
System Mobile

Loved the sample application—it tied everything together.

Phil Hanna
Senior Software Developer, SAS Institute

The essential guide for learning and using Wicket.

Erik van Oosten
Lead programmer and Project Manager, JTeam

Finally, the Web Framework of web frameworks, Apache Wicket, now has a bible of its own.

Per Ejeklint
Senior Software Architect, Heimore group

Wicket is an innovative evolution of the MVC programming with simple roots, but without a primer such as this, it can be more challenging than it needs to be.

Brian Topping
Founder, Bill2 Inc.

Wicket In Action glues the areas of web development with Apache Wicket together and gives a great overview of Apache Wicket...it will make a great compendium.

Nino Martinez Wael
Java Specialist, Jayway Denmark