Saturday, January 31, 2009

Using Maven to create a new Tapestry 5.1 project

I've been digging deep into the (revised) Maven archetype plugin: the tool used to generate new projects from a template. The existing quickstart archetype had some glaring omissions, partially related to limitations of the old plugin. The new plugin makes many more things possible.

In the past, you needed to specify the new project's groupId, artifactId and other data on the command line. This process was so tedious and error prone that I advised wrapping it up in a Ruby script.

Now it's a bit easier, as Maven will ask you for any necessary properties:

$ mvn archetype:generate -DarchetypeCatalog=http://tapestry.formos.com/maven-snapshot-repository
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'archetype'.
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Default Project
[INFO]    task-segment: [archetype:generate] (aggregator-style)
[INFO] ------------------------------------------------------------------------
[INFO] Preparing archetype:generate
[INFO] No goals needed for project - skipping
[INFO] Setting property: classpath.resource.loader.class => 'org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader'.
[INFO] Setting property: velocimacro.messages.on => 'false'.
[INFO] Setting property: resource.loader => 'classpath'.
[INFO] Setting property: resource.manager.logwhenfound => 'false'.
[INFO] [archetype:generate]
[INFO] Generating project in Interactive mode
[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)
Choose archetype:
1: http://tapestry.formos.com/maven-snapshot-repository -> quickstart (Tapestry 5.1.0.0-SNAPSHOT Quickstart Project)
Choose a number:  (1): 1
[INFO] snapshot org.apache.tapestry:quickstart:5.1.0.0-SNAPSHOT: checking for updates from quickstart-repo
Define value for groupId: : com.formos 
Define value for artifactId: : demo1
Define value for version:  1.0-SNAPSHOT: : 
Define value for package:  com.formos: : com.formos.demo1.web
Confirm properties configuration:
groupId: com.formos
artifactId: demo1
version: 1.0-SNAPSHOT
package: com.formos.demo1.web
 Y: : 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 24 seconds
[INFO] Finished at: Sat Jan 31 13:12:31 PST 2009
[INFO] Final Memory: 8M/14M
[INFO] ------------------------------------------------------------------------
~/work
$ 

The key part is the -DarchetypeCatalog=http://tapestry.formos.com/maven-snapshot-repository, which points Maven at Tapestry's own nightly snapshot repository. It picks up a catalog file from there which points to the quickstart archetype stored inside the snapshot repository. No muss, no fuss.

Of course, the first time you run this, Maven has to download about 34MB of modules!

In any case, it works nicely. I put some extra effort in so that the archetype description clearly identifies the exact version of Tapestry.

The new quickstart archetype is much improved; it now includes a Layout component that wraps the page content using a free CSS layout, "concrete" (which has a Creative Commons license). In other words, your application will look good from day 1, though (of course) I'd expect you to throw away the layout subsequently. Anyway, this will answer some questions such as: "how do I use a Layout component?" and "how do I access a message catalog?"

