Tapestry Training -- From The Source


Tuesday, September 28, 2004

[Off Topic] Roller Coaster Tycoon 3 demo

I downloaded the Roller Coaster Tycoon 3 demo this morning. I've always been a big fan of the original Roller Coaster Tycoon (RC1), even though I never came close to finishing it. I just like building the parks and letting the little people run through it.

I've always thought it was marvelous that a game that was fully creative, non-violent (well, except for dropping the peeps in the pond) and intricate was so popular.

It looks like they've retained the essential nature of the original. You are still building your park on a grid, but your eye, your camera, is free to roam much more freely ... rotating and zooming to your heart's content.

The ability to get a peep's eye view of any ride, not just roller coasters, is wonderful.

The demo is a major power hog; my laptop (A Dell Inspiron 8200, 1 gig of ram, 2ghz P4, GeForce 4 440 Go) is somewhat taxed ... it will run full screen at 800x600 but only just. I suspect larger parks will be a problem. This game is going to cost me a lot of cash for a new system.

I haven't found where you get to review all your peep's thoughts (I hope that's still in there). They've also made the concession stands overly complex (you get to define a whole menu, control how many pickles are put on each burger and a bunch of other stuff nobody will ever do).

The biggest win is that you can pause the game to do construction. That was always my biggest beef with RC1 ... constant interruptions when building your big coaster.

The peeps are much more involved; different sexes and ages. There's some kind of group (or family) system.

Parks also simulate day and night as well as season; the park looks terrific at night, and there are fireworks shows!

Alas, back to work for now!

Wednesday, September 22, 2004

Feedback++: Going beyond Line Precise Error Reporting

This I like ... for Laurent Etiemble, even line precise error reporting is not enough, so he has made some improvements to display the actual text that is in error. Details in his blog. It looks like:

This is certainly something that could show up in Tapestry 3.1 (either by duplicating Laurent's work, or getting him to properly donate it). Additionally, Geoff has talked about some kind of hook that would make the stack trace clickable links ... clicking the links would open the correct file inside Eclipse.

HiveMind 1.0 final tomorrow!

The votes have been cast and, predictably, HiveMind 1.0 final release has been approved. The web site has been updated, an the Maven repository has been seeded with the 1.0 final jars. The distributions have been uploaded to Apache, and the only thing left is to wait about 24 hours for the Apache mirrors to pick up the files. Tomorrow morning I'll update the Jakarta web site and submit the news item to TheServerSide.

And still, so much more to do in HiveMind 1.1 and in Tapestry 3.1.

Thursday, September 16, 2004

Tapestry 3.1 and backwards compatibility

I've gotten a couple of concerned notes about backwards compatibility from Tapestry 3.1 back to Tapestry 3.0. People are concerned they may have to throw away some or all of their 3.0 applications when they upgrade to 3.1.

Tapestry has historically had a fuzzy distinction between APIs (application program interfaces, intended for exposure to, and use by, end-user developers) and SPIs (service provider interfaces, or at the very least, internal interfaces that are expected to change between releases). The interfaces in the org.apache.tapestry package are generally APIs , and the interfaces and classes is other packages are more often SPIs.

Despite the large amount of refactoring so far, nothing I'd consider an API has changed, though some SPIs have changed.

I'm working to make the upgrade path from 3.0 to 3.1 pretty painless for 90%+ of users.

  • It is possible that the <extension> element will no longer be honored (you'll get a runtime warning).
  • It is likely that the <service> element will no longer be honored.
  • It is possible that it will no longer be allowed to sub-class BaseEngine. Certainly the AbstractEngine and BaseEngine classes have changed significantly, and will likely merge together.
  • Parameter directions from 3.0 DTD specs will be ignored, and will always be implemented using the new smart caching connected properties code (yet to be written).

I think it will be a reasonable upgrade path from 3.0 to 3.1. For simple applications and pages, nothing will be necessary. For a minority of applications, there will be some localized changes.

It would be very nice to more cleanly separate internal interfaces and classes from the public APIs. However, doing this properly will certainly break backwards compatibility.

Part of the problem is the use of inheritance in Tapestry. In Tapestry 3.x, your pages and components must subclass from Tapestry base classes. This exposes much internal implementation details about those classes, dragging things that should be firmly in the "internals" category out into the open.

Part of my vision for Tapestry 4.0 (besides stripping the leading "I" off any remaining interfaces) is to break the inheritance requirement. In that release, your pages and components will be true POJOs. This will be an even better separation than is possible today. Something very much like todays IPage/IComponent hierarchy will exist .. but that will be largely be internal to Tapestry. The classes you write will be peers of the actual components. In general, your code will not access the component directly, but will instead have information, properties and services from the component injected into your classes.

I'm very excited by this potential, but first things first ... have to get 3.1 up and running and not leave all the 3.0 users behind!

Wednesday, September 15, 2004

Whew! Full speed ahead!

The vast refactoring of Tapestry continues. Today I completed my first pass. All the major subsystems of Tapestry (such as ISpecificationSource, ITemplateSource, DataSqueezer, IScriptSource, etc.) are now HiveMind services. Yes ... everything still runs pretty much identically, but under the covers the code is evolving into smaller, simpler classes.

In addition, the first real changes (still, not visible though) are now in place. There is now a collection of BindingFactory implementations, one for each type of binding (OGNL expression, message keys, and literals). There's a BindingSource service that knows how to take a string (from an HTML attribute value) and find the correct BindingFactory, based on prefix, to generate a IBinding instance from it.

This is now being used for all bindings created by the SpecificationSource and the ComponentTemplateLoader. Its driven by a configuration, which means that it will be super easy to add additional binding prefixes (even application specific ones). This is the first, approachable, step along the path to what will be Tapestry 3.1.

It's a great, iterative process. New code I create is truly testable ... I hope to start retiring many of the integration tests (the ones driven by XML script files) since those are pretty darn slow to execute compared to focused unit tests.

I had one great headache; I converted a utility class (BaseComponentTemplateLoader) into a service (ComponentTemplateLoader). BaseComponent used to create one instance of this every time a component loaded its template. I converted this to a threaded service, because it had some internal state.

After many headaches, I realized that BaseComponent was doing it right ... the state wasn't merely threaded, it was reentrant. Loading a component will often cause a new component to be created ... and if that new component has a template, the process goes recursive. I didn't realize that, and started getting bizarre, impossible results. Eventually, I realized what was going on ... and my final solution is very similar to where I started. ComponentTemplateLoaderImpl is a normal service (not threaded), but delegates just about all of its behavior to ComponentTemplateLoaderLogic, which is created (as before) for each component and discarded immediately.

This makes me think that HiveMind needs a reentrant service model. I think Spring has something like this, "prototype beans", where each method invocation causes a new implementation instance to be created. That would be easy enough to do in HiveMind.

It has been very slick seeing the mix of service implementations; most of the Tapestry services are ordinary singletons. A few, which hold client-specific state for the duration of a request, are threaded. However, when these are combined together, the singletons and threaded code doesn't have to know anything when they invoke each other ... its just objects and interfaces and the mechanics of locating a thread-specific instance to process a particular service method is entirely hidden.

So, Tapestry is getting more powerful and simpler at the same time. That's hard to beat. Not sure when I'll have time for more or what I'll hit next ... I'm following a kind of round-robin approach, where even the code I've created recently is ready to be refactored into smaller and smaller pieces. Probably next up is to start thinking about engine services. There's also refactoring around OGNL 3.0. Or getting ready for the major rework for modularity (splitting the application across multiple folders). It's all good!

Tuesday, September 07, 2004

[Off Topic] VoteOrNot.org

Everyone knows its important to vote. The stakes are extraordinarily high for the current presidential election ... but even so, voter turnout in this country is abysmally low.

I'm proud to say that I've voted in every presidential election since I was 18, including most primaries. I've also voted in every (I think) state-wide election. Too many people, though, let themselves get sidetracked.

How about if someone offered you $100,000 to vote? Oh, and $100,000 to a friend who got you to vote? That's what VoteOrNot.org is doing. Go to their site, promise to vote, and possibly win after the election.

Saturday, September 04, 2004

NEJUG - Erik Hatcher on Lucene

Erik Hatcher will be in town next week to present on the Lucene text searching/indexing tool to the NEJUG (North East Java User's Group). This is occuring 5:30pm on September 16th. If you can snag a reservation, you should ... Erik's a great presenter and Lucene is a great (and largely unrecognized) technology.

Progress on all fronts

Tapestry 3.1 is really getting into gear now; I've been working my way forward from the servlet, converting everything into HiveMind services, pipelines and configurations. I've also said sayonara to revision histories and been moving source code into "standard" directories (that is, src/java). I can see switching to Subversion for source control someday, just because it does a proper job of moves and renames -- history on files is maintained even when the file is renamed or moved to a new directory. It seems like CVS is pretty antagonistic towards refactoring, especially in context of the XP mantra of fearless, merciless, constant refactoring.

Tapestry's bug list is now under JIRA, which is so much easier, faster and more sensible than Bugzilla.

I've taken a pause from working on the Tapestry code to work on the Tapestry documentation. The awkward DocBook stuff is being phased out ... all the documentation will be converted to Forrest format, which means better and more consistent navigation. I realized that unless I had the Tapestry 3.0 documentation in a ready to edit form, I would not update it as I was making the real changes in the 3.1 code. As I found during Tapestry 3.0's too-long development cycle, if you don't keep the docs up to date as you work, your problems just multiply. With HiveMind, I've worked diligently to keep docs up to date at all times, and I want to start on the right footing for Tapestry 3.1 as well.

James Carman looks likely to be the newest HiveMind committer, the vote is in progress but opposition is unlikely. Meanwhile, I've just fixed a few nasty little bugs in HiveMind, in prep for release candidate 2. Nasty, of course, always means class loaders and/or thread concurrency. Now, throw dynamic class fabrication into the mix.

And I signed a contract for three months of work, possibly more (details to come). So the good news is that I have money coming in and am doing Tapestry work full time. The bad news is I don't have huge amounts of time to do things like build out the Tapestry lab course I've been dreaming of, or do the Hibernate research I've been hankering for (until and unless that becomes part of my contract). I've actually been full time with this client for almost two months; I've been letting others pick up the slack in terms of answering questions on the mailing lists while I do more and more heavy lifting on the code front (especially on the Tapestry side).

Much more urgent is the need to get out of the house and hit the beach! Summer's ending and I'm still pretty pasty-white. Time to break out the boogie boards and hit the waves.