Tuesday, May 22, 2012

Executable Wars with Gradle and Jetty

One of the things I recently wanted to do was create a set of Java based utility components that could be easily packaged (aka one delivery file), run together, and that all leveraged assets created inside a webapp.  Normally this would involve creating a 'fat jar', which takes all exisitng library classes and flattening them into the fat jar.

The upside of this is that you don't need any special class loaders, all the classes required by the application are now packaged directly in the jar.  The downside is that anything that used to live in META-INF folders in the third party libraries now get clobbered together in a single META-INF.  Of course, anything that used to rub up against servlet APIs, web aplication contexts and the what not will also seemingly break.

After poking around for a bit, the executable war file seemed like the way to go since it avoided some of these pitfalls and has the following benefits:
  • All third party jars can be packaged in a WEB-INF/lib
  • Solid and true jetty-6 provides a stable foundation for running a quick embedded container to run the war (i.e. itself)
  • All code written for a webapp can be immediately consumed
  • Remotability for the tool is immediately available
  • Once you open this pandora's box, wild-eyed ideas sprout up like the first executable war could take a list of wars as a command line arguments and deploy them all in itself.. "it's war files all the way down!"
Riding the Gradle band wagon, I wanted to try doing this in straight up Gradle script without re-using existing Ant tasks.  The following was done with Gradle 1.0-rc5

Some notes on this evening's experiment:
  • Jetty 8 has an 'orbit' file that Gradle doesn't yet handle gracefully.  There were some workarounds online, but I wanted this at a one hour research task so jetty 6 it was..
  • Tomcat 7 has a simple API for instantiating and running an embedded Tomcat, I just haven't gotten around to trying that out yet
  • "Gradle as Jetty Runner", "Gradle as Tomcat Runner", or plain old Groovy command lines are all valid options for doing the same thing, but in this case I wanted 1 file, 1 command
  • After so many years of Maven relaxation, it was kinda fun having direct control over build configuration primitives in the build file again and be able to use them in simple one liners
This already has me thinking of another little experiment -- self deployable agent wars using the above + MBeans, but that'll be for another night!