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.
The inside scoop on what's happening with Tapestry ... from the creator of the Apache Tapestry framework. Plus all the normal, random thoughts on coding and technology.
Tapestry Training -- From The Source
Saturday, August 30, 2003
HiveMind EJBProxy is back
Pull the fork back out?
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
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!
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
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
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
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
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
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
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
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
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
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
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.