Migrating from WebWork to Stripes, Pt 1
The first in a series of blogs about converting an application from WebWork to Stripes.
To begin with..we arent officially moving our architecture to Stripes..at least not yet. Our site just went live in September, so switching a framework at this stage would probably cause folks to hunt me down :)
However, when i first proposed the webwork/spring/ibatis architecture way back in early December 2005, Stripes, while attractive, was only 3 or so months old. It was still too new for me to really consider basing a new site on. Plus, WebWork looked nice, and with the Struts merger announcement, i knew webwork/struts would be around for awhile.
Fast forward to today, and Stripes is up to version 1.41 and Struts 2 is finally in early release (not sure Struts 2.0 has had an official GA release yet). I've been looking at Stripes again for around a month now...and i keep reading stories about how slow OGNL is, and I am wondering if the lower than expected load capacity on one of the heavy pages on our site is due to OGNL. (more on that in a follow up post...though to be honest, the current version is fast enough for our needs in the near future. After working on weather.com and dealing with 60 million hits per day sometimes, i get rather picky on max requests per second). So, i thought i would try rewriting that heavy page in Stripes to see how it felt to develop in Stripes compared to Webwork.
First off, Stripes was VERY easy to get up and running. There was only one (one!) jar i needed to download (i already had commons-logging). I added a few lines to my web.xml and within 5 minutes had a Stripes demo page working. Nice.
Second, thanks to Spring, i DID NOT have to touch any of the model or DAO classes. although somewhat controversial, i like to use autowire by name in my spring classes to cut down on the size of my Spring xml file. I use the full class name DAO as variable names in my actions, and in my Spring file. For instance PersonDAO would be named personDAO in my actions and in my Spring file. That also happens to follow the naming convention in Eclipse if you let it autocomplete the field declaration for you. I like that i can add a new DAO to an action by just adding the field and not needing to modify the Spring file. For the few actions that can write to the db, though i do usually disable autowire by name.
So, since i didnt need to touch the other layers of the application..converting my webwork action to a Stripes action was almost ridiculously easy (it only involved changing the action itself, and the jsp for that action):
1) My action class now implements ActionBean, instead of extending ActionSupport
2) Added the url the action responds to via the @UrlBinding annotation (instead of declaring it in xwork.xml).
3) Changed my execute method from public String execute() to public Resolution execute() (though execute is not needed by Stripes..any method name would do..just has to be public and return a Resolution, i believe)
4) To hook my DAOs to Spring, add @SpringBean before each Spring injected bean (which is better than having this in the xwork.xml..as the Stripes annotation makes it more obvious that Spring is involved for documentation purposes. Yeah, it ties that action to Spring explicity, but since its just a one word annotation..its worth it for the self-documenting nature of the annotation)
5) the execute method now returns the jsp view as a String, instead of returning SUCCESS, and having SUCCESS for the action mapped to a jsp in the xwork.xml file
Unless i am forgetting something..thats all i did to convert an action from webwork to stripes. Nothing to it. And I LOVE how the annotations are also like documentation.
The final (and biggest piece) of the conversion is the jsp itself. I had relied entirely on the webwork tags for logic and action binding (which probably meant a lot of OGNL along with some freemarker). I didnt use JSTL or the EL at all. So, i had to come up to speed with JSTL and some of the limitations of JSTL and the EL. Webwork was a bit friendlier in this way. I liked that WebWork allowed be to easily call methods on the action that a jsp was mapped to. It took me awhile to figure out that i need to convert those types of methods to static so that i could create a custom tag file to access those methods via JSTL. In the long run, i think i'm better off with the standard JSTL in my pages, and only using a frameworks custom tags when they really save a lot of work. (though i dont think webwork plays well with JSTL, though i could be wrong).
I'm still learning JSTL as i convert, and think i almost have the page converted. The next step later this week (i hope) will be to load test this page to compare the results to the same page in webwork. That test will probably run in our test environment..so the raw numbers wont be very important..be the comparison of the numbers in each framework will be. I'll blog about those results when i get them..again, hopefully later in the week sometime.
Overall, I really, really like how easy and quick it is to develop with Stripes. The biggest drawback has been the limitations of JSTL. I wonder if Stripes has a tag that would allow me to call methods on beans or actions without having to resort to custom tags. Guess i should ask that question on the Stripes list. Down the road, i also want to try out Hibernate 3.2 and see how an all-annotations based architecture feels. But first i need to get a better handle on Stripes.

