Saturday, October 31, 2009

... in other words, a first step towards using Maven for dependency management but NOT builds. That's the irony of Maven ... they've conflated two things (dependency management and builds) in such as way that they make the useful one (dependency management) painful because the build system is so awful.

As an interrum step between full Maven and (most likely) Gradle, I've been looking at a way to use Maven for dependencies only in a way that is compatible with Eclipse ... without using the often flakey and undependable M2Eclipse plugin.

In any case, rather than assuming that dependencies might change at any point in time at all, let's assume that when I change dependencies (by manually editing pom.xml) I know it and am willing to run a command to bring Eclipse (and my Ant-based build) in line.

The key target here is refresh-libraries, which deletes the lib directory then repopulates it. It creates a sub folder for each scope (lib/provided, lib/runtime, lib/test) and another sub folder for source JARs (lib/provided-src, lib/runtime-src, etc.).

That's pretty good for half an hour's work. This used to be much more difficult (in Maven 2.0.9), but the new scopes attribute on the Maven dependencies task makes all the difference.

Using this you are left with a choice: either you don't check in .classpath and the contents of the lib folder, in which case you need to execute the target and script in order to be functional ... or you simply check everything in. I'm using GitHub for my project repository ... the extra space for a few MB of libraries is not an issue and ensures that I can set up the exact classpath needed by the other developers on the project with none of the usual Maven guess-work. I'm looking forward to never having to say "But it works for me?" or "What version of just about anything do you have installed?" or "Try a clean build, and close and reopen your project, and remove and add Maven dependency support, then sacrifice a small goat" every again.

Next up? Packaging most of this into an Ant library so that I can easily reuse it across projects ... or taking the time to learn Gradle and let it handle most of this distracting garbage.

Sunday, October 04, 2009

I've been taking a little time from my billable projects to continue working on Cascade. One feature that's very important to me is to have great exception reporting, akin to Tapestry's. Here's a current snapshot of where I am:

This is very Tapestry-like (I've even borrowed the CSS styles). You can even see the start of the Request object's properties being displayed.

Something to notice here: Clojure stack frames are in Clojure syntax. To appreciate this, see what you get when you click the "Display hidden detail" button:

The exception report view is omitting a lot of clojure.lang internals, and it is working backwards from the mangled Java class name to the Clojure namespace and function name. This, plus only displaying the stack trace for the root exception, makes it much more reasonable to figure out where problems are actually occurring.

I expect to expand this further, adding a pop-up or hover window to display Clojure source associated with the stack frame.

Saturday, October 03, 2009

Tapestry is nice enough to bundle the Prototype and Scriptaculous libraries its client-side support is wired against, which is very convenient ... until you find out the the packaged version is not compatible with your shiny new browser, such as Internet Explorer 8.

Tapestry IoC to the rescue: you can override where Tapestry looks for the Prototype & Scriptaculous files (alas, it currently looks in the exact same place for them). Where these files are stored, and how they are exposed to the client is controlled by two contributions inside TapestryModule:

The first contributions set where, on the classpath, the Prototype & Scriptaculous files are located, defining symbols that can be referenced in various servers. The second uses some of those symbols (and a few others) to map the classpath location to a URL (this is the job of the ClasspathAssetAliasManager service).

However, what's being contributed is Prototype 1.6.0.3 and for compatibility with Internet Explorer 8, we need the latest and greatest: 1.6.1. That's what
tapx-prototype does. And at its core it's just a couple of lines of code:

Notice that we can just override part of the configuration of one service (FactoryDefaults) and extend the configuration of another service (ClasspathAssetAliasManager) without disturbing anything else. This is Tapestry IoC in a nutshell!

Glenn Vanderburg has been popularizing a terminology for extensible software: a "seam" is any point where existing software can be extended. He's used to the Ruby world where, literally, every method is a seam. Tapestry, too, is all seams ... every service, and (with more effort than Ruby) every method of every service is a seam, and lots of effort has gone into the design of Tapestry IoC to ensure that it can be extended without massive cut-and-paste or other disruptions.

I'll be releasing the tapx code soon as a stable release, once I do a little more testing with IE8.