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!

Saturday, August 30, 2003

HiveMind EJBProxy is back

Just got the latest Javassist JAR from Shigeru Chiba and he's fixed the problem related to try ... catch that was breaking the EJBProxyFactory service. He's on Tokyo time, so communications can take a while; I believe he wants to do a release of Javassist 2.6 in the next few days.

Pull the fork back out?

So now the "Tapestry in Action" goes into production; a complicated process of copy editting, typesetting and marketing. One part of this is that I must go back through the manuscript and create the index, a new and mind-numbing procedure. In addition, it's looking good for Manning to public the book under MEAP (early access / online versions of the chapters).

I got some odd feedback from Maryan Bace (publisher at Manning) and Ted Neward about a previous blog. Ted felt that:

The last set of reviews were pretty positive, except for Ryan Cox who was, like, 95% positive, but really didn't like a few aspects of the book ... didn't like the Hangman example app, didn't like the sidebars and warnings, didn't like the deep investigation of the Virtual Library application. This is part of the process ... about fifteen different people have reviewed some or all of the book, and they disagree wildly. Mind Bridge, Geoff Longman, Greg Burd and Dave Buck think the book is aces, and they are my real target audience so I'm not exactly worried.

... was a slam on Ryan. If it could be interpreted that way, I apologize profusely. Both Ryan Cox and Bill Lear were the most negative about the book, and therefore the most useful. Both took considerable amount of time to really work through the manuscript and provide reams of questions, notes and challenges. That's how the process works ... it's suprisingly democratic; as the author, I'm required to respond to each and every reviewer comment. Responding to Bill's comments is what, in my opinion, kicked the book up from a pile of facts into a real, flowing, useful tome. Ryan's comments came later, and so couldn't have the same impact, but he definately zeroed in on particular areas that needed expansion and elaboration. The point of my original blog was that even someone who disagreed on some fundamental aspects of the book was still very positive about the book in general.

Tuesday, August 26, 2003

Performance of different HiveMind service models

Thought I'd do a little comparison of how the different HiveMind service models perform (relative to each other). First of all, I found a huge difference between Hotspot client and Hotspot server; HiveMind seems to really benefit from Hotspot. Second, the big difference is between simple virtual method invocation and invoking interface methods ... an order of magnitude difference with HotSpot server. I think the big difference is that the very simple adder bean gets completely inlined by HotSpot. I'm going to try and find a way to convince HotSpot not to inline the bean code.

The method being invoked is:

public long add(long arg0, long arg1);

Each run invokes the method 50,000,000 times. The elapsed time is the time in milliseconds. Note that the Java clock (System.currentTimeMillis()) is very, very innaccurate.

JDK 1.4, Windows XP, Hotspot Server

Run Bean Interface Singleton Deferred Threaded
Run #1 200 320 2003 2544 2874
Run #2 220 2324 2223 2614 2844
Run #3 210 2454 2894 2654 2894
Run #4 210 2223 2083 2604 2734
Run #5 230 2083 2073 2594 2794

Bean - invoking the method directly on the service implementation class (that is, instantiate the class without using HiveMind)
Interface - Invoking the method against an interface, not object, reference
Singleton - Invoking the method against the service using the singleton model (as expected, very close performance to interface)
Deferred - Invoking the method against the service using the deferred model (slight increase in time reflects the extra proxy and synchronized block)
Threaded - Invoking the method against the service using the threaded model (another increase for the additional proxy and the ThreadLocal stuff)

JDK 1.4, Windows XP, Hotspot Client

Run Bean Interface Singleton Deferred Threaded
Run #1 381 2183 2193 5157 8573
Run #2 380 2203 2213 4116 7701
Run #3 371 2203 2243 4186 7681
Run #4 371 2203 2253 4126 7701
Run #5 371 2203 2213 4126 7701

Big difference switching from Hotspot server to Hotspot client; hard to say why in particular ... less inlining but also less of a difference between bean and interface, but the additional cost of the extra proxies (for deferred and threaded) and for the ThreadLocal stuff (for the threaded model).

Something useful to do next would be to create a more realistic bean, something less likely to be completely inlined by HotSpot, so we can really see the difference between the Bean and Interface invocation costs. I think the take away is that the big cost is the difference between Bean and Interface, the cost of adding Deferred or Threaded service model is costly, but incremental.