I can see replacing the "concrete" layout with something more general, less blog-oriented (but that's beyond my CSS/HTML design skills!).

All of this is all usable right now. Have fun!

Friday, January 30, 2009

A tip for TestNG: Keep the Constructor Simple

TestNG does not do a great job of reporting exceptions when instantiating your test classes. Keep the content simple. If you are going to do anything that can throw an exception, defer it by creating a setup method annotated with @BeforeClass.

In my situation, I had an exception, and add my normal TestNG verbosity level, 2, there was no obvious output explaining why my tests didn't run, just a message about "unable to instantiate" my test case class. Upping the verbosity to 10 helped me identify the problem ... at which point I moved a bunch of setup logic out of my constructor and into a setup configuration method.

Sunday, January 18, 2009

Using a Samsung ML-1450 with Airport Extreme

I just upgraded my router to an Airport Extreme, partially just to allow Suzy to use the printer even when I don't have my laptop hooked up. However, the printer in question is a Samsung ML-1450 which doesn't have great compatibility under Mac OS X.

After a little searching I have it working quite nicely. An Apple Support Thread plus some poorly written release notes almost tell the whole story.

Remove your printer (from the Printer Preferences) if it currently exists.

Delete the folder /Library/Printers/SAMSUNG. That's all the old set of Samsung drivers.

Download the updated Samsung Drivers.

Run the install; it will do a full restart.

Open Printer Preferences and add the printer back in. It should auto-discover the new drivers (which will display as "Samsung SPL 2.5").

Tuesday, January 13, 2009

The Tapestry Roadshow at The Great Indian Developer Summit (April 22 - 25, 2009)

I'll be presenting three sessions at the Great Indian Developer Summit in Bangalore, India this coming April. The sessions are on Clojure, Tapestry IoC, and a long tutorial session on Tapestry 5.

I'm not sure what days I'm speaking yet.

Monday, January 12, 2009

Comparing Prototype and jQuery

Glenn Vanderburg has written a careful treatise on why he prefers Prototype to jQuery. The thing about Glenn is that he doesn't write (or talk, or think) in terms of "feelings" or "impressions"; his thoughts are clear, and organized, and fact based, and detailed.

I looked at jQuery about two years ago; to me it seemed a little iffy, a little skewed towards web developers doing bespoke web page development, rather than the dynamic generation Tapestry is all about. That impression may or may not be accurate, but Glenn has nailed some significant differences in the design and implementation of the two frameworks, which is why Prototype comes out on top.

Wednesday, January 07, 2009

Upcoming features for Tapestry 5.1

I've been working on some new features for Tapestry 5.1. Importantly, I've been trying to get my head around Spring Web Flow and how that would integrate with Tapestry without sacrificing the flavor of either framework ... fortunately, Keith Donald (SWF Head Honcho) has been helping out.

I'm also very interested in performance ... or really, throughput. I made a number of changes in December that dramatically improved Tapestry performance for very large and complex pages (with thousands of component renders). It can be an uphill battle, given that Tapestry creates an in-memory DOM of the page and streams that out at the very end (unlike a JSP that can spit out bits and pieces of content immediately at the start of its render). There's certain overhead in creating all those DOM objects and then navigating them while rendering. So where we take away on one side, we need to add back on another ...

The goal is to minimize the amount of traffic over the wire; specifically, the amount of static content: assets such as images and stylesheets that don't change during the life of the application.

Tapestry 5.1 now has built-in GZIP compression of responses, both for dynamic page renders (traditional and Ajax) and for those static assets.

I'm also automatically building versioned URLs for context assets (not just classpath assets stored inside JARs); they'll get the benefit of automatic compression and far-future expires headers too.

This falls into my vision for Tapestry in particular, and frameworks in general: they should help you employ best practices, even if you don't even know such practices exist. Just using Tapestry becomes a best practice all by itself*.

Another way to embrace this view is to see Tapestry as the embodiment of the combined experiences of the Tapestry developers and community over the last many years. Good lessions, hard won, realized in code.

*At this point, steam should be coming out Ted's ears!

Monday, January 05, 2009

Rapid Turnaround in Tapestry 5

Borut BolĨina has a screencast demonstrating live class reloading in Tapestry 5. And he's doing it with Jetty, in Windows ... so he includes the fixes to the environment to make this work (surprisingly, the problem is with CSS files, not reloaded Java classes!)

It's easy to dismiss how important live class reloading is; you tend not to appreciate how volatile the web tier is, or how often you are twiddling your thumbs (or reading blogs ... Hey! You get back to work!) waiting for redeployments and reloads. Live class reloading lets you explore your solution space a little bit at a time, without paying a horrible cost.

That's exactly what I do in live demos, or when teaching labs. I put a little bit into the template, a placeholder for what's coming. And I refresh the browser. Then I add some properties or event handler methods to the code, and components to the template. And refresh the browser. Then I start checking error cases and edge cases, making changes, refreshing the browser.

I often get runtime exceptions; usually there's a snippet of text (such as the properly spelled property name) in the exception page that I can paste into my code. Refresh the browser, and continue. Working incrementally this way is faster and easier, with less waste and frustration.

You get used to this style very quickly and then the thought of going back to an environment that doesn't support it (Struts, Tapestry 4, even Flex) is disheartening.