[update 2008-05-27: A detailed presentation that summarizes this blog post along with visuals and code snippets is now available]
For quite a while, I was trying to ignore the increasing buzz about Wicket, convincing myself that I don’t need yet another MVC framework (there are too many of them anyway), but somewhere between the Javalobby articles, the InfoQ article and the O’ReillyNet article – my resolve cracked and I took a closer look.
It looked interesting and so I decided to try and migrate a selected few JSP screens of an existing Spring MVC + Spring WebFlow application to Wicket. This went much better than I expected and two months later (not full time) – I completed migrating the entire app to Wicket and it is now ready for a new release as a 100% JSP free application. I’m now trying to convince my colleagues to try Wicket and they give me strange looks because I was an outspoken Spring MVC / WebFlow fan not so long ago : )
So is Wicket the one true MVC framework that a lot of us have been hunting for? At the moment, I tend to think so. Of course I have not tried GWT, Tapestry, RIFE, Stripes, JSF, Seam, Echo2 and the other usual suspects. And how is Wicket better than Spring MVC and Spring WebFlow? Having used both, I will attempt to elaborate below.
[update1: I tried JSF, and you can read my comparison of Wicket with JSF]
[update2: I also tried GWT and here is my comparison of Wicket vs GWT]
[update3: Detailed performance & memory usage comparison of Wicket with Seam / JSF]
Lots of information is already available on Wicket and how it compares with other frameworks in general, so here I will try to focus on what I experienced when I moved from JSP + SMVC + SWF to Wicket. The way I had to throw some of my pre-conceived notions about Java web-app development out of the window may be of interest to you. This is not a very structured list, but I’ve been meaning to put down these first-hand Wicket impressions for a while, so here goes:
If you like Java you will really like Wicket. Over the last two months, I was surprised to learn a few Java-isms that I was not aware of – such as some subtleties when using anonymous inner classes etc. To be really productive with Wicket I think that your Java fundamentals do need to be sound. But that is a good thing.
Great component model
The application that I migrated is a reasonably complex one, with a few CRUD screens, forms, search results etc – and Wicket offered almost everything I needed – and more. I was able to easily create a couple of custom components like:
- a date picker (Wicket has one but I really wanted to write my own)
- a variant of a multi-select check box where if there are pre-selected values, they “float” to the top of the list. It was very easy to create this by extending the Wicket multi-select checkbox.
Once you get used to components (even a web page is a component) as opposed to URL mappings and MVC actions, you can develop at a very fast clip. After experiencing the elegance of this kind programming model where you can show or hide components and control all this in pure Java code as opposed to hacking in JSP or JSTL, you really won’t feel like going back.
I used to hold the opinion that people new to Java who need to learn how to create web-applications could probably skip most of the Swing sections in the typical introductory course material and get straight on to Servlets and JSPs. Now I have completely reversed this thinking. Swing-style coding is the future for web-applications, I can feel it :)
In the old app I had written a custom JSP tag for the special multi-select checkbox list and was quite pleased with the result. I used to think that JSP tags were more than sufficient to create re-usable components and using Prototype directly was enough do fancy Ajax things etc. Now I have revised that opinion as well.
*Real* separation of concerns
Because the application I was developing had zero JSP scriptlets and strictly used JSTL, I was under the impression that I had reached nirvana in terms of separation-of-concerns.
Of course I was wrong again. In Wicket, all layout is controlled in good old HTML files. And Wicket has some neat-o ways to do markup-y things in the Java code itself – like for instance how you can color alternate rows when rendering an HTML table.
If you have a separate team doing the presentation look and feel work, they can truly work in isolation and their output can be used as-is. Although I don’t care about this at the moment (in my case, the UI designer and Java developer is the same guy), I’m sure that this is a big deal for most development shops. I am aware that Tapestry promises the same thing.
So this is a key difference from Swing where you have the concept of layout managers. As far as I know this is where frameworks like GWT and Echo2 are different from Wicket because they also have layout controlled in Java code. IMHO the Wicket approach is the right one because you get the separation of concerns advantage. And I personally like complete control of the markup. I mean, with all those silly cross-browser incompatibilities and the need to finely adjust spacing, padding, coloring and the like, this seems to be a good thing.
This is very nice because:
- You can do things much more easily and efficiently in pure Java than in JSP and the limited syntax of JSTL. Ever had that nagging feeling that your JSPs were getting un-maintainable? Try Wicket!
- You can refactor confidently and catch problems at compile time which are not possible with JSP. For example if in JSTL you were referring to a non-existent Javabean property, you may not know until the page renders.
- Pages are no longer slow the first time you access them because there is no more JSP compilation step
- in my case, the app embeds Jetty and now I don’t need the JSP jar dependencies any more. This cuts the Jetty footprint from about 7 MB (including Ant and the Eclipse Java compiler) to about 1.3 MB. I had tried JSP pre-compilation earlier but gave up because of differences in how Tomcat / Jasper does things vs the Glassfish JSP engine. Jetty + the web-app requires only a JRE to run if there are no JSPs.
- A nice side-effect of using wicket is that your pages are guaranteed to be XHTML compliant
The downside is of course that you have to recompile a little more often than if you were using JSPs. Wicket does allow you to change the markup on the fly and refresh in debug mode. Also, Wicket provides out of the box, a very detailed error page with some nice syntax coloring telling you exactly where the problem lies in your markup or otherwise – which is very, very cool.
Ah, again, *really*. Re-usability in the JSP world is a custom tag or a hack-y include file.
I already mentioned how easy it is to extend (yes, extend as in the Java keyword) a Wicket component to customize how it behaves. And once you get the hang of the Wicket way of doing things and how to use anonymous inner classes to your advantage, life is good :)
So compared to doing things in JSP, it is far less work in Wicket to create a component that is truly re-usable, say across all the pages of your application. And unlike JSP tags, you get the full benefit of the Java OO features. Did I mention that the design of the whole Component class hierarchy in Wicket feels very nicely done?
Wicket also has a Panel concept where you can group custom markup + components and re-use the group as a single unit to your hearts content. IMHO you really don’t need any “tiles” kind of framework anymore, just create panels and instantiate them at will.
Templates for web pages
Something I really missed in the JSP world was the ability to have all pages have a consistent header and footer and I really hated having to add includes to all JSPs to achieve this. Not any more. Wicket has a brilliant markup inheritance concept that simply works.
I’m guessing that this is the killer feature of Wicket. Control freak that I am, I was at first concerned that Wicket comes along with its own basic Ajax implementation, or in other words it provides a replacement for say Prototype or Dojo out of the box. I initially tried to use Prototype from Wicket and was pleasantly surprised when that proved really easy. Adding on Scriptaculous effects was no problem either.
But after trying the Ajax support in Wicket I was really impressed and soon decided to do away with all those *.js files lying around in my web-app. The very useful Ajax debug popup that automagically appears on your web pages in debug mode is one good reason to rely upon Wicket’s built in Ajax. Now I feel confident that I can implement any kind of fancy Ajax on my screens, so bring it on! One example that I tried and can mention here: it was very, very easy to create a page that runs a long running process in a separate thread and updates a progress indicator through Ajax every few seconds or so.
I came across this quote that Ajax in Wicket is possibly better and much easier when compared to how you do it in Ruby on Rails, and I wouldn’t be surprised if this is true.
Form Binding and Validation
Spring MVC is extremely good at binding HTML forms to POJOs, (a far cry from Struts 1.X) -so can Wicket be any better? I really think so. Just like Spring MVC, as long as you have POJOs and you bind in terms of OGNL, you are fine. I was able to bind almost all of the POJOs that I was using in the earlier Spring MVC app to Wicket forms without any problem. Some things felt really cleaner – like how to have multiple submit buttons on a form.
When it comes to Form validation and displaying validation errors, there are so many options and great possibilities. By default, you can display errors in a section (feedback panel) at the top of the form. I was also able to create a Wicket “behavior” that would highlight the offending widget on the screen by applying a red CSS border around it. Lurking on the Wicket mailing list, I can see folks trying all kinds of cool things such as Ajax-ified feedback messages etc. The Wicket mailing list is a friendly source of help btw, and I got quick responses to all my newbie questions.
Other Neat Stuff
Wicket has some goodies and some of the ones that I ran into (there must be many more) were these:
- File upload: After using Spring MVC where you have to choose say commons-fileupload and manually include the JAR, I was pleasantly surprised to see that Wicket supports multipart forms / file uploading out of the box.
- File download: Wicket has a special “Link” class specifically for the purpose of downloading files. Wicket takes care of all the low-level details such as setting the right content-type for the browser – so you end up doing the Right Thing. You don’t need to deal directly with the HttpServletRequest or Response objects at all.
- Buffered Image: I use JFreeChart and in the old app I had to hack around a bit to get a server-side created chart streamed into an IMG tag. Wicket has an Image component that works with a buffered image. Perfect!
- URL Mounting: You can get those bookmarkable “friendly URLs” you want with this feature. I liked the support for “REST-ful” URLs out of the box: e.g: /foo/bar/param1/param2 – and how easy it was to use.
Security (Acegi) and Wicket
The old application was using the Acegi security framework. I started out retaining Acegi for authentication and co-existing with Wicket, which was easy. I soon realized that Wicket has a very simple authorization strategy and I was able to plug in custom code to check if a user is not logged in, redirect to a login a page etc. I was also able to easily handle an auto-login using a “remember-me” cookie.
An interesting thing from the security point of view is that the URLs that Wicket generates are inherently secure. In other words it is near-impossible to predict them as they are tightly tied to a user’s session. I came to the conclusion that simply programmatically hiding / unhiding links to secure pages based on the currently logged in user’s role would be sufficient for role-based access-control kind of security.
Acegi is very useful in a URL to MVC-action mapping situation because you can restrict URL patterns to roles – e.g. you can enforce URL wildcard rules like “/admin/**” can be viewed only by ROLE_ADMIN. I will probably continue to use Acegi for a planned remote REST/POX API to the app and for the LDAP and CAS support that it comes with etc. But I’m almost convinced that Acegi is overkill for a basic Wicket app. I am still going back and forth on this – so do let me know what you think.
Integration with Spring
This was easy. I was able to manage without the recommended wicket-spring integration JARs and went with a relatively simpler (and arguably less-elegant) approach – plucking the Spring context out of the ServletContext. In case you were wondering – I have so far used only the core wicket JAR and have not even used wicket-extensions. But I’m sure I’ll start using wicket-extensions soon, I can’t wait to try modal popup windows, the file-upload progress-indicator and the other cool stuff :)
Another example of how well thought out Wicket’s design comes across is that it took only a few lines of code to delegate to the Spring MessageSource instead of using Wicket’s default i18n. So I was able to use my existing resource bundles unchanged.
Integration with Hibernate
I use Spring on top of Hibernate and staying clear of the dreaded LazyInitializationException was as simple as adding the excellent Spring OpenSessionInViewFilter. Regarding GWT, from what I can make out, getting it to work with Hibernate may not be as easy because of the way it works. I would appreciate some comments confirming this, because this could be another key point to consider when you choose an MVC framework.
No Annotations Required
Yep, I’m one of those stubborn types who firmly believes that the only annotation that you should use is @Override. And as mentioned above I did not use the annotations based Spring integration. I bring this point up because from what I have heard – some of the other competing MVC frameworks rely a lot on annotations such as Tapestry, Stripes, RIFE, Seam etc. So if this really matters to you or if your environment is pre-JDK5.0, it could be another differentiating factor. Wicket already is famous for not needing any XML configuration at all. If the Wicket guys are reading this – I really appreciate that you have not forced users to use annotations and I sure hope Wicket stays that way!
WebFlow or Wicket
In the old app, I was using Spring WebFlow and was quite happy with it. So when I started out with Wicket, I was trying to figure out how I could integrate it with WebFlow. But as I understood Wicket more and more and things started to click in my mind, I realized that there is no way you can have them both – you have to choose one or the other.
I found WebFlow great because it allowed me to re-use subflows. So as an example if I had a use-case like “assign task to user” and the user did not exist, I could easily call the “create user” flow and then resume the original calling flow at the point where I branched out, you know – all that continuations stuff. But now my conclusion is that you can easily do all that – and more – with Wicket.
In Spring WebFlow, each view state in a flow is typically a JSP page. Which brings me to now think that it was not really designed to reuse anything more fine-grained than a JSP view – when interacting with a user. I already mentioned that Wicket allows you to reuse sections of HTML and group bunches of components into panels. So when you start trying to build more dynamic pages – I think Wicket wins. Navigating back and forth in Wicket really is child’s play, you just call or instantiate another page at will. You can even do tricks like holding a reference to a previous page, (a page is nothing but a good old Java component) so you can build any kind of complex kind of back-and-forth or wizard kind of navigation easily. I am aware that Wicket has a breadcrumb component and a wizard component but I have not tried them yet.
When it comes to Ajax, I really think Wicket is better than Spring WebFlow. Spring WebFlow is unquestionably a well designed framework, continuations and all, but sometimes I felt that certain things were constraining – for example you have to jump through a few hoops to access flow-scoped variables from outside a web-flow. When you use Ajax, you do need to do that kind of stuff a lot. In addition, in the Ajax world – you are invariably dealing with a section of a page – rather than the page in its entirety – and that is where IMHO the “page centric” nature of Spring WebFlow is a limitation.
A couple of other points, I did not use browser back-button support at all yet, but just from looking at the documentation, Wicket’s back-button support appears to be just as good, if not better. And nit-picking here – I don’t particularly like the huge UUID kind of URLs that SWF generates by default eg: /like?_flowExecutionKey=_c815540C2-03F1-39F8-19E9-D56FC0E377B7_k14D5E331-7B59-EA45-CF06-672C33FA2097
But Wicket is quite the opposite, with a “URL compressor” turned on by default.
Are there any points I have missed? Please feel free to comment and help me straighten out my thoughts on comparing some of these MVC frameworks. The migration was done on an open source app, so if you want me to pull out some “before and after” code samples, do let me know!
Afterthoughts [update 2007-03-03]
Triggered by the comments and also a few additional things that popped into my mind:
- Unit Testability: I have not used this yet, but if this means a lot to you – Wicket has that covered. And before you look down on my lack of best practice :p let me hastily add that I use Watij, but not as much as I should have.
- Custom Session: You can create a typesafe custom Session class and you never need to deal with the HttpSession at all.
- Refactoring: It is worth repeating that because of no JSPs, no templating (like for e.g. Velocity) and no XML – refactoring of the Java code is simple within your plain old IDE and no special tooling is required. I can vouch for that, I am using NetBeans and have no extra modules (plugins) installed. Debugging, setting break-points and stepping-through plain old Java code is far more easier than trying to do the same thing with e.g. JSPs.
- Simplified Stack: In my case I replaced [HTML + JS + Prototype + JSP/EL + JSTL + Spring MVC + Spring WebFlow] with [HTML + Wicket]. Also note that whether Acegi needs to be there or not is debatable.
- Clean separation from Service Layer: This is somewhat specific to Seam and let me elaborate a little. I attended one of Gavin King’s Seam sessions recently and was a little taken aback (so were quite a few others) by the suggestion that the notion of a re-usable middle tier (service layer) is grossly over-rated, i.e. a) you normally never find yourself swapping out a layer, and b) a change in one layer always impacts the other, no matter how loosely coupled they are. Conclusion: so why bother, and you are better off merging all the layers into one. You know the feeling – like wtf, is this back to the monolithic JSP-directly-accessing-DB days!? Anyway – now I can stand up and testify that I was able to cleanly take out Spring MVC and replace with Wicket with only minimal changes to the service interface (mostly feature adds and minor refactoring). This is worth thinking over, and I also feel that a well defined Service Layer is easier to expose as an XML remote API, which I plan to do soon. Just my 2c, do comment!