In addition, the little bit of performance testing I've done using the HiveMind test suite shows that the one-time cost of parsing the HiveMind module deployment descriptors is signifcant; all else is dwarfed by this cost. I'm concerned, or perhaps merely curious, about performance when you build a full application from a wide mix of singleton, deferred and threaded services. Services calling services calling services, all as interfaces, all with proxies and perhaps interceptors ... what will be the cost of all that wrapper code? On the other hand, what are the costs of executing a managed object as an EJB? I'm fairly confident that refactoring stateless session EJBs into HiveMind services (deferred or threaded) would be a net win performance-wise.

Monday, August 25, 2003

Stick a fork in it!

Tapestry in Action is complete, uploaded and ready to go. Well, not quite, tomorrow when I'm not quite so bleary eyed, I'm going to make a final pass over the manuscript to find any lingering errors. Still, this has been eight months of fairly continuous effort, overshadowing everything else going on in my life, stealing my summer, distracting me from extending Tapestry and HiveMind.

Next up, fill in the Tapestry documentation gaps and make sure Tapestry is 3.0 (final) before the book is on the shelves. Clock is ticking, we have about two months!

Hopefully, many hands will make light work; looks like we may have three (!) new Tapestry members shortly, including Erik Hatcher (aka, Mr. Ant), Tsvetelin Saykov (who works with Mind Bridge) and Harish Krishnaswamy.

Meanwhile, a few folks are not too happy that I responsed to some flame-batewith some industrial strength venom. Was it unprofessional? Perhaps; I do take Tapestry very, very personally (which is paradoxical with how pleased I am at how the community and developer pool is growing). Still, leaving a challenge like that unanswered is not in my nature ... and if you read what's in my reply, I think you'll see that, even within the flame, I'm still on-message and marketing! marketing! marketing!

And now to bed ... tomorrow I buy my new house (!). Yes, it's everything, all the time, 24/7 and full after-burners at Chez Howie.

If you like retro arcade-action-puzzle games, check out Rocket Mania! by Popcap Games. This is the other thing keeping me from finishing the Tapestry docs :-)

Saturday, August 23, 2003

Home Stretch on the Book

I'm on the home stretch now for "Tapestry in Action". Manning wants the final version by the end of this month (Aug 2003) ... I'm reconciling all the references to listings, tables and figures, and exporting my ugly diagrams from Visio into TIFF, which is what the production people need. Pretty much, a gruesome, crushing process.

The last set of reviews were pretty positive, except for Ryan Cox who was, like, 95% positive, but really didn't like a few aspects of the book ... didn't like the Hangman example app, didn't like the sidebars and warnings, didn't like the deep investigation of the Virtual Library application. This is part of the process ... about fifteen different people have reviewed some or all of the book, and they disagree wildly. Mind Bridge, Geoff Longman, Greg Burd and Dave Buck think the book is aces, and they are my real target audience so I'm not exactly worried.

Attack Struts! Don't mention Struts! Compare it to Servlets! Don't mention Servlets! More sequence diagrams! Avoid UML! Keep it short! Go in-depth! ... it's maddening. Tapestry is just so big ... and yet, so simple at the core of it. The same little trick repeatedly endlessly, and the only way I know to demonstrate that is to show that same trick again and again and again.

I just had to take a break, so I did some more work on HiveMind. I've added the concept of different "service models" for services; the existing ones are singleton and deferred. Singleton is a singleton service, created at first reference. Deferred is based on some work I did last week; the service creation is deferred; a proxy is created to stand in for the actual service until a service method is invoked.

The new service model is threaded. This is something new and neat; it bypasses the multi-threading problem by allowing each thread to have its own dedicated instance of the service. That is, the proxy will construct an instance of the service that is bound to the current thread (ah, the magic of ThreadLocal). From that point on, any time that thread invokes a service method, it is directed to that thread's service instance. Same proxy passed to a different thread will get a different service instance ... I actually test this as part of the unit test suite.

There's now a service, ThreadEventNotifier, that is used to inform objects when the thread is "cleaned up" (i.e., the end of the request cycle in a servlet or Tapestry app).

I suspect in the future, I'll add additional service models; for instance, one like threaded, but using a pool of service instances ... and maybe one like threaded, but permanently attached to the thread once created.

Thursday, August 21, 2003

Changed my blog template

I changed around my blog template, to move the links and archives over to the right side. Perhaps I was inspired by http://www.csszengarden.com/.

Actually, this is more of an apology; I think that blogger screws up the dates of old postings when I republish my entire site (to update the older archives to match the new template), and some aggregators may see a flurry of false new postings. So be it.

Wednesday, August 20, 2003

Microkernel Mash Up at The Server Side

A thread on TheServerSide (PicoContainer 1.0 beta 1 has been released.) has, like all threads on TheServerSide, devolved into a rambling, biased comparison of everyone's pet projects.

