As I'm trying to figure out the JARs required by Tapestry, I find that commons-upload.jar is required by default.
2004-07-21 17:12:47 StandardWrapperValve[tapestry]: Servlet.service() for servlet tapestry threw exception
java.lang.NoClassDefFoundError: org/apache/commons/fileupload/FileUploadException
at org.apache.tapestry.request.RequestContext.(RequestContext.java:153)
Huh?! That's wierd - I'm not doing any file uploading... (I know, this type of message belongs on the mailing list - I just thought it was funny )
Yesterday I began converting a small application from Spring MVC to WebWork. By the end of the day I was pretty much finished, but shot an e-mail off the the user's list to figure out a few more things. Today was spent incorporating that knowledge and making the app follow more WW "best-practices". Below is a list of things I discovered:
- WebWork's documentation is actually quite good. I was able to figure out most things just by reading it. I'm still surprised that most web app frameworks don't describe a simple CRUD operation as their first example. In my experience, CRUD is 80% of a webapp's job.
- WebWork integrates with Spring quite nicely. It's interesting to see that Spring has most of its MVC Framework support as part of the core, but WW has its own. I wonder why? Who cares, it works!
- WebWork is a bit better than Spring MVC in that they have a mechanism for saving/displaying success messages. However, it doesn't live past a redirect, so you're still stuck putting messages in the session. Struts (as of 1.2.1) allows you to use a
saveMessages(session, messages)
call - and subsequent JSP tag to display (and automagically remove). Like it or not, Struts seems like the easiest solution for developers to use.
- There's no clean mechanism for cancelling validation when a user clicks on a "cancel" or "delete" button. Struts supports cancelling using it's <html:cancel> button and it's pretty easy to detect "delete" and cancel validation in a form's
validate()
method. I ended up using an onclick handler for my cancel button and not worrying about validation on delete. This is the way I did it with Struts for years. Spring is cool in that it has a processFormSubmission()
method that you can override before validation kicks in.
- With Commons Validator, I'm used to specifying generic validation messages like "errors.required={0} is required.". This is possible with WW by using "errors.required=${getText(fieldName)} is required.". However, WW is a bit unique in that validation rules and ResourceBundles are defined on a per-action basis. I like having a central location for all my messages - like Spring and Struts have. I know it's possible with WW, but I'm trying to develop a "best-practices" sample app.
- I really dig that fact that you can use one JSP tag to render an entire <tr> in a table. This <tr> ends up having a label and an input field - which is very cool IMO. I did find some issues with the XHTML output, but found it very easy to submit patches. Good stuff.
- The config files (xwork.xml and validators.xml) must be in WEB-INF/classes. This is because they're XWork configuration files, and XWork is a non-web framework. It would be nice if I could put these in WEB-INF - where the rest of my config files (Spring, SiteMesh, etc.) reside.
- Many of the JSP tags require you to use "'literal value'" - where you put single and double quotes back-to-back. IMO, this is just ugly and I'd much rather put some sort of indicator that it's a dynamic value - i.e. ${...} or #.
- I couldn't get client-side validation to work. Seems cool though.
My experience with WebWork has been quite pleasant. I received excellent support from the mailing list - even though it took me a while to subscribe. The mailing list archives are woefully out-of-date, but this is a general java.net problem - not a WW issue. Maybe they should create a forum until the mailing lists get back on track?
Hopefully this last day and a 1/2 will make it much easier to implement WebWork in AppFuse. Thanks for the support gents - now I'm off to learn Tapestry!