Tapestry Training -- From The Source

Let me help you get your team up to speed in Tapestry ... fast. Visit howardlewisship.com for details on training, mentoring and support!

Tuesday, January 29, 2008

Tapestry mentioned in ComputerWeekly

My friend Todd pointed me to this mention of Tapestry in ComputerWeekly under the heading "Hot Skills: MVC". The same article cites the momentum of Tapestry and Spring and the relative weakness of Struts.

They even used one of my catch phrases: The simplest choice should be the correct choice. Nice.

Monday, January 28, 2008

Maven: Won't Get Fooled Again

Fool me once, shame on you. Fool me twice, shame on me. I'm not going to get fooled by Maven again.

I can't express how much grief recommending Maven has caused me. I had a good experience with Maven for Tapestry 5 for quite a while and had the hubris to recommend it for The Really Big Project. TRBP consists of 40 (and growing) modules, all deeply interrelated. That interrelation is killer, it means that most developers have the master project, with all 40+ modules, open at once. That's 80 source paths (one for production code, one for test code), plus class folders, plus an amazing set of dependencies drawn in from Maven.

Maven simply doesn't scale to this level. Sure, the command line build does work in relatively short order (more on this shortly) ... but for day-to-day usage it's all about the IDE, and the IDE support for Maven just isn't there yet, may never get there.

In both Eclipse and IDEA, the Maven support has been very slow, buggy, and unstable. IDEA 7 gets it a bit more right than Eclipse (with the 0.0.12 Maven plugin) because synchronization is explicit. Still, it seems to turn into an endless amount of tweaking, fixing and praying, to keep things operational.

At the core, Maven has a great idea (really well thought out dependency management) saddled with an obnoxiously bad plugin system for performing the build. The obnoxious part is that a build that works on Monday may fail on Tuesday because some new, broken plugin was released into the central Maven repository.

Perhaps the worst part of Maven is the documentation, especially when it comes to writing your own plugins. The Maven team is criminal: their basic methodology appears to be:

  • Crank out an XML version of a data structure
  • Run a tool that generates a Java interface from the XML (containing no comments whatsoever)
  • Implement the class, don't add any comments
  • Don't package source with the plugin, as that would almost make it possible to figure out what's going on
  • If you slip up and accidentally generate JavaDoc, make sure the link to it on your site is broken

The Maven project site is an embarrassment. The tool supposedly designed for "project comprehension" is itself incomprehensible, due to its scale, the chaos of its documentation, and the extreme lack of engineering discipline evidenced by its maintainers.

Get out while you still can.

I'm now looking strongly at Ivy which keeps the dependency management (including Maven compatibilty) but jettisons the build. It just makes it easy to write your own Ant-based builds with the automatic dependency download.

Tuesday, January 22, 2008

Tapestry Code Quality

According to Enerjy, Tapestry comes in at about the top of the list for open source projects they've scanned. I suspect that T5 is quite a bit larger than the other top projects, and T5 probably also gets knocked down because I tend not to JavaDoc implementations, just the interfaces.

Also, looks like it doesn't understand Tapestry components, or the concept that the visible annotations on fields are both functional and documentation providing. Oh, and it hates that I don't use braces on trivial if statements.

This is all fine and good, though the code inspections built into IntelliJ were of more use to me.

Monday, January 14, 2008

Latest batch of features

I've been very busy on Tapestry 5 now, sprinting towards an end goal of a stable release. I'm very psyched about the latest stuff:

  • Improved Error Bubbles: those pop-up error bubbles (for client validaton, in 5.0.7) were just a first pass. I've smartened them up a bit, and now the bubbles for the non-focus field fade out entirely. I like the way it works, as you tab from field to field, the bubbles fade in and fade out appropriately.
  • Memory Management: Tapestry is a bit more careful about instantiating pages now. The first few page instantiations are "free" but past a certain point, Tapestry will wait a few milliseconds for a page instance to free up before instantiating a fresh one. And pages that aren't used for about 10 minutes are freed outright. And it's all configurable.
  • Whitespace Compression: Tapestry now strips out unnecessary whitespace from templates. This is a bit controversial (because the output is bit less readble) but is a win in terms of server side processing and on the client side. This change significantly reduces the number of objects needed in memory to represent a component template and that can't help but be a good thing.
  • Optimized Request Paths: When rendering output, Tapestry will make use of shortened, relative URLs, if those are shorter than an absolute URL. This is another attempt to minimize the content sent to the client, before we get into GZIP filters and so forth.
  • Immediate Response Mode: Miss the default Tapestry 4 request/render cycle? Don't care about book-markable URLs or the user hitting the refresh button and inadvertently re-submitting a form? You can now disable the normal "send a client redirect" behavior and have Tapestry render the HTML immediately. This requirement comes from some particular clients, but honestly I hope it won't be widely used.

Beyond that its been bugs, bugs, bugs and getting the last major features in place; more Ajax support (with still more to come) and generally adding some polish.

I still can't say exactly when this will be ready, but I'm now able to work on Tapestry full time (and then some) so its coming together rapidly.

Thursday, January 10, 2008

Creating new T5 projects the easy way

The Maven archetype for Tapestry projects is really useful for getting up and running quickly.

However, that's not what I use day-to-day. That command line is so long and ugly!

I use the following Ruby script as a wrapper around Maven:

#!/usr/bin/ruby

require 'optparse'

$group = nil
$artifact = nil
$package = nil
$archetypeVersion = nil
$version = "1.0.0-SNAPSHOT"
$offline = false

$opts = OptionParser.new do |opts|
  
  opts.banner = "Usage: new-project.rb [options]"
  
  opts.on("-g", "--group GROUP", "The group id for the new project") do |value|
    $group = value
  end

  opts.on("-a", "--artifact ARTIFACT", "The artifact for the new project") do |value|
    $artifact = value
  end
  
  opts.on("-p", "--package PACKAGE", "The root package for source code in the new project") do |value|
    $package = value
  end
  
  opts.on("-v", "--version VERSION", "The version number of the new project") do |value|
    $version = value
  end
  
  opts.on("-o", "--offline", "Execute Maven in offline mode") { $offline = true }
  
  opts.on("-V", "--archetype-version VERSION", "Version of the Tapestry quickstart archetype") do |value|
    $archetypeVersion = value
  end
  
  opts.on("-h", "--help", "Help for this command") do
    puts opts
    exit
  end
end

def fail(message)
  puts "Error: #{message}"
  puts $opts
  exit
end


begin
  $opts.parse!
rescue OptionParser::InvalidOption
  fail $!
end

fail "Unexpected command line argument" if ARGV.length > 0
fail "Must specify group" unless $group
fail "Must specify artifact" unless $artifact

$package = $package || "#$group.#$artifact"

command = ["mvn"]

command << "-o" if $offline

command << [
  "archetype:create",
  "-DarchetypeGroupId=org.apache.tapestry",
  "-DarchetypeArtifactId=quickstart",
  "-DgroupId=#$group",
  "-DartifactId=#$artifact",
  "-DartifactVersion=#$version",
  "-DpackageName=#$package"]

if $archetypeVersion
  command << "-DarchetypeVersion=#$archetypeVersion"
end

command = command.join ' '

exec command

A typical usage is thus: new-project -g com.example -a myapp ... and we're off and running.