September 25, 2007 8 Comments
I’ve been working with Struts 2 recently, and like most frameworks it relies on a set of jar files. I like to work with Eclipse as my primary IDE. In that framework, my normal mode of operating is to create a User Library containing the jar files I need and then add it to my Dynamic Web Projects through the Java Build Path configuration.
It seems that the system has changed in Eclipse 3.3, aka Europa. I’m working with the Web Tools Platform plugin, so at least I have dynamic web project capabilies. I can also set up a Tomcat server easily.
What’s changed is that now, when I add a User Library to the build path, Eclipse warns me that it won’t be deployed to the server. The warning is:
“Classpath entry org.eclipse.jdt.USER_LIBRARY/libname will not be exported or published. Runtime ClassNotFoundExceptions may result.”
Yer darn tootin’ they’ll result. I suppose this is a feature, not a bug, because I have had situations where the libraries were already added to my server’s classpath so I didn’t want to duplicate them in the war file. Also, some war files become enormous because of all the libraries used. (The last time I wrote a simple app that used JPA, Spring, and Hibernate the resulting war file was huge. And the size of the war file that comes with a trivial Grails application is easily over 10 megs.) Now Eclipse leaves the libraries out of the war by default.
I’m reminded of when the Collections framework for Java was created, and ArrayList turned out to be exactly like Vector but without the synchronization. The theory seemed to be that you can always add synchronization later (Collections.synchronizedList(myList)), but that you couldn’t remove it from Vector when you didn’t need it. This change has the same feel to it — you can always figure out a way to deploy the libraries, but you never had a way to get rid of them short of editing the resulting war file.
That’s not necessarily a good thing for me, though. I’m always tempted to add libraries to my server’s classpath, partly to keep the size of the individual war files down, and partly because I tend to use the same libraries over and over and I hate packing them into every single application. All those repeated files feel like a waste.
Still, it’s dangerous not to include the jar files in the web application itself. Version problems can easily arise, especially because I tend to upgrade to the latest version of a given library whenever I can. For that reason, I’ve resisted the temptation to, say, put Hibernate and Spring into my server’s lib directory.
So what do I do in Eclipse? It turns out there are two solutions:
1. Declare the libraries to be module dependencies for the war. That’s done by going into the project properties, then Properties –> J2EE Module Dependencies –> Select All. Then Eclipse treats the libraries the same way it would any dependent project.
2. The other approach is to go on the file system and copy the jar files directly into the WEB-INF/lib directory of the project, then do a refresh. Apparently Eclipse is smart enough to then add the jars to the classpath for my source code.
I’m not sure which way I’ll prefer in the future. Eclipse does have a Navigator view which supports drag-and-drop copying, so that’s easy enough. Still, I hate to leave the IDE when I’m in the middle of using it.
This is also one of the few situations where using MyEclipse wouldn’t make any difference. Version 6 truly rocks, but it doesn’t have a predefined library for Struts 2. Maybe Struts 2 was still too new when MyEclipse 6 was being developed.
As an aside, it should be interesting to see which way the framework wars will turn in 2008. There’s still a huge installed base of Struts 1.* clients out there, but many of them are looking at other options. The other page-based framework I’ve used is Spring Web MVC, which has its own learning curve.
JSF is part of the Java EE spec, but if you’re used to a page-based framework the switch to a component-based framework is not trivial. Tapestry is still out there, and it has a few very fervent advocates, but I haven’t heard much growth in it. I also haven’t gotten any calls about it in quite some time. Seam is growing, too, but I expect that’ll be popular among the same crowd that likes JSF, since it’s based on JSF anyway. Of course, there’s also Google Web Toolkit if you want to build a desktop application inside a browser.
Struts 2 is very interesting, and has the modern feel of interceptors and filters and POJOs (oh my!). It has Spring-like dependency injection, though I think they use Guice by default rather than Spring, not that it really matters. I never learned WebWork before the merger, so the learning curve has been pretty substantial for me. Personally I feel that Struts 2 is so fundamentally different than Struts 1 that I’m surprised they kept the Struts name. That marketing decision may make all the difference, however.
I’ll keep an eye on all of them, of course, but for my own applications, I like Grails.
(Yes, I know that’s the same as saying Spring Web MVC. We’ll see how that plays out, too.)