Such as HiveMind.

Interestingly, I was far from the first to mention HiveMind, but I posted a couple of corrections. Also, Drew McAuliffe doesn't like the name. Pshaw!

Tirade against Out-Sourcing

Sue Spielman has written: Outsourcing in my company? I do not think so.

She really sums up a lot of my basic problems with out-sourcing (based on my own experience): it doesn't save money, it's a PR nightmare, it leads to inferior quality and service, it displaces American jobs, and ultimately, it doesn't save money.

For a long time, my Developer's Mantra was mental flexibility and initiative. The flexibility to pick up new ideas, coding or otherwise, and run with them. The initiative to identify problems and address them. There's that JFK quote (I'll have to paraphrase) about seeing things that don't exist and asking "why not?".

None of the off-shore IT help I've ever dealt with has had either mental flexibility or initiative. Whether it's support staff who don't provide support, or "developers" who produce terrible spaghetti code, it just doesn't work.

That's not a slam on those people ... it's a slam against the short-sighted, greedy, mismanaged companies that hired them to perform a job function that they don't have the experience, English language skills, and mind set to achieve.

Sure, I keep hearing "its the future, get used to it" but I'm not buying that ... Eventually one of these big Fortune 500 companies, or Gartner, is going to actually analyze whether out-sourcing really works. Spending 100% for a successful project is always a better deal than 30%, or 10%, for a failure.

I definitely like Sue's advice that if you are expected to train your off-shore replacement, quit. I just hope her company is looking for a talented Tapestry developer when that comes to pass ...

Meanwhile, I need to check what Howard Dean's stand is on this.

Friday, August 15, 2003

Another book on Tapestry

Here's something fun that popped into me mailbox this morning:
Dear Howard,

We will publish the first german book on Tapestry 3
in December / January.

We would like to contact you few weeks before it finishes
and kindly ask you to write a short foreword for it.
Al long or short as you like.

The Software and Support Publishing Company (owns the biggest Java-Magazin in Germany http://www.javamagazin.de/) has 
agreed to this book.

A book similar to ours will look like
this: http://www.software-support-verlag.de/sus/sus_buch/psecom,id,37,nodeid,8,_language,de.html

I am looking forward to hear from you.

Kind regards
Prof. Dr. Stefan Edlich

By the way: You have provided the wold with a great bunch of software!

Java-Magazin recently published an article comparing Tapestry favorably to WebWork written by Christian Sell.

Wednesday, August 13, 2003

Importance of toString()

I'm always dissapointed when I use some else's code (open-source or proprietary -- though its worse for proprietary) and the objects I get back from that code don't implement toString().

One of the main goals of Tapestry is feedback: when things go wrong, provide the developer with as much information as possible to correct the problem. HiveMind follows the same path, crafting useful exception messages, and providing the same line-precise exception reporting as Tapestry. Every object ever made visible to the client code (the code that uses HiveMind) will implement toString().

It's not that hard, folks!. HiveMind and Tapestry mostly use ToStringBuilder from Jakarta commons-lang. I don't really care about efficiency ... toString() generally gets invoked only in a worst-case situation, where the code is already throwing a stack trace or such. What's important is that the developer be provided with as much useful information as possible ... but not overwhelmed with extraneous detail (see my earlier blog about excessive exception logging).

Even the dynamically generated interceptors and proxies in HiveMind get a toString() method; I mean, which would you rather see:

$Proxy_f6f75b1384_25@b6d6ab

or:
<Proxy for hivemind.test.services.BuilderAccess(hivemind.test.services.BuilderAccess)>
The first tells you nothing at all; the second identifies the service and the interface implemented by the proxy. Which is going to kick start your debugging? Next time you write some "reusable" code remember that it can't really be reused unless it can be debugged, and the first step in writing debuggable code is to implement toString().

Tuesday, August 12, 2003

HiveMind Deferred Service Proxies

I'm really coming to love Javasssist. I've called it a giant hammer searching for nails and I am finding a lot of nails to hit with it.

One thing that was bugging me in HiveMind was that if you create a service, and that service uses some other service (that is, you set a property using the <set-service> property setter), then the other service will be constructed. And so on, and so on. Of course, the service could look up the second service just as needed, but that's bad from both the unwanted-coding perspective and the Inversion of Control perspective (or perhaps those two are perfectly aligned)?

In other words, I want to be able to assign the service as a property (of another service) without actually constructing the service. Fortunately, services are hidden behind interfaces, so all I need is a implementation of the service that looks like:

private syncnhronized TheServiceInterface _service()
{
  if (_service == null)
    _service = _serviceExtensionPoint.constructServiceImplementation();

  return _service;
}

public Foo serviceMethod(...)
{
  return _service().serviceMethod(...);
}

And, of course, where does that implementation come from? Brewed up on the fly by Javassist. So now I can have my cake and eat it too ... all the worrying about when to instantiate classes falls back into the HiveMind framework domain, and is of no concern to the HiveMind user, who simply has an interface and is free to invoke methods on it.

Monday, August 11, 2003

Default symbols in HiveMind

There is now an easy way to set "factory default" symbols in HiveMind. There's a new extension point, hivemind.FactoryDefaults. Contributions to this extension point define default values for symbols. The "order" of the SymbolSource contribution is very high (I suppose I should have use MAX_INT, but instead, it's at 1,000,000). This means that, in all likelyhood, whatever additional SymbolSources you add will be consulted first, before FactoryDefaults.

So, you might ask, what the hell are symbols? Symbols are a kind of escape clause; sometimes the information you want to contribute isn't known until runtime (or at least, until the time the application is installed). This might include database URLs or admin e-mail addresses.

What we don't want is to make anyone unpack a JAR and edit the descriptors ... that's just asking for trouble.

Instead, the descriptor includes a placeholder for the value (using the Ant syntax), i.e.

<database url="${database.url}"/>

At runtime, HiveMind will convert database.url into a real string. How? By using HiveMind extension points. hivemind.SymbolSource identifies different objects or services that can be consulted for symbol values, and establishes the order in which checks take place. FactoryDefaults is one contribution here (if you check, you'll see that there's a service to complement the extension point). You can add your own SymbolSources as well.

I can imagine an installer that would present a UI to collect all of these configurable values ... the database URLs and e-mail addresses. The installer creates a properties file and stores it where the running application can access it; a SymbolSource contribution can read the properties file. Tah dah!

Increasingly, new HiveMind features are being implemented in terms of existing features. This is very cool and to be expected.

Sunday, August 10, 2003

Light at the end of the tunnel!

I just uploaded the final appendix for "Tapestry in Action". That means that main writing is complete! Yow!

What does that leave?

  • Revisions from the technical reviewers
  • Final production issues: fixing all the section numbering and converting all the Visio diagrams into TIFF

I am so sick of the book, you can't imagine; but after I've wrapped up these details I can get back to work on the Tapestry reference documentation (you know, the free stuff).

Friday, August 08, 2003

Geronimo Bandwagon

If you've been reading the mailing lists for Apache's Geronimo, you may have seen me there, plugging HiveMind. To me, it seems like a natural ... but there's the JMX and Avalon crowds as well.

I'm actually a bit skeptical of the whole endeavor; if they were starting from scratch, this would be a total disaster ... but to some degree, many of the bits and pieces are already available. Even so, I'm already concerned this is a private party out in public. We'll see if they can assemble a complex project and do it all via e-mail and wiki.

Tapestry Elevator Pitch

"And God said, 'Let There Be Light!' And there was Light. And it was good." But it lacked a clean separation of concerns.

Well, that's not quite right. An elevator pitch for Tapestry is hard because there is so much misinformation about Web Applications. Everyone think's they're easy, becase everyone's doing 'em, right? Developers are so mired down in getting things working with Servlets or Struts they can't imagine that there's a better way. There is. Lately, I've been going with "the easiest choice is the right choice". Or:

Software development hasn't gotten harder in the last decade ... it's outrageously tight "first to market" schedules and ever escalating requirements that have been putting the pain on developers. People think web applications are easy, because everybody's doing them, but there's a lot of enterprise-critical applications being held together with duct tape and chewing gum. There are so many things wrong with the web application development model: that all developers are fully equal, that Java developers can do HTML (or even choose colors), that what works in a prototype will work in a full scale application. Tapestry's component approach takes on all of these issues and more: it lets the Java guys do Java, let's the HTML guys do HTML and lets everyone work together sanely. It provides a standard approach to all the issues, which keeps every developer from becoming the "lynchpin" of their little code-fiefdom. It keeps simple things simple, and makes complex things simple as well. With Tapestry, when you choose the easy option, you aren't screwing yourself in the long run: the easiest approach is usually the best approach, by design. Tapestry doesn't get in the way of developers, it liberates them, helps them, and keeps them focused on the domain issues, and lets them ignore all that annoying plumbing.

Moving code

Last night, I tagged HiveMind as 1.0-alpha-1 and created a branch on Tapestry (hlship-3-1). The branch represents the future Tapestry 3.1 code base. First order of business: move code to HiveMind.

This is important, because in alpha-1 the dependencies are backwards: HiveMind depends on code from Tapestry. That code is boring stuff: IResourceResolver, IResourceLocation, ILocation, and related implementations.

I've moved the interfaces over and stripped off the leading 'I', and moved over implementations and tests. The major changes:

  • IResourceLocation --> Resource
  • ILocation -> Location
  • IResourceResolver -> ClassResolver
  • ILocationHolder -> LocationHolder

Also, moved over ApplicationRuntimeException.

With a little shaving to fit, got the HiveMind code coverage up to 88%, with 112 tests, Tapestry 3.1 needs a little work before it will be functional again, but its close.

Tuesday, August 05, 2003

HiveMind -- progress

I've been adding more and more to HiveMind in the last couple of days. Yesterday, I added several new translators: extension-point, service, enumerated. I'm keeping the documentation up-to date. I just fixed some latent bugs in Javassist code generation. The code coverage is at 87% (pretty good for 93 files and 5,491 ncloc). I've made recovery from module parsing errors more configurable.

I've added a nifty system to translators called "initializers"; this allows you to say something like "int,min=5" to enforce a minimum value when converting an attribute from a string to an Integer. Each Translator implementation may have a second constructor, which takes a string, and can interpret the string (usually as a list of key value pairs).

There's been some discussion on the Tapestry mailing list about HiveMind. Dave Solis wants meaty examples. Colin Sampaleanu doesn't like the registry part, he wants a more pure IoC (Inversion of Control). You can use HiveMind in an IoC mode, especially with the new translators combined with the BuilderFactory, or you can access the Registry to lookup services and extension points in your own code. I prefer to give options. He also had some good points about testing.

I'm thinking of adding some "deferrment" capability to HiveMind. For example, when you obtain a service, you may get an object that implements the interface, but doesn't talk directly to the service. Instead, as needed, it will ask the service extension point to create the instance (and interceptors) ... that is, on first invocation. Likewise, getExtensionPointElements() may return a List and defer the actual creation of the list of elements until first access.

Just talked with my buddy Prashant and another good thing for HiveMind would be a validator ant task; something that could read all the module deployment descriptors and validate that all contributions to all extension points are valid ... that is, recognized elements, recognized attributes, required attributes provided, and so on.

Maven -- Update

I still can't get Tapestry to build under Maven but yesterdays "current peave" appears to be innacurate. I don't know why, but redoing the same steps now seems to work.

Next step is to get my tweak to the clover plugin to actually work.

Update to the update: my maven bulid keeps failing with OutOfMemory error. Don't know why. That explains the discrepency ... yesterday, I wiped out my %MAVEN_HOME% before building and the result was a partial Maven install that fails when building HiveMind.

Monday, August 04, 2003

Maven -- The Emperor has no clothes

I still can't believe that the Maven crew is trying to go to a 1.0 release while Maven is clearly in an early alpha stage. For simple, simple projects like HiveMind, it works acceptibly, but I've had zero luck getting Tapestry working ... Maven just can't handle multiple projects, despite its claims. Maven is a great idea in theory, but in practice, it falls flat. They'll probably get it together eventually, but it is not ready for primetime yet.

My current peave is that I can't build Maven locally (I want to make a minor fix to the clover plugin). Not just pulling down the CVS HEAD, but I pulled down a tagged release, the beta-10, and tried to build locally. Crash and burn. The whole point of Maven is that this should not happen, I have the same code as they did when they rolled out the beta-10 distro, and all the dependencies line up because they come out of the central repository. Either Maven has some hidden dependencies and doesn't like JDK 1.4 on XP, or they messed up with the tagging, or Maven just doesn't work as advertised.

Meanwhile, the problem with Maven is that it adds many, many layers of indirection on top of Ant. Although the output is pretty, and some of the reports are cool, unless things change soon, I'll be back in the Ant camp --- the 1.6 release of Ant promises to have a lot of the things I'm missing, like a rational way to reuse build files across a large project.

Friday, August 01, 2003

More fun HiveMind stuff

Getting HiveMind to work with Vista (the WebCT product) is going well. I immediately found that I needed <schema> to support an id and ref-id attribute, to make it easy to re-use a schema within a module. Vista has Startup, PostStartup and Shutdown extension-points with long, but identical, schemas.

I think the code and general appraoch is stabilizing. Things to do:

  • Validations of extension contributions. Be nice to have equivalents to W3C Schema minOccurs, maxOccurs, <sequence> and <choice>
  • More XML rules and translators
  • More base services

Still, that's pretty cool. HiveMind is turning into a powerful bit of code ... right according to plan.