7 Comments:
Good to here you are looking into Stripes. As for the calling methods from JSTL, if you are just calling simple getter/setter methods, it is as simple at ${actionBean.method}, which would call the method called getMethod on your action. Not sure why you would want to call other methods from the JSP, but if you are trying to do something specific, definately ask a question on the mailing list.
Thanks Paul.
Yeah, i do know about calling setter/getters, but i have a couple of utility methods i sometimes calls from the jsp. One is a method called getQueryString(String excludeParams)..the excludeParams are a comma separated list of params to remove from the query string. When building links on the pages, i like to have an easy way to pass along all params..but some pages dont need certain params passed, or it causes problems. So, i came up with a way to specify a list of params to remove, if present, when building the query string.
The other utility method i created was a replacement for the ww:text tag..i have a bunch of config stuff, like site urls, defined in a properties file, that all jsp reference..so that urls arent coded in every jsp. I created a static method called getText that can read the same properties file used by my webwork code. I know Stripes has support for 2 properties files, but i wanted to keep things a little more separated, to keep the size of the properties files down a bit.
The query sting utility method is pretty handy, and i wonder if others would find it useful?
Figuring out how to create custom tags to be able to use these 2 methods is what caused my a few difficulties..but i thnk i have it working well, now.
For getQueryString, just take care of excludeParams in the handler/ActionBean. So you will have a method called getQueryString() in your action that knows which params to get rid of for that action, and just gives you the query string.
You might want to have a method in your BaseActionBean that is like getQueryString(String excludeParams), then in each individual action bean, have a method getQueryString() that passes the specifc String of excludeParams to the BaseActionBean method.
As for the stie urls and stuff, what I do is make my base ActionBean know how to get all that stuff. So put a method on your BaseActionBean called getSiteUrl() and then all your actions can get it, and also your JSPs can get it via ${actionBean.siteUrl}. If there is a lot of it, package it up in an object called Config, so you would get it via ${actionBean.config.siteUrl}. Then you can get all of the info from a properties file, from the database, from XML, from Spring, hard-coded into the Config class, whatever, it is abstracted away from the actions and JSPs, so you can set that up however you want.
Paul,
Actually..how you describe the getQueryString() method is how i have it working in my webwork action. Its my a superclass that all webwork actions extend. I tried creating a similiar method in my Stripes superclass..but in JSTL, i couldnt fingure out how to pass params to a method call. I know i could say actionBean.queryString, but how can you pass params to it? if you can tell me how to do that, i would be grateful, as i couldnt figure it out (without resorting to static method/custom tag solution)
As for the url stuff..i do wish Stripes had a similiar funtion to webworks getText tag. I like how i can define properties for EACH action class, and being able to just use ww:text and have webwork look in the action class, then up the chain until the right key is found. This is the biggest single thing i missed when trying Stripes. I like to have common properties defined in my superclass properties file, and have subclass speficic things in their own properties files. I know this makes for more files, but it does keep the file size down and prevents a humongous properties file. If you develop a large site in Stripes, the 2 supported properties files arent enough (in my opinion). This is the only advantage webwork has over Stripes that I have come across so far.
Since it sounds like you're using a modern stack, you should look into jsp tag files. They make generating most custom tags trivial. The only problem is finding (accurate) documentation on them (which is the problem with jstl and the el as well).
"Down the road, i also want to try out Hibernate 3.2 and see how an all-annotations based architecture feels."
It feels pretty damn good. very good
Check out the stripernate library, it's amazing. It makes stripes and hibernate w/ annotations totally seemless and pretty efforless to setup.
Right now I'm looking into bringing in spring to manage transactions and the DAO layer so I can do unit tests out of the container. Stripes just has me spoiled with the complete lack of configuration, so spring has always been a little intimidating.
I can't read jsp / jstl / el / java code at all so i use freemarker. That hodgepodge mix of different langauges reminds me of coldfusion, free marker is very clean.
As far as jsp being limited, I've never needed to do anything like that, as I keep all the complex stuff in java classes behind the view. My freemarker pages are just divs, tables, and some stripes tags, nothing fancy at all.
I started something pretty cool yesterday: a generic extendible login module for stripernate with cookies and all that. I'm very pleased with how it's turning out. I have 3 projects that use the same login thing each with different domain models. Maintaining it 3 times was not working. This is pretty cool I'm very excited about it and eventually hope to share it.
Oh as far as hardcoding the urls and whatnot feeling dirty, I agree. But on the other hand I don't want an xml file to maintain.
My current solution to this (not sure how good or bad it is) involves a consts package, in which I have a bunch of different classes with static strings in them.
i.e.
consts.ActionUrls {
public static final String login = prefix + "Login" + extension
}
I have a servlet context listener setup, which tosses these classes into the servlet context scope.
Every string has a getter and setter, so in freemarker I can say
[@s.form action=Application.actionUrls.login /]
Not sure if that's really any better that action="/Login.action" but it feels a little cleaner to me at least. I don't think it completely solves the problem though.
Post a Comment
Links to this post:
Create a Link
<< Home