Savant command-line tool and plugins are almost ready

Been working this week on Savant 2.0. My first thought when I started writing Savant 2.0 was to write a complete replacement for both Maven and Ant that used Groovy and allowed for both a plugin model as well as a simple build script approach. This was too much to bite off when you consider all of the other changes to the dependency management part of Savant we made for 2.0.

For JCatapult we created a set of Ant build scripts that could be plugged into any build file and reused. It looks like this:

<project name="foo">
  <import file="${jcatapult.home}/ant/plugins/java/1.0/compile.xml"/>

This model meant that the build.xml file had nothing but import statements in it. It made life much simpler when working with numerous projects that were virtually the same.

The part I didn’t like was that I loved this model. I liked it so much I started using them for everything including Commons, Savant and internal Inversoft projects. This meant that I had a dependency on JCatapult, which for all intents and purposes is a webapp platform. This seemed strange.

I started thinking about moving these files over to Savant. At first I just figured I would migrate the entire set of Ant plugins from JCatapult over and be done. However, once I moved them over it meant that I would need to start pulling in plugins for a variety of projects. Some would come from Savant and others might come from JCatapult or elsewhere. This was due to the fact that some of the JCatapult plugins were very specific to JCatapult projects. I could force developers to download each plugin they needed from various places, install them in a specific directory and then update their build files before they could build any projects. It all started to look very clunky.

Then I remembered (duh!) that Savant is a dependency management tool and it can find, version and download ANYTHING. Why not apply this pattern to Ant build files in the form of plugins?

So, I did just that!

It works great. The way it works is that I wrote a simple Java class that figures everything out and then generates an ant build file. The full process looks like this:

  1. New script called svnt invokes a Savant class
  2. This new class parses the project.xml file, which defines the plugins the project will be using
  3. It downloads any missing plugins to the Savant local cache
  4. Since the plugins are JAR files, it explodes the JAR file to ~/.savant/plugins under a specific directory just for that plugin
  5. This class then generates a temporary build.xml file that imports all of the plugins the project needs
  6. It outputs the location of this temporary build.xml file
  7. The svnt script executes Ant passing it the location of this build file (i.e. ant -f /tmp/tmpbuild.xml)

And that’s it. Nothing fancy, just a little sugar on top of Ant to provide downloading of plugins and build files automatically.

The last part of this exercise is to write a bunch of plugins. Since these are just Ant build scripts and we’ve all created hundreds of those so it should be a simple matter of tweaking them ever so slightly to work when imported.

My new projects don’t have a build.xml file (but if they do it is imported to add additional targets or override targets from the plugins) and just contain the Savant project.xml file. This file now defines plugins and it looks like this:

<project name="foo" group="" version="1.0">
  <plugin group="" name="clean" version="1.0"/>
  <plugin group="" name="java" version="1.0"/>
  <plugin group="" name="junit" version="1.0"/>
  <plugin group="" name="release-svn" version="1.0"/>

That’s it. If anyone is interested in trying it out, I should have a release available in the next few days along with some documentation for the 5-10 plugins I will have ready. If you want to try and build all this by hand right now, you’ll need to install JCatapult since Savant uses that until it can be self building.

Google Code could be EXTREMELY dangerous

I host a number of projects including JCatapult over at Google code. We use the wiki over there for our documentation because it is simple and centralized. The wiki is stored inside the SubVersion repository and when you update the wiki it performs a commit to the repository. Pretty straight-forward.

One of the project members, James Humphrey, was editing our wiki last night, finished editing a page and hit Save. Rather than just updating the wiki page in SubVersion, Google’s custom built SubVersion server decided it wanted to completely revert our entire project back to revision 1. Yeah, I’m totally serious!

Well, the old revisions appear to be in the repository, but in order to clean this clandestine (hehe) mess up I’ll have go in by hand and revert our entire repository. This consists of roughly 10 sub-projects and 5 tags for each project plus branches, etc, etc. Really nasty.

So, here is my warning to all those out there that might be using Google Code, be careful. I’m working with Google right now on trying to figure out what happened and how to fix it. I’ll update this post once we figure it out.

FCKEditor is touchy (especially with SiteMesh)

First off, let me just say that I don’t like any rich text editors very much. They are all a messy mix of HTML, JS, CSS, etc. There isn’t anything out there that is truly clean, feature rich and performs well. FCK has always been my least favorite, but I thought I would try 2.6 BETA and I was surprised at how much they added and updated things. This release has better dialogs and a smoother JavaScript experience. It is also less static and easier on AJAX apps.

