Wicket Impressions 1
I chose Wicket for this project, partly because I met some people who were very enthusiastic about the framework, and partly because I wanted something that was easily tested. My client requires a Java solution, so Ruby on Rails was out. I did a quick little shoot out between three Java framework options, and Wicket passed the first impression stage.
Now I’ve got a couple of iterations of software development with it under my belt and I’m starting to feel a bit more comfortable with the framework. As far as Java web frameworks go, its pretty good, but… I would do things a bit differently. The application is written in a style that would actually better fit Ruby, SmallTalk, Lisp, or some language that supported passing in procedures or lambdas (as the language gurus call them) natively. Take for instance the Link class. In order to do anything useful, you need to subclass and implement the onClick callback method—even if all you want is to go to another page. Here is an example:
add(new Link("wicketId") {
@Override
public void onClick() {
// do fancy logic
setResponsePage(new IncidentPage(incident));
}
});
If this were Ruby the code would look like something like this:
self << Link.new("wicketId") do
// do fancy logic
respond_with(IncidentPage.new(incident)
end
So am I complaining about semantics? Possibly. However, there are more “Java” ways of accomplishing the same class—particularly if you want to manage all business logic in a few classes. The more “Java” way would be something like using the java.lang.Runnable interface. That would allow you to set up an enum to include all your business logic like this:
enum IncidentLogic implements Runnable {
EDIT {
@Override
public Page run() {
// do fancy logic
return new IncidentPage(incident);
}
}
}
and it would be used in your page like this:
add(new Link("wicketId", IncidentLogic.EDIT));
I’ve also experimented with using a dynamic proxy to bind any method to an interface. That would let you set up a logic utility class and reference it like this:
add(new Link("wicketId", Linker.link(IncidentUtility.class, "edit"));
It’s not as pretty but it works. Now here’s the nice thing about Wicket. If I feel strongly enough about it, I can create my own subclass of the Link object to implement that approach myself. My DynamicLink would look something like this:
public class DynamicLink extends Link {
public static interface Executable {
Page do();
}
private final DynamicLink.Executable click;
public DynamicLink(String wicketId, DynamicLink.Executable action) {
super(wicketId);
this.click = action;
}
@Override
public void onClick() {
setResponsePage(click.do());
}
}
In fact, I think I may just do that. It’s better than having bits and pieces of behavior spread throughout the Pages and panels defined in the application. I think I find it a bit frustrating when i need to do things like that just to format dates the way I want. Why can’t the provided DateFormatter let you set the pattern you wanted to use? Why do I have to subclass the one in Wicket just to get that feature?
At the end of the day, my complaints are minor and the Wicket community is helpful. I’m fine with that. The Wicket framework is probably one of the leaders in providing a test harness that can be used easily in your JUnit tests. That is a much bigger selling point to me.
