Friday, September 25, 2009

Off topic: Quizissippi

For those of you in the Portland, OR area ... mark your calendars for Wednesday evenings at the Mississippi Pizza Pub for Quizissippi, hosted by the wonderful Red Molly. It's a trivia contest with cash prizes ... and since it's run by Molly it will be very fun and very competitive and not quite like any trivia contest you've previously experienced.

The first Quizissippi is at 7pm, on October 7th in the Atlantis Lounge. I'm already looking forward to Mark pouring some of his great drinks, and Molly dazzling us all with her cleverness. And maybe some quick cash ... if I'm smart enough!

Joys of cross-browser development

I'm working on a dependent drop-down list inside my Tapestry application (one I'm building for a client). Guess what? They fire the critical "change" even completely differently.

In FF, change is fired when:

  • You hit enter after tabbing into the select and changing its value
  • You tab out of the field after changing its value with the up and down arrows
  • You mouse click on the select, then click on an entry in the pop up list

This is sensible, even if it does not, perhaps, match the spec.

In IE 6:

  • After using the mouse to select a value from the popup
  • After changing the value with the up and down arrows

In other words, any visual change to the select causes an immediate change event. Of course, I need to work around IE's behavior since it will result in way too many Ajax requests. My event handler needs to set a timer and wait some time, perhaps 1/4 seconds, before doing the Ajax update (but only if another change event hasn't been triggered). Fortunately, I have Prototype's delay on my side.

Meanwhile, who implements the spec correctly? Here's what it says:

The onchange event occurs when a control loses the input focus and its value has been modified since gaining focus. This attribute applies to the following elements: INPUT, SELECT, and TEXTAREA

So, when using mouse selection, FF fires early (before the tab out of the field, or when you hit enter), and IE fires early all the time.

And for those who have asked ... yes, I'll "productize" this code and put it into Tapestry 5.2!

Thursday, September 24, 2009

Devoxx 2009: Tapestry and Clojure

devoxx logo Coming up in November ... I'll be at the Devoxx 2009 conference in Antwerp, Belgium. I'll be presenting two 60 minute talks: one as an introduction to Tapestry (Nov 20th, 10:30-11:30, Room 9) and another as an introduction to Clojure (Nov 18th, 12:00-13:00, Room 6). Given that my existing talks take closer to 90 minutes, this is going to take fast talking and a bit of editing!

Devoxx is a very cool conference, run by the user group community and very well organized. It's one of the best places to speak because of the quality of the A/V: it takes place in a movie theater, with giant screens and plush, stadium seating.

This is my first return to Devoxx since 2004, when it was still called Javopolis. With luck, this time, I won't succumb to jet lag and comfy seats and start snoring in someone's session!

Tuesday, September 22, 2009

No Fluff Just Stuff Seattle Roundup

It was a huge pleasure to be speaking at a No Fluff Just Stuff conference again, it's been much too long. This was a good show with a lot of folks coming down from Vancouver, BC to attend.

This was an odd show for me, as we didn't do any Tapestry talks at all. However, all three of my talks (an introduction to Cappuccino, and two talks on Clojure) were well attended, with good questions and some fun discussions between sessions. I'm looking forward to doing these same sessions, with a number of improvements, in the Spring when NFJS starts back up.

Interestingly, I was busy writing Clojure code almost continuously in the back row of other speaker's sessions ... but this didn't stop me from appreciating Scott Davis's great talks on Grails, and on "deconstructing Web 2.0". Also, I had a lot of interaction with Brian Goetz ("are all web application's broken"). As usual, as soon as you mix Java with concurrency, it's a bit sobering. Tapestry helps here, but is not a complete panacea against some of the "nightmare scenarios" that may become more commonplace as the number of CPU cores increases.

I'm getting more adept at advanced Clojure; I've been busy adapting the concept of parameter destructuring to pulling data out of the request path and query parameters.

(defaction increment-count
  {:path "count/increment"}
  [env] 
  [count :int] ; destructure the value after "/increment" as an integer
  (send-redirect env (link env show-counter [(inc count)])))

This defines a Cascade action, mapped to the "count/increment" path. A number is expected to follow (i.e., /count/increment/4) and the job of this action is to increment that value and redirect the user to the show-counter view.

Cascade actions are still functions, thus the normal parameter declaration: [env]. Cascade views and actions always take a single parameter, a map called "the environment" that provides access to Cascade-specific values as well as Servlet API objects.

The path destructuring follows: [count :int] which destructures the first "extra path" value as an integer. There's a number of built-in parsers referenced by keywords such as :int, or you can supply a function that takes a string and returns a value. If another pair of values is given, that applies to the next value in the path.

I'm finding this a pretty elegant way to express this secondary aspect of mapping URLs to view and actions; there's additional syntax for destructuring query parameters instead of path values. I may extend this further, to handle default values for missing terms in the path.

I try to capture some of this in my Clojure talks; the idea of growing the language up, adding the new features you need. From one perspective, this is just a domain specific language, but in the Lisp world, that concept is so deeply entrenched that there isn't even a word for it beyond "programming". This is one part of the overall Clojure picture that gets me very excited, and I'm continuing to struggle with how to express this to people for whom even the Lisp syntax is alien and off-putting.

Monday, September 21, 2009

Speaking at ApacheCon 2009

Just a reminder ... I'll be spreading the good word about Tapestry at ApacheCon this year. My session is Tapestry 5: Java Power, Scripting Ease! on Wed Nov 04 at 11am.

Wednesday, September 16, 2009

Tapestry Performance Benchmark (vs. Wicket, JSF, etc.)

Peter Thomas has created a detailed performance analysis of Wicket, Tapestry, Grails and Seam. It's an interesting read from non-Tapestry user's perspective, and complements Ben Gidley's findings.

He's measuring raw performance and Wicket narrowly bests Tapestry in most categories, with Seam pretty close and Grails much further out.

I'm disturbed by some of his problems developing the application (with respect to adding client-side credit card number validation) and there's no mention of Tapestry's other qualities, such as live class reloading, exception reporting, etc. Still, criticism of Tapestry's documentation hits close to home (and it, alas, too fair). Accurate and very complete, but not organized for a beginner ... something I'm hoping to address over the next few months.

Like Tapestry? Read German? There's a book for you!

book cover

Igor Drobiazko has just announced his new book, Die Entwicklung von Webanwendungen mit Leichtigkeit! (The development of web applications with ease!).

Alas, it is in German, though he hopes good sales in Germany may lead to a translation for the English speaking market. It's available as an e-book now, and in hardcover at the end of September.

Wednesday, September 09, 2009

Formos in the news

I may no longer work at Formos, but I'm still pleased to see a nice writeup about Formos and StreamBank. StreamBank is an application that helps land owners and The Freshwater Trust work to improve stream health and water quality across Oregon. The article doesn't state this, but StreamBank is written in Tapestry (it started as Tapestry 4 and was ported to Tapestry 5).