Anyways, back to the point. JCatapult applications all use SiteMesh for templating and decoration. They actually have to because of our componentization model, otherwise components would be coupled to specific decoration or worse require tons of configuration (anyone interested in this concept contact me directly). Well, SiteMesh decorates your HTML using the GoF decorator pattern. Essentially the servlet container renders your JSPs or FTLs. That HTML is written out to the output stream, which SiteMesh has nicely intercepted being as it is a Filter. Once all the other Filters and servlets in your app complete, SiteMesh post processes the request, parse the HTML and decorates it. Very simple. The issue is that FCK editor uses HTML, JS, and CSS inside iframes in order to work its magic. Very ugly. What happens is that SiteMesh might end up decorating requests for FCK files. FCK REALLY doesn’t like this and usually you’ll end up with one of these symptoms:

  • No edit area, just the toolbar
  • Empty dialog boxes
  • Totally borked drop-shadows on dialogs

The quick fix, just tell SiteMesh to ignore FCK. You can accomplish that inside decorators.xml using an exclude:


Do we really need code reloading?

With Grails, Rails, Python, etc offering developers the chance to change code, hit refresh and see the changes I often wonder if reload truly a feature that is a must have these days? It seems like it is one of the main selling point by most of the folks pushing those frameworks.

I think this is not a requirement, and doesn’t really increase productivity. Here’s why:

  • This promotes less tested code as you can code an entire app without testing at all by simply hitting refresh
  • The testing cycle is lengthy by nature, so you do any testing during development, it is going to take some time
  • Rather than using reload, if you use the development cycle of write, test, run or test, write, run, than starting up the application incurs minimal overhead in addition to running the tests
  • So, what are we really trying to accomplish while developing? Better code, less code, better tests, faster development. These things seem to imply great conventions and excellent extensibility and not reloading.

JCatapult M1 today

I’m releasing JCatapult milestone 1 as I type. This is the first major release of JCatapult and the first of two milestone releases before 1.0 is released in March. This release is stable and contains the majority of the functionality that will be included in 1.0. The documentation is still in progress, but anyone is welcome to take a look and play around with JCatapult before 1.0. Here’s the website:


HttpServletRequestWrapper, Tomcat and forwards

I’ve been working on getting the JCatapult security framework to leverage Struts actions rather than a bunch of configuration and additional custom code. In order to pull all of this off, I had to modify the HttpServletRequest in order to make it seem like the requested URI was different than the original request URI. I used a HttpServletRequestWrapper in order to pull this off like this:

final HttpServletRequest httpRequest = (HttpServletRequest) request;

HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(httpRequest) {
  public String getRequestURI() {
    return successfulLoginURI;

  public String getServletPath() {
    return successfulLoginURI;

  public RequestDispatcher getRequestDispatcher(String uri) {
    final RequestDispatcher rd = httpRequest.getRequestDispatcher(uri);
    return new RequestDispatcher() {
      public void forward(ServletRequest servletRequest, ServletResponse servletResponse)
      throws ServletException, IOException {
        rd.forward(httpRequest, servletResponse);

      public void include(ServletRequest servletRequest, ServletResponse servletResponse)
      throws ServletException, IOException {
        rd.include(httpRequest, servletResponse);

As it turns out, I had to do that little tricky part at the end with the RequestDispatcher because Tomcat fails during a forward if the incoming HttpServletRequest is a wrapper.

The new year

It’s 2008 and I’m hoping to start blogging more regularly again. To start, I figured I’d tell my readers my plans for 2008. Here’s the quick run down:

1. Continue building Inversoft’s Profanity products and increase sales

I did a lot of work last year getting the profanity database and filter working well. These products are slowly selling and Inversoft is getting more customers each week. I’m hoping to add some more advanced logic this year to reduce false positives even further.

2. Rebrand Inversoft and finish the website redesign

We have been working with the excellent designers from We Are Super Ordinary to rebrand Inversoft with a new logo and a new website presence. This should help us leverage our website as a good marketing tool for the business

3. Launch JCatapult and promote the heck out of it

JCatapult is starting to get to a 1.0 stage. I’m hoping to finish up the last few things in the next couple of weeks, including migrating SmartURLs into the Struts source repositories and make it one of the default plugins shipped with Struts. JCatapult will be based primarily on Struts2 and the SmartURLs port (called the Struts2 Convention Plugin). Once that migration is complete, JCatapult should be ready for a solid beta release.

4. Build a web application as a JCatapult example

I’ve had a few ideas and domains registered for nearly 7 years now and I’m going to try and build out one of these ideas using JCatapult. Hopefully I can find 3-4 developers that are interested in helping build this application in their spare time. Anyone who is interested, send me an email.

That’s the run down for 2008. I’ll try and post a few times each month on my progress, in addition to the standard technical ramblings I put up, which usually get more traffic than the rest of my posts. Time to get coding! Happy New Year!