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!

Monday, May 17, 2004

By Request: How Line Precise Error Reporting is implemented

Hi Howard,

I read your blog and I'd like to make a request.  I'd really like to read 
more technical details on techniques you might use to get line precise 
error reporting.

This is one of the best features of tapestry and if you can pass on some of 
the details of how to go about it and get people excited about doing it 
themselves that could only be a good thing.  This is typically an area 
where most other open source projects fail badly.  The normal error 
reporting seems to be the null pointer exception.

Regards,


Glen Stampoultzis
gstamp@iinet.net.au
http://www.jroller.com/page/gstamp

I agree with all of this, but it's not just open source projects which fall flat in this area ... and this is a vitally important area: Feedback, one of my four key aspects of a useful framework (along with Simplicity, Efficiency and Consistency). Without good feedback, the developer will be faced with a challenging, time-consuming puzzle every time something goes wrong in the framework code. It's not enough to say "garbage in, garbage out" ... if the framework makes getting the job done harder, or even just makes it seem harder, then it won't get used, regardless of what other benefits it provides.

Line precise error reporting is not magic, but it is a cross-cutting concern (Dion is thinking about how to make it an aspect), so it touches a lot of code.

It starts with the Resource interface, which is an abstraction around files; files stored on the file system, at a URL, or within the classpath. Tapestry extends Resource further, adding the concept of a file within a web application context. The Location interface builds on this, combining a resource with lineNumber and columnNumber properties.

The XML, HTML and SDL parsers used by both HiveMind and Tapestry carefully track the location (in most cases, by making use of the SAX Locator to figure out where in a file the parser currently is).

All the various descriptor (in HiveMind) and specification (in Tapestry) objects implement the Locatable interface (having a readable location property), or even the LocationHolder interface (having a writable location property), typically by extending from BaseLocatable. As the parsers create these objects, they are tagged with the current location provided by the parser.

Later, runtime objects (services and such in HiveMind, components and such in Tapestry) are created from the descriptor/specification

You can see how my naming has been evolving. Descriptor is a better term, I don't remember where "specification" came from, but it's now entrenched in Tapestry terminology.
objects. The runtime objects also implement LocationHolder, and the location of the descriptor object is copied into the location property of the runtime object.

The next piece of the puzzle is that exceptions need to have a location as well! When an exception occurs in a runtime object, the runtime object throws an ApplicationRuntimeException that includes the correct location.

There are a couple of utility methods on the HiveMind class used to help determine what the correct location is:

    /**
     * Selects the first {@link Location} in an array of objects.
     * Skips over nulls.  The objects may be instances of
     * Location or {@link Locatable}.  May return null
     * if no Location can be found. 
     */

    public static Location findLocation(Object[] locations)
    {
        for (int i = 0; i < locations.length; i++)
        {
            Object location = locations[i];

            Location result = getLocation(location);

            if (result != null)
                return result;

        }

        return null;
    }

    /**
     * Extracts a location from an object, checking to see if it
     * implement {@link Location} or {@link Locatable}.
     * 
     * @returns the Location, or null if it can't be found
     */
    public static Location getLocation(Object object)
    {
        if (object == null)
            return null;

        if (object instanceof Location)
            return (Location) object;

        if (object instanceof Locatable)
        {
            Locatable locatable = (Locatable) object;

            return locatable.getLocation();
        }

        return null;
    }

This method is particularly handy to the ApplicationRuntimeException class, since it may want to draw the location from an explicit constructor parameter, from a nested exception, or from an arbitrary "component" associated with the exception:

    public ApplicationRuntimeException(
        String message,
        Object component,
        Location location,
        Throwable rootCause)
    {
        super(message);

        _rootCause = rootCause;
        _component = component;

        _location = HiveMind.findLocation(new Object[] { location, rootCause, component });
    }

That's pretty much all there is to it ... but it's all for naught if all this location information is not presented to the user. The location will generally "bubble up" to the top level exception, but you still want to be able to see that information. Tapestry's exception report page does a great job of this, as it displays the properties of each exception (including the location property), and then tunnels down the stack of nested exceptions (this is actually encapsulated inside the ExceptionAnalyzer class).

Line precise error reporting isn't the end all of Feedback. Malcolm Edgar, a one-time Tapestry committer, has been working on his own web framework (I believe for internal use at his company) ... it goes one step further, actually displaying the content of his equivalent to an HTML template and highlighting the line that's in error. That's raising the bar, but perhaps Tapestry will catch up to that some day.

Further, simply reporting locations isn't enough. If I pass a null value into a method that doesn't allow null, I want to see a detailed exception (You must supply a non-null value for parameter 'action'.) rather than a NullPointerException. A detailed exception gives me, the developer, a head start on actually fixing the problem. Explicit checking along these lines means that the location that's actually reported will be more accurate as well, especially considering that there's no way to attach a location to a NullPointerException.

Monday, May 10, 2004

Thinking about Flex

I was very impressed by the Flex presentation at TheServerSide.

Flex is a rich client toolkit. Flash and ActionScript on the client. Java and XML on the server. RMI or Web Services in between. The client contains all the state, the server is wonderfully stateless.

I first learned a bit about Flex from Matt Horn, who works for Macromedia; they hired a bunch of J2EE developers in one of their acquisitions, and none of them took to Flash. Flex is their take on how to have their cake and eat it too. It's another XML-based user interface scripting language but seems to have a lot more going on inside, especially with respect to data binding and client-server communication.

Here's a good intro to it: Building Rich Internet Applications with Macromedia Flex: A Flash Perspective.

I've been browsing the docs and playing with the samples. It was easy enough to set up inside Eclipse; I just created a new project, created a content folder, and expanded the flex.war into the content folder; this gives a web.xml, and the necessary libraries and such. Next, I used Geoff's Jetty Launcher to serve up the context folder and could start creating the .mxml files. Flex uses servlet filters to converts .mxml into .swf (Flash movies) in much the same way that .jsp files are converted into compiled Java classes.

Running this on my laptop (Dell Inspiron 8200, 512mb ram, Pentium 4 2gz) generally worked well; yet many key presses had a noticeable (though minute) delay ... but at the same time, there was also a good amount of fading, zooming, sliding images. It's as if user-input in Flash is given lower priority. Anyway, it was all still quite impressive and I expect to do more experimentation.

The documentation I've read so far was very good. Rich hypertext and PDF and lots of detail and examples. If I can get my head around the data binding and communication to the server, I could probably put stuff together right now. The default skin is clean and simple. The default components do a better, easier job of creating simple, clean interfaces than Swing or AWT (though the XUL variants there probably help). Again, it isn't just Flash and ActionScript and XML ... the data binding was given significant thought (I'll be able to tell if that thought was worthwhile at some point soon).

My initial reservations:

  • All your client-side logic is written in ActionScript (really, ECMAScript). Unit testing this is going to be at least as much of a challenge as unit testing Tapestry pages.
  • There's some form of debugger for ActionScript, but it doesn't look integrated ... it looks like it might be command-line oriented.
  • Applications are ultimately monolithic; you can break your .mxml files into smaller pieces, and create components as well (a clever use of XML namespaces), but there's just the one application object. How long is the initial creation of the .swf file for complex apps? How much of that .swf must be downloaded before the user sees the initial page? How will teams of developers work together?

So why is the Tapestry guy interested in this stuff? Because HTML is, ultimately, a dead end. Tapestry squeezes the most out of HTML that can be done, but I firmly believe that in three to five years, some form of rich client will supplant HTML for the zero-delivery cost web applications that are currently created using Tapestry, JSP, ASP or whatnot. I predict that a lot of stuff now down exclusively with HTML will be done using a mix of HTML and Flex (or whatever client-side technology emerges, should Flex fail). This could be good news for Tapestry ... the sites I envision dominating the market will consist of "boutique" HTML (HTML created by non-Java developers) and Tapestry shines at integrating that kind of HTML into a dynamic application. The HTML parts of applications will be much more focused on readable documentation (news sites, some form of community sites, blogs and the like) where the ability to print and book mark are important. The kind of applications currently shoe-horned into the HTML world (help desks, all kinds of corporate infrastructure, CRUD applications) will be easier and better using a rich-client alternative.

At TSS, people were dismissive because of licensing costs ($25K per server, give or take). Well, licensing costs come down (think WebObjects, which went from $50,000 to $750). And software licensing is the smallest piece of the development cost compared to developer time and hardware.

More of concern is the single-vendor aspect. This is anathema in the Java world ... and there's the looming possibility of Microsoft buying Macromedia and killing Java support within it. I don't know what the solution to this is ... perhaps Macromedia needs to open-source Flex with a mixed GPL/proprietary license like Sleepycat's ... for-profit users pay Macromedia, non-profit don't. Alternately, seed flexible APIs into the product to ensure that third-parties will be able to provide Java support regardless of ownership of Macromedia and Flex.

In any case, the concept is exciting, regardless of which vendor finally makes it all work. Factoring out the presentation layer from web-deployed applications would be a great thing in differentiating J2EE from .Net. A stateless server-side (mated to a richly stateful client-side) means that simple, efficient solutions (based on HiveMind, Spring, and Hibernate) will have their power multiplied.

A short break between TSS and Germany

So I'm back from TheServerSide Symposium and have just enough time to catch my breath before heading out to a multi-day engagement in Germany.

I was "in character" even before I arrived in Las Vegas, kibitzing with a group of developers across the aisle from me on the flight in.

My sessions, as well as a "TSS tech talk" video shot went pretty well. The HiveMind presentation still went a bit roughly; I'm beginning to think that, up against the Goliath of Spring, my little David had better differentiate itself quickly ... the distributed configuration (for both data and services) is the key distinguishing feature, and a solution that mixes HiveMind with Spring is a likely winner.

Much more interest in the Tapestry presentation, which is the advanced one convering component creation. Again, this is really an area where Tapestry differentiates itself most strongly from the other similar frameworks (if such things exist). I did a bit more live presentation, which was a chance to show and discuss Spindle and the great Tapestry exception reporting page (and line precise error reporting).

Both sessions filled the small room I was in; I counted about 55 attendees in each session. The Tapestry session might have overflowed that room had it now been up against the very contentious "What's in EJB 3.0?" talk.

I thought the sessions I attended were very good. The keynotes were, alas, ignorable (except for the Flex presentation, which rocked). Most presenters were quite good; I think Rod Johnson did a very good job and was quite gracious towards me personally and towards HiveMind, to the point of quoting my HiveMind presentation during his "J2EE without EJB" session. We also talked frequently between sessions; overall, we respect that our frameworks address different needs and that combining them should be made as painless as possible. Meanwhile, I'm jelous that he's in a position to use his framework in production, something that identifies problems and limitations fast. It really underscores how I was languishing at WebCT; I need to get involved in some real work on a real project and be in the technical architecture driver's seat again; it's been too long.

I talked to so many people over the course of a few days and lost track of it all quickly ... I have to start jotting down notes on business cards. I know I promised copies of the book to Jason Carreira and Kito Mann, anybody else had better send me a reminder! Also, a lot of people are really pushing for Tapestry to support the Portal API somehow, someway.

People have been talking themselves blue over everything that went on and I don't have any additional, deep insights to add. Supposed "thought leaders" (like myself) have (publically and privately) questioned the status quo for quite a while, challenging the usefulness of EJBs, the practicality of separating the layers so profoundly, and identifying the needless complexity as a platform threatending problem (Rod has examples of major banks throwing away $20 million investments in Java and J2EE in favor of .Net). This philosophy has now gone completely mainstream. One has to question the relevance of EJB 3.0 at this time (and more so when it is ready for release). A phrase I came up with while talking to Rod is "Results Not Standards". Tapestry users are getting great results, even though Tapestry is not a standard (though it is compliant with the useful and reasonable parts of the J2EE standard). Likewise, WebWork, Spring, Hibernate (which is trying to become a standard) and so forth.

Tuesday, May 04, 2004

SDL, Testing, and the Scripting Debate

I'm really loving the effort I invested in SDL, it's very clean, very useful stuff. I'm beginning to productize Tapestry test framework and I'm targetting SDL, not XML, as the language for the scripts. Background: for Tapestry 3.0, I developed a "mock unit test" suite, more of an integration suite, where I simulate a servlet container around Tapestry pages and components. There's no HTTP involved, but none of the Tapestry objects know that ... they see the Servlet API and, for Tapestry's needs, it works just like the real thing.

Each script consists of a few definitions, and a series of sequential requests. Each request passes up query parameters, and makes assertions about the result of the request: mostly in terms of asserting text in the output (sometimes in the form of regular expressions).

However, the tests are pretty ugly; because a lot of the assertions are looking for HTML, there's lots of CDATA sections. The execution and parsing code is all twisted together and built on top of JDom. Line-precise error reporting came later, so it can be a challenge to find where, inside a test script, a failure occured. In addition, all the code is inside the junit folder, not part of the Tapestry framework itself, so it can only be used by Tapestry itself.

I'm currently starting to rebuild this support for use by Tapestry and for end-user applications. I'm building a better parser, using SDL as the script language, and building tests for the testing framework itself as I go (Who watches the Watchmen? Who tests the Testers?). Lots of work up front, but will easily pay for itself when we start adding more complicated tests for some of the 3.1 features ... I also expect it to run much faster.

Meanwhile, the debate about replacing XML and SDL in HiveMind with scripting rages on. I don't see the advantage to the scripting approaches ... they're all more verbose than the equivalent SDL. It's more code to do the same thing that you'd normally do by referencing builder factories. It won't document as HiveDoc, it raises many issues about multithreading. It adds unwanted dependencies to the HiveMind core framework. No one has made a compelling argument ... certainly not compelling enough for me to spend any time on that when I have other priorities, and so far, nobody else is checking code into the HiveMind CVS. So ... we have a fairly active HiveMind community but I'm still the only developer ... do I like this, or not?

Monday, May 03, 2004

Goodbye, Digester!

Ah, the evolution of XML parsing in Tapestry. Tapestry is very much driven by validated XML files (for page and component specifications, application specifications, and library specifications). In the earliest days, Tapestry was tied directly to Xerces. Later, it switched over to JAXP. I had reams of code that would walk the DOM tree and construct the specification objects from the XML.

As a nod to efficiency, I switched over in 3.0 to use Digester, but that's caused a lot of grief in its own right. It seems like the version Tapestry uses was always in conflict with whatever version was in use by the servlet container, especially Tomcat. That caused a lot of grief.

Meanwhile, Digester drags along some of its own dependencies, jakarta-collections and jakarta-beanutils. More JAR hell, keeping all those JARs and versions straight.

No more; I replaced Digester with an ad-hoc parser derived from (and sharing code with) the HiveMind module deployment descriptor parser. It uses a stack to track the objects being constructed (that's borrowed from Digester), but uses a simple case statement and some coding discipline, to deal with recognizing new elements and processing them. I haven't done any timings, but comparing this code to the Digester code leads me to think that this will have a substantial edge ... which will be even more important once Tapestry supports reloading of page templates and specifications. In addition, inside the monolithic SpecificationParser class, it's a lot clearer what's going on. The old code had to create some number (usually three, sometimes six) Digester rule objects for each Digester pattern (patterns are matched against elements on Digester's stack to determine which rules fire). The new code is almost entirely just private methods: beginState() methods that decide what state to enter based on the current element, enterState() methods that create new specification objects, push them onto the stack, and change to a new parser state, and endState() methods invoked when a close tag is found, to finalize created objects and pop them off the stack, and return the parser state to its earlier value.

Next up; the JDom-based parser for the Tapestry mock unit test suite. First, I want to use SDL, not XML, for these scripts. Second, I want them to run much, much faster and I suspect that a lot of time is being spent in JDom. Third, I want thrown assertion exceptions to have line-precise error reporting.

And fourth ... part of Tapestry 3.1 will be to productize this approach to testing Tapestry applications.

I'm the Seven of Clubs

On the just published Who's Who in Enterprise Java List (by The Middleware Company), I'm in the Clubs ("Pot Pourii") category, as the Seven of Clubs. If they do this again, I'd love to be recognized in the Hearts ("Contribution") category, along with Gavin King, Rod Johnson, Craig McClanahan and many others.

It's interesting just how many names on the list I don't recognize!

Someday, I'll have to find another picture of myself that I like ... this one was taken in 1999 atop Mt. Haleakala, Maui, Hawaii.

Sunday, May 02, 2004

Introduction to Jakarta Tapestry

And interesting link from Object Computing, Inc.: Introduction to Jakarta Tapestry.

The author, Rob Smith, is very positive on Tapestry ... he find's it fun! That should be the fifth goal of Tapestry (after simplicity, efficiency, consistency and feedback).

Thursday, April 29, 2004

Amazon.com reviews of Tapestry In Action

The on-line reviews of Tapestry in Action at Amazon.com are really quite nice; very positive but also fair. As I've stated before, everyone wants something different out of the book ... for example, should there be more of a comparison to other frameworks? I think not ... the book was already too big, and there's books on that exact subject already.

I gave away many copies of the book this weekend at the No Fluff Just Stuff conference ... I hope a few of those people (you listing Bruce and David?) might have a chance to post a review as well.

Starting on Tapestry 3.1

I've been putting this off ...and I have many other things I could/should be doing. But before it goes any further, I need to move my refactorings of Tapestry out of the branch and into the head. Most of the refactorings concern classes that were moved from Tapestry into HiveMind. It's going to be a mess to put humpty dumpty back together again at this point.

Meanwhile I've very happy with how the Simple Data Language has turned out. I've been converting documentation and examples. HiveMind will support both formats indefinately. The debate still rages, though, and its boiled down to: declarative vs. procedural. I prefer the former, and I'm waiting for folks like Harish to come up with some form of design to support the latter. To me, the scriping/procedural approach looks harder to read. The SDL format is, I think, quite natural.

Finally, on the iTunes/iPod front I continue to be quite happy. The new "party mix" mode seems to work quite well, and I love the way iTunes merges songs together.

Monday, April 26, 2004

Let's boil the ocean: Simple Data Language

I'm having some fun today thinking about how to get the XML out of HiveMind.

I've long defended the use of XML inside Tapestry (and HiveMind), because it was a convienent, standard way to store hierarchical data. But it is hard to type, hard to read, hard to edit and has some challenges to parse. So I'm thinking about other options.

So ... I still want elements and attributes and nesting, though I don't actually care about nested character data. Nested character data is for documents, not hierarchical data files (despite the fact that Sun's DTDs never use attributes, just character data).

What I have so far (a couple of hours hacking around) is something small and simple. An element is a name. It may be followed by a list of attributes inside parens. An element terminates with a semicolon, or uses curly braces to denote nested elements. Attribute values don't have to be quoted if they look like identifiers, or are numeric literals. Looks something like:

module (id=foo.bar.baz version="1.0.0")
{
  service-point (id=Startup interface=java.lang.Runnable)
  {
    create-object (class=foo.bar.baz.StartupImpl);
  }
}

Of course, use of whitespace is totally at your discretion. For comparison, the equivalent XML document:

<?xml version="1.0">
<module id="foo.bar.baz" version="1.0.0">
  <service-point id="Startup" interface="java.lang.Runnable">
    <create-object class="foo.bar.baz.StartupImpl"/>
  </service-point>
</module>

This is a chance for me to look at JavaCC, a common tool for writing language recognizers and parsers. Good experience in and of itself.

On the other hand, it may be smarter to follow others and simply implement the similarily themed YAML -- YAML Aint Markup Language. When I gave a HiveMind presentation a few month's back at a local Java user's group, I was asked about YAML then, and had a vague understanding of it. YAML has a few more features, better mimicing most (if not all) of XML.

I think the YAML version would be:

--- #YAML:1.0
module:
  id:          foo.bar.baz
  version: 1.0.0
  - service-point:
      id:                Startup
      interface:     java.lang.Runnable
      - create-object:
         class:              foo.bar.baz.StartupImpl 

For either of these two formats, it would be straight-forward to create a filter that produces equivalent XML.

What a week!

So, on short notice, I traveled down to North Carolina to do two days of Tapestry training and mentoring for RoleModel Software. This was a really great experience for me ... RoleModel is a very dynamic group. When they like something, they really let you know. RoleModel is headed up by Ken Auer, an early, vocal proponent of XP (having writing at least one book on the subject). RoleModel is all virtual, it's Ken and a bunch of sub-contractors ... but these guys are pretty darn sharp. In addition, a couple of the junior members are apprentices ... one is still in high school. I've been dubious about pair programming, but it was interesting to see it in action. Their layout is one computer per pair, but with duplicated monitors, mice and keyboards. Anyway, the whole arrangement really resonated with me when I later listened to Dave Thomas' session at NoFluffJustStuff, because it is wrong to treat people at radically different levels of experience identically. Dave identified five levels of experience. At RoleModel, you could see this in action, as the apprentices would work with more experienced folk a level or two above them on the ladder.

I even tried my hand, helping Ken work out how to use the Tapestry Tree component. He was doing a lot of typing, I was doing research and writing down diagrams to understand how the Tree's data model works. Even with two deeply experienced coders, it was working surprisingly well (but we only had an hour to try this). It's important to keep an open mind.

Back from North Carolina Thursday night, on Friday morning I picked Erik Hatcher up at Logan airport and we hooked up with a bunch of other folks for the Boston NoFluffJustStuff event. We were largely scheduled opposite each other so I didn't see him present at all. I did attend David Geary's sessions on Java Server Faces. Good, clear presentation, ambitious if awkward technology. I did learn that at least some folks on the JSF committee are aware of Tapestry ... and I promised him that I'd be raising the bar ever higher. I also gave him a copy of the book (he's going to send me a copy of Core JSF when it is published).

I also attended a session on Groovy. Groovy is a mix of Java, Python and Ruby. It's a scripting language ... but it compiles directly into Java bytecode. Types are optional. It has closures (like Ruby). It adds methods to existing JDK classes like String and Collection. You can completely mix and match Java code and Groovy code. Richard did a great job of describing the language (and even identifying its faults), though the consensus was that he should have fired up a window and just typed the examples live, rather than use slides. The fact that Groovy is in the Java Community Process is odd ... since it is so compatible with Java, there doesn't seem to be a need. Even so, once it stabilized (and if it doesn't go into kitchen-sink hell), I can actually see using it for real code inside Tapestry and HiveMind. I did have a few ideas, and Richard encouraged me to join the mailing lists.

Those were the only technical sessions I attended; however Bruce Tate's session on simpler, faster, better Java was fun. It fits in with my own philosophy (and I'd like to see Tapestry and/or HiveMind as another example, beside Spring, WebWork and Hibernate). This was a continuing (and occasionally divisive) theme all weekend ... J2EE as the enemy not the solution. My philosophy is obvious on this blog:

  • Use only what you understand / cherry pick what's necessary
  • Use simpler solutions, don't buy into the whole stack
  • J2EE APIs are just starting points; don't build directly on the metal ... add a layer between

The other great, non-technical session I attended was Dave Thomas's session "Herding Racehorses and Racing Sheep". He's a great, entertaining, dynamic speaker but also well researched. The session was any number of things; what's wrong with our industry, how to cope with outsourcing, how to advance in your career properly. Some of it tied back to my earlier experience with Ken Auer, since his team is doing at lot of what Dave was preaching.

I did three sessions, 90 minutes each, all on Sunday. During the Tapestry intro ("Building Web Forms With Tapestry") Erik was there to help field questions. I also gave away a copy of the book, which went over quite well. It was pretty lively and, based on the session evaluations, quite well received. I do want to try more of Erik's approach, whereby I develop parts of the application live and rely on pre-written slides less. First I have to figure out my problem's with Jay's projection monitors (currently, I can get it to work by extending my desktop onto it ... if I'm facing the audience, I can't see what I'm typing). I neglected to count attendance, but the room was pretty full ... maybe thirty people total.

The HiveMind session was more sparsely attended but equally lively. I think everyone in the audience had a specific axe to grind but saw how HiveMind could help them. Again, maybe a little more live, or a more realistic example, would be good.

The final session of the day was the Creating Components session ... fewer people than earlier in the day (fifteen or so ... I have to remember to count them). Complicated stuff, but people were digging the concepts. Again, live would be better ... in fact, people were very impressed with Spindle, which I used in just the last few minutes. I kept finding new features in it, while I was demoing it!

I am concerned that my sessions ran too long ... right up to the ninety minute mark. That means I'll run over at The Server Side Symposium. I think I've been so concerned about running short that I haven't accounted sufficiently for questions from the audience.

Sunday, April 18, 2004

Tapestry 3.0 Final

The final release of Tapestry 3.0 is now available. Real announcements go out tomorrow (giving the Apache mirrors time to synchronize).

Got a lot of very, very tough work planned for 3.1. Time to roll up those sleeves!

Friday, April 16, 2004

Change Proposals on the HiveMind Wiki

HiveMind, for its entire history (nearly a year now), has been an ongoing experiment. It was a chance to start a project, fresh, in the Jakarta Commons (though that's not where it ended up). It was an experiment in using Maven as a build tool. It was an experiment in test driven development (give or take), with the goal to keep code coverage over 90% (it's at about 94% right now). I've also been pushing myself to keep the documentation up-to date with every change.

But the big experiment was to try and build a new community (overalapping Tapestry's community, of course) around it. That's been a bit shakey, largely because HiveMind was up, then down for a long time, then up, then frozen, and is only in the last week that the home page and all the infrastructure is in its final location, fully operational, and ready to work.

What's exciting now is that we're using the Wiki to Design In Full View. You can see this on the HiveMind Wiki, on the ChangeProposals page.

What do I mean by "Design In Full View"? It means that we are designing new aspects of the framework on the Wiki. Not just me, but others. And it's not "Design By Committee", we are having real discussions about approaches, requirements, relative merits, costs and benefits and so forth. The end result will be a living document in the Wiki that can be referenced, or used as the basis for final documentation.

We'll see where this heads. I'm confident that we have enough smart people on the team now, and more waiting in the wings, that we'll be accomplishing some insanely great things with HiveMind.

Thursday, April 15, 2004

New England Software Symposium

So after missing a couple of speaking engagements, I'm back on track for the New England Software Symposium. Checking the agenda I can see I'm on a couple of expert panels and giving three sessions:

  • A souped-up version of my "Basic Components" presentation, now titled "Creating Powerful Web Forms With Tapestry".
  • Creating Tapestry Components
  • Introduction To HiveMind (since my Tapestry + Hibernate presentation isn't ready yet).

The best part, for me, is that I can drive to this event (it's less than an hour from my house) and sleep in my own bed.

Wednesday, April 14, 2004

Vote to release Tapestry 3.0

Just submitted a vote to release Tapestry 3.0 FINAL. Quite a few people have been demanding a release (yes, that means you, Erik) and I think Tapestry is in excellent shape to proceed forward. Not quite all my goals for 3.0 have been reached ... there's still some gaps in the documentation, and the test suite isn't quite at the level of code coverage I'd like (it stands at 81.3% overall, and should be in the 85 - 90% range). Regardless, Tapestry 3.0 is stable and more than ready for production.

The vote will run into Saturday, with an announcement following on Monday. There's a chance that one of the committers will decide that a bug is too important to wait, and will veto the release.

The team in general, and myself in particular, have really big plans for release 3.1. Everyone's hot button item is modularity ... in 3.0, all your page specs go in WEB-INF and all your page templates go in WEB-INF (for some people) or in the root folder (for me). That causes two problems. First, those directories can get crowded when you have dozens or hundreds of pages (especially when you add in messages files and other assets to the mix). Secondly, J2EE prefers that you split your application across folders, because it (effectively) applies declarative security at the folder level. Therefore, you want to be able to put all your administrative pages, with access restricted to an admin group, into an admin folder.

This will require a bit of a rethink on how Tapestry generates and interprets URLs, and likely, some significant changes to the IEngineService interface.

The other significant change relates to component parameters; I would like to deprecate directions "in", "form" and "custom" and always use (the equivalent of) direction "auto" ... but add in hints that determine how long values can be cached. That is, once you evaluate an OGNL expression, is the value valid just while the component renders, until the page finishes rendering, or until the end of the request? I have a rough mental outline of how this all will work, and it's going to be a lot of fun with Javassist. Components will have to know when they start and finish rendering, whether parameters are bound, whether they are bound to invariants or to expressions and so forth.

That, combined with Drew's upcoming improvements to OGNL should be very exciting. Mind Bridge has profiled Tapestry applications and they can spend around 50% of their time evaluating OGNL expressions. The majority of those OGNL expressions are simple property references. They're working on a plan to make use of Javassist to replace reflection with direct method invocations where appropriate, and Drew's seen about a 10x improvement.

This leads me to the following prediction: In Tapestry 3.1, Tapestry applications will be significantly faster that servlet, JSP, Struts or JSF applications with equivalent functionality. Of course, it's pretty much impossible to find applications with "equivalent functionality", but none the less. By improving the efficient of OGNL, and making use of the optimizations possible because of the Tapestry component object model, I believe the overall processing (especially with respect to Java reflection) will decrease noticeably.

Now if I only had my own personal performance lab ...

Tuesday, April 13, 2004

Two new toys

This is way off topic, but I couldn't resist.

Toy #1

Bought myself a 15 gig iPod. Basically, this is me throwing in the towel on even trying to do work on my laptop while I travel (and I have a lot of travel coming up in May). Since I find the tedium of air travel to be agonizing, this is my hi-tech pacifier. And I'm already in love with it. I've already moved about 1.5 gig of MP3s onto it (all legit, by the way) and it works like a champ. Eventually I'll compare it's native AAC format.

It came in a perfect black cube (something of a Steve Jobs trademark) and every aspect of it so far has been done right ... except I can't get it to charge off my laptop's firewire port. Another plus: the visualizer for iTunes (the desktop program) is a licensed version of G-Force. I guess it's time to uninstall MusicMatch.

Amazingly, I ordered this from Apple at the set-price ($299) late in the afternoon on Sunday and it arrived here this morning (Tuesday!) and it has been custom engraved. And it was shipped FedEx from Shanghai! Oh, if you find an iPod at some airport engraved with "Howard Lewis Ship howardlewisship.com" ... that's mine. Give me a call so I can get it back!

Apple knows how to do these things right. Easy to use, and I keep finding new features. Sound quality with my Boise noise-canceling headphones is terrific. I'm ready to travel anywhere.

Toy #2

This one's virtual ... it's the Google AdSense banner over on the right side of this page. I rather doubt I'll drive enough traffic to earn more than some spare change but to me it's fascinating how it scans the content of the page (presumably from Google's cache) and produces pretty on-target ads. I'm slightly annoyed by the Struts and JSF training ads I've seen on a few of the archive pages, but so be it.

Thursday, April 08, 2004

TheServerSide Java Symposium Schedule

I was just looking at the TSS Symposium schedule. I'm up twice on Thursday, May 6th: HiveMind from 11:30 to 12:45, and Creating Tapestry Components from 3:30 to 5:00.

That leaves the question of which other sessions to attend! It will be a chance to learn more about AOP, and I want to see Gavin King's presentation on Mobile Data. It will also be a chance to learn a bit more about Porlets OR JBoss Cache OR J2EE without EJB (all scheduled against each other, alas).

The dinner keynote by JBoss, on "Professional Open Source" will be interesting. Will they be able to come up with a useful definition of this term?

I'm also interested in the Macromedia presentation on rich clients. At some point, (two years? five?) HTML applications will be marginalized, and some form of rich client within the web browser will take over. You won't do so much HTML, but you'll still need HiveMind to implement the server side of your application.

Wednesday, April 07, 2004

Many pots coming to a boil

So, HiveMind after months and months of being left out in the cold, is finally turning into a real project again. It's a top-level Jakarta project, all of its infrastructure is in place, and the home page is now working (without all the broken links). I've also moved the model attribute out of the <service-point> descriptor element and into the <invoke-factory> and <create-instance> elements (which makes a lot more sense).

Tomorrow will be the next Tapestry release, 3.0-rc-3 (that's "release candidate #3"). I'm really expecting this to be the final release candidate ... but you can never tell.

Time to shift my attentions (and growing energies) back to important things: preparing for The Server Side Symposium and NoFluffJustStuff (big revisions necessary for my presentations --- to reduce the amount of fluff!) and otherwise preparing for upcoming public and private sessions about Tapestry.

Tuesday, April 06, 2004

HiveMind up and humming!

We now have an empty Wiki, the full set of mailing lists, the new home page, and the Jira project. Time to get back to work on HiveMind.

Still need all the developers voted in to the project to get their CLAs to Apache before CVS access rights can be extended. Knut? Prashant? You guys listening?

Monday, April 05, 2004

HiveMind Home Page

The HiveMind home page is now up, in its proper location: http://jakarta.apache.org/hivemind/.

This is about half the infrastructure for HiveMind. The Jakarta Jira project has been created, and the CVS repository is in place. All that's left is the wiki and the mailing lists.

Friday, April 02, 2004

TheServerSide.com - Review of Tapestry In Action

The Server Side has just posted a short Review of Tapestry In Action. It is interesting (and frustrating) that every reader wants something completely different from the book. This review is reasonably accurate (through I wish Kris, the author, had used a spell checker). He faults the book on the one hand for being verbose ... then praises it on the other for being detailed. His summation is to read the first two chapters to decide if you like Tapestry, then keep the rest handy for when you implement an application. Not bad advice.

Thursday, April 01, 2004

Berkeley DB Java Edition

My pal Greg work for Sleepycat Software, who just released Berkeley DB Java Edition. Berkeley DB is some cool technology; quite a few popular sites use the C version of Berkeley DB in their presentation layer (in fact, Berkeley DB is used in a huge number of places, including Subversion), as a cache against raw data stored in Oracle or a backend system. It's anything but a relational database ... its a high-performance, transactional, embedded database. It's a way of storing large amounts of binary data, which just might happen to be serialized Java objects.

The Java Edition adds a Java-friendly API ... Berkeley DB databases end up looking like Maps and other Java collections. Or you can get more down and dirty and control exactly how objects are serialized into, and de-serialized out of, Berkeley DB entries.

There's a lot of talk about J2EE without the complexity of J2EE, thus things like Spring and HiveMind ... the sacred cow of EJBs (both session and entity) fall away when you find a different, better way to organize and componentize your code. Most of us still assume that the only way to store our data is in a relational database, and then get involved in an Entity EJB vs. Hibernate vs. JDO vs. TopLink battle ... when, in many cases, all we want is a simple way to store and retrieve Java objects. The relational database becomes an assumption, somehow evading questions of cost (of licensing, of adminstration, of maintenance, of hardware), use cases, requirements ... it's another sacred cow waiting to be slain. If you are creating a typical application, where the application itself is the only use of the database, then an embedded database may be the better, faster, more efficient, cheaper, zero-administration approach.

"Tapestry In Action" in bookstores

Just called over to the local Barnes & Nobel and they claim they have Tapestry in Action in stock; time for a little field trip (and I'm bringing a camera). Times like this really make me feel the need for a digital camera.

I also understand that a review of the book will be appearing soon on TheServerSide.

Meanwhile, Tapestry 3.0-rc-2 is ready (a formal announcement will wait for 24 hours, for the many Apache distribution mirrors to pick up the new distro files). In addition, I'm waiting for the HiveMind infrastructure to be set up: for some reason, this is taking a while.

I've continued to play around with Hibernate; I really want to get some good patterns and best practices together, both for presentations at NoFluffJustStuff, and as part of my on-site presentations. I don't know that I'll have the Hibernate stuff together in time for the New England Software Symposium, however. I'm having trouble getting started and staying focused (not surprising for someone who had his kidney removed just 16 days ago).

Update: Barnes and Noble had a copy in stock (but misfiled with the HTML books, so I moved it to the Java section myself). Borders didn't have a copy yet, they were expecting it in the next day or so. Still, it was a fun rush to see the book in a book store! In addition, the HiveMind infrastructure tasks are finally in progress. Should have a new and better HiveMind in place today or tomorrow!

Sunday, March 21, 2004

Back and recovering

I'm back from the hospital and starting to recover. It'll be a couple of weeks before I'm anywhere near full strength. The operation executed perfectly; no complications, nor problems expected down the road.

Monday, March 15, 2004

Back to full RSS feed

Now that I'm hosting this blog at my domain, I've switched back to the full RSS feed. JavaBlogs.com no longer seems to have an issue ... something about the mix of JavaBlogs.com and BlogSpot was toxic. I suspect that somewhere between them was a mis-configured web server or firewall. Hosting myself will also give me better access to statistics on page viewing.

Moving off of javatapestry.blogspot.com

I've got my own domain, why don't I use it?

This blog is now housed at http://howardlewisship.com/blog/.

Sunday, March 14, 2004

Back to short site feed

JavaBlogs.com once more can't process this blog's RSS site feed. I'm pretty sure its a problem on their side and the fingers are a-pointing. Using the short site feed seems to fix things.

This, of course, causes another problem: the formatting of the site is geared towards a fairly large display using Internet Explorer. Smaller screens and other browsers (such as Safari) are having problems. Given everything else going on right now, I won't have a chance to address that for a bit.

Saturday, March 13, 2004

Tapestry In Action: on my kitchen table

It's strange how things can coincide. Right on top of the HiveMind announcement, I now have on my kitchen table twenty-four copies of Tapestry in Action. That's copies for me, for parents, for the Quincy library, for friends ... and a bunch held back for other purposes. Suzanne and I are just giddy!

My big concern was the readability of some of the larger screen captures from later in the book ... turns out, they look terrific. The book reads great, and even though a couple of juicy chapters are available online, to get the best stuff, you're going to have to pick up a copy! Should be in book stores and available online in about two weeks.

In other news ... I have a sudden, serious medical condition. I don't want to go into details or be melodramatic; it's entirely treatable and I have an excellent prognosis: we won't be testing how well Tapestry can survive without Howard at this time. It does mean I'll be largely off-line for at least a couple of weeks, starting next Wednesday. It also means I'll be missing my speaking engagements in New York and Wisconsin.

My other appearances, including Boston, Virginia, Colorado and Las Vegas, should not be affected.

Friday, March 12, 2004

HiveMind is in

From: Geir Magnusson Jr 
Subject: [VOTE RESULT] HiveMind as Jakarta sub-project
Date: Fri, 12 Mar 2004 15:03:44 -0500
To: Jakarta General List 

The vote has been running a week now (actually longer), the count has 
been unanimously supportive (there were two +0 votes, all the rest were 
+1), so HiveMind is now a Jakarta sub-project.

Congratulations to Howard and the rest of the HiveMind community.

-- 
Geir Magnusson Jr                                   203-247-1713(m)
geir@4quarters.com 

Pretty much says it all. We have that, we have the book (expected on my doorstop shortly), life is pretty good!

Wednesday, March 10, 2004

Sample Chapters: Tapestry in Action

Manning has published two sample chapters for Tapestry in Action.

Chapter 02 introduces the basics of Tapestry, and shows how to use DirectLink, Conditional, Foreach and Image components.

Chapter 05 skips ahead a bit and discusses Tapestry input validation subsystem, which is very powerful. Alas, the screenshots were done a couple of months ago, and show the older, uglier version of the DatePicker component.

I think it was Geoff who suggested chapter 05, something along the lines of "let's blow the tops of their heads off!"

Tuesday, March 09, 2004

Rolling toward Tapestry 3.0

I've been spending the day working on Tapestry 3.0 ... fixing as many bugs as possible, updating documentation, and so forth. I've also been categorizing which fixes and enhancements will go into 3.1. A bit more of this, and I'll be ready to call a vote to release 3.0-rc-1. I'd really like to have 3.0 in at least RC (release canddiate) stage before the book shows up in stores.

Along the way, I made a very useful enhancements to the DatePicker component. It now uses a clickable button to show and hide the pop-up calendar (and the button can be customized to your app's look and feel). This is a big improvement over the old look, which used a button labeled with a "V". That was a bit tacky, the new look is pretty much ideal.

Friday, March 05, 2004

Once more, the importance of error reporting

A major feature of Tapestry that has been ported into HiveMind is line precise error reporting. When errors occur, Tapestry and HiveMind will isolate the problem down to a particular line or a particular file ... not just when parsing an HTML template or a specification file (or a HiveMind module descriptor), but later, at runtime. Line precise error reporting is a major part of an overall attitude, a discipline, about reporting errors. It takes great effort to consistently catch and report errors, and to maintain that location information. Its very important however, because without it, your user's frustration levels will go through the roof.

I know I'm going to alienate a couple of people here so I apologize in advance. I may be a whiz in my own world, but at the moment, I'm a trembling newbie in the Hibernate world. So I'm putting together a couple of simple mapping files, and making use of the Ant schemaexport task. Now, I've done something wrong, and at this time, I don't yet know what. But see what I have to go on:

bash-2.05b$ ant export
Buildfile: build.xml

compile:
     [copy] Copying 1 file to C:\workspace\ProjectRegistry\target\classes

export:

BUILD FAILED
file:c:/workspace/ProjectRegistry/build.xml:44: Schema text failed: net.sf.hibernate.MappingException: invalid mapping

Total time: 1 second

See what I mean? Not enough effort has been expended on a) describing the actual problem (which mapping? what's actually wrong with it? how do I fix it?) and b) telling me what file is broken (never mind the line!).

This is one important aspect of HiveMind: when using HiveMind's XML support, you get much checking and much reporting for free. A hypothetical HiveMind message for this might be:

Unable to process attribute cascade (of element class/set, at file://..../Project.xbm.xml, line 27, column 35): 'deleted' is not a recognized enumerated value.

Again, I don't want this to be considered a dig at Hibernate. The core competency of Hibernate and its crew is to marshall data between Java objects and databases, something they have years and years of experience at. The core competency of HiveMind is to organize services and parse XML into objects and report errors while doing it. It might be nice for Hibernate (as well as virtually every other framework, open-source or closed) to prioritize a little bit of effort into these issues. I also look forward to a day when more frameworks leverage HiveMind for these purposes, offloading this XML parsing and error reporting burden onto it.

Thursday, March 04, 2004

HiveMind downloads are available again

I've restored the pre-built distributions of HiveMind available at the temporary download location. However, those only go as far as alpha-3, and the current code (provisionally alpha-4, but likely to become beta-1) is only available via CVS and has many cool features not available in the earlier versions. Get Maven and build it yourself.

Back online at JavaBlogs

After a bit of experimentation, I was finally able to get this blog back up on Java Blogs. I changed my RSS preferences to "short" (just the first paragraph of each post, no markup) and that makes Java Blogs happy. Previously, the RSS included the full text of each posting, with markup.

Upcoming New York Trip

I'll be giving a talk about HiveMind at a one-day seminar in New York City on April 3rd: Developing Web Apps using Open Source Tools. In fact, I'll be presenting on HiveMind, not Tapestry, to sort of celebrate the fact that HiveMind is now back on track. It'll be a chance to mix it up with some folks like Rod Johnson, Ted Husted, and the like.

Starting in with Hibernate

At long last, I'm getting a chance to really dig into Hibernate. I took a cursory look at it about a year ago, but realized I didn't have enough time to design and build a new application (for the end of the Tapestry book) and stay on schedule. Now that I've promised Jay Zimmerman a session on using Tapestry and Hibernate, I need to actually learn the technology.

So far, I'm liking what I'm seeing. I'm also, in the back of my mind, thinking in terms of Hibernate/HiveMind integration (Hivernate?). I could peek at what the Spring folks have done, but that would be cheating. Likewise, I'm not looking at what others have done in terms of Tapestry / Hibernate integration either, at least until I take my first pass at it.

It's clear that Gavin and team have hit the same issues and requirements I've encountered over the last 10 (!) years. It's kind of fun ... I'm seeing the echos of their design decisions over the last few years, the rough edges they've smoothed out by extending their DTDs and APIs. Someone on the outside of Tapestry looking in would see the same thing.

Monday, March 01, 2004

HiveMind Proposal Redux

Just posted to the Jakarta General mailing list, the new HiveMind proposal.

Sunday, February 29, 2004

Automatic Proxy creation in Spring

Found an article on Automatic Proxy creation in Spring. Turns out that I'm not the only one troubled by the ease of gaining access to the "unproxied" versions of beans. Spring apparently has some "magic beans names" that get hooked into the object creation cycle, which allows all beans within an context to be proxied.

Of course, I still prefer HiveMind's approach: namespaces rather than magic names, and service creation and interception integrated together, with no cracks showing through.

HiveMind: element

I'm having one of those days ... as soon as I stray away from my computer, it's a big disaster. Messed up with the caulking gun and made a mess. Can't find the drill bits for my electric drill, so I can't mount the smoke alarm that's been sitting, for months, on the dining room table. And when I play on the XBox, I have two left feet. So back to the computer we go.

A common complaint about HiveMind, which cropped up again on The Server Side, was how much people hate <rules>. Yes, it's a simple, stack based language sitting in the middle of the document ... what's your problem? No one ever says "that's clever" ... it is usually something like stunned disbelief or just a total lack of comprehension. Since XML conversion is one of the tenets of HiveMind, it really should be simple and easy, so ...

I've now added (and integrated, and tested) an alternative: <conversion>. It accomplishes the same thing, but is both more limited, and more understandable and comprehensable ... especially in the most typical case, where you are defining largely flat data for a configuration point (or as parameters to a factory service). Even more so, since the default when using <conversion> is to use the smart translator.

In other news ... I'm conferring with Prashant tomorrow to see about re-submitting the HiveMind proposal to the Jakarta PMC. At this time, Christian Essl will have to be removed from the initial committers list ... he hasn't responded to any of my e-mails. That's a shame, he's provided some great ideas including the use of the nested proxies to handle the thread-safe instantiation of services without the need for synchronzing individual methods. Hopefully he'll return to the fold once we get started.

HiveMind: smart translator

Just added a new, nifty thing to HiveMind ... the smart translator. In HiveMind, a translator is an object that plugs into an XML conversion rule. It can interpret an XML attribute and convert it to a different type ... for example, to a boolean, or an int.

The new smart translator does the conversion based on the type of property the result will be assigned to. I got the idea from Spring, which does this kind of conversion already. What's the end result? Well, usage of the central hivemind.BuilderFactory is simplified, because now there's just a <set> element, the old type-specific elements (<set-boolean>, <set-int> and <set-long>) have been removed. Eventually, I would have had to write <set-double>, <set-char>, etc. That no longer necessary.

There's still specialized elements such as <set-service> and <set-configuration> ... those things can't be seamlessly accomplished using the JDK's PropertyEditor class, since they rely on a bunch of information only available inside the HiveMind Registry. Perhaps in the future, I'll be able to make the smart translator even smarter.

That covers the property injection side of things; I need to revisit the constructor injection part. There's still too many elements in place there, because with constructors, there's no property that's getting assigned, so no way to know what the type should be. In fact, I'll revisit the code and make it work backwards from the available constructors to find the correct match. In most cases, finding a match shouldn't be an issue, even if there's some guesswork with some of the constructor parameters.

Meanwhile, I have a bunch of other great ideas to implement, based on the recent discussions on The Server Side.

Saturday, February 28, 2004

java.blogs needs a little work

I read a lot of blogs via the java.blogs aggregator website, and the service has come a long way in terms of reliability in the last few months. Unfortunately, it has decided it can't read my blog any more. I've been furiously posting updates here and nothing shows up there.

The best thing is to bypass java.blogs ... I mostly use it to find blogs of interest that I then record as favorites inside my desktop aggregator: FeedReader.

Friday, February 27, 2004

Cutting down those dependencies

I've been somewhat troubled by the number of real, actual, runtime dependencies in HiveMind. I just put some work in, and managed to remove the dependency on commons-beanutils (and, by extension, commons-collections). I also removed code that invoke commons-lang's StringUtils.isBlank() so that HiveMind should be compatible with commons-lang 1.0. Those wacky commons-lang guys changes the meaning of method StringUtils.isEmpty() and introduced a new method, isBlank(), with the old behavior ... a lot of fuss for such a minor method, so I just re-implemented it as a method on the HiveMind class.

Anyway, my concern is, of course, DLL hell (and it's Java JAR equivalent), where widget A and widget B disagree about which version of widget C they each use. When you're in the business of hooking widgets together, this stuff is pretty critical. Less is more!

Interceptors in HiveMind and Spring

I've been doing more playing with Spring and HiveMind. Like most developers, I'm focusing on what I know and am comfortable with.

I wanted a simple example of using an interceptor. Now, I know Spring has a lot more AOP (Aspect Oriented Programming) goodies inside it, but again, one must start somewhere.

As a starting point, here's the service interface and class:

Adder.java:

package springex;

public interface Adder
{
    public int add(int arg0, int arg1);
}

AdderImpl.java:

package springex.impl;

import springex.Adder;


public class AdderImpl implements Adder
{

    public int add(int arg0, int arg1)
    {
        return arg0 + arg1;
    }

}

In Spring, you create a bean, often refered to as the target, then create a second bean that adds interceptors to the first bean. It ends up looking something like:

springbeans.xml:


<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>	
  <bean id="adderImpl" class="springex.impl.AdderImpl"/>
	
  <bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"/>
			
  <bean id="adder"	class="org.springframework.aop.framework.ProxyFactoryBean">
	
    <property name="proxyInterfaces">
      <value>springex.Adder</value>	
    </property>
			
    <property name="interceptorNames">
      <list>
        <value>debugInterceptor</value>	
      </list>	
    </property>
		
    <property name="target">
      <ref local="adderImpl"/>
    </property>
  </bean>

</beans>

The code for creating the BeanFactory and invoking methods on the bean is pretty simple:

SpringMain.java:

package springex.main;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;

import springex.Adder;

public class SpringMain
{

    public static void main(String[] args)
    {
        Resource r = new FileSystemResource("springbeans.xml");

        BeanFactory factory = new XmlBeanFactory(r);

        Adder a = (Adder) factory.getBean("adder");

        System.out.println("adder = " + a);
        System.out.println("result = " + a.add(4, 7));
    }
}

And when you run this ...

Debug interceptor: count=1 invocation=[Invocation: method=[public java.lang.String java.lang.Object.toString()] args=null] target is of class springex.impl.AdderImpl]
Debug interceptor: next returned
adder = springex.impl.AdderImpl@c8f6f8
Debug interceptor: count=2 invocation=[Invocation: method=[public abstract int springex.Adder.add(int,int)] args=[Ljava.lang.Object;@1b9240e] target is of class springex.impl.AdderImpl]
Debug interceptor: next returned
result = 11

You can see the Debug interceptor catching the invocations of toString() as well as add(). It doesn't do a great job on arguments. With some more work, you could create an adviser for the interceptor that would determine which methods to intercept, and which to leave alone.

Now, to do the equivalent in HiveMind. Because interceptors are the main approach to AOP in HiveMind, their useage is very streamlined:

META-INF/hivemodule.xml:

<?xml version="1.0"?>

<module id="springex" version="1.0.0">

  <service-point id="Adder" interface="springex.Adder">
  	<create-instance class="springex.impl.AdderImpl"/>
  	<interceptor service-id="hivemind.LoggingInterceptor"/>	
  </service-point>

</module>

The <interceptor> element references a interceptor factory service that fabricates an interceptor for the service. The factory is responsible for deciding which methods will be enhanded and how, by providing additional code that is invoked before and/or after the service methods are invoked on the core service implementation. You can have a whole stack of interceptors by adding additional <interceptor> elements.

One of the things I like is that there is no way in HiveMind to directly access the service implementation (the equivalent of the adderImpl bean in Spring). It will always be properly buried beneath proxy objects and interceptor objects.

Next, the main class.

HiveMain.java:

package springex.main;

import org.apache.hivemind.Registry;
import org.apache.hivemind.impl.RegistryBuilder;

import springex.Adder;

public class HiveMain
{

    public static void main(String[] args)
    {
        Registry registry = RegistryBuilder.constructDefaultRegistry();

        Adder a = (Adder) registry.getService("springex.Adder", Adder.class);

        System.out.println("adder = " + a);
        System.out.println("result = " + a.add(4, 7));
    }
}

And the runtime output:

adder = <SingletonProxy for springex.Adder(springex.Adder)>
springex.Adder [DEBUG] BEGIN add(4, 7)
springex.Adder [DEBUG] END add() [11]
result = 11

HiveMind does a careful job of converting method parameters into something readable, even when the parameters are arrays. It also shows the return value for non-void methods, and would log any thrown exceptions. The Log4J logger is springex.Adder. This is based on the service id, not the Java class.

Unless toString() is explicitly part of the service interface, HiveMind objects will implement their own version. Here, the object returned from Registry.getSerivce() is a singleton proxy, an object that handles the just-in-time creation of the core service implementation the first time a service method is invoked (and yes, its efficient and thread-safe). Its toString() implementation provides the service id and the service interface.

Folks, we have a Wiki

Erik Hatcher has spearheaded getting the Jakarta Tapestry Wiki up and running. He nagged. Apache infrastructure delivered. All rejoiced.

Thursday, February 26, 2004

HiveMind CVS is back up

You can now access HiveMind CVS again ... including all my latest changes (such as the change in package name). Follow the directions on the HiveMind home page.

Can HiveMind break its <rules>?

Inside the Server Side Discussion Opinion: Comparing HiveMind to Spring, Keith Donald pointed out a problem ... the <rules> mechanism is a real pain!

<rules> and all that is flexible and powerful, but also intimidatingly complex. In the discussion, I described an idea I expect to pursue: an alternative to <rules> for simpler, flatter data ... leaving <rules> in the background for when you need the industrial strength solution.

Meanwhile, I've been thinking that HiveMind's service models are slighly off. Currently, you define the service model with the <service-point>. However, the need for a non-standard service model (such as threaded or pooled) is really a function of the implementation not the interface. Therefore, I expect to move the model attribute out of <service-point> and into <create-instance> and <invoke-factory>.

HiveMind coming back to life

CVS is still not back up, but I've been able to update the HiveMind home page for the first time in months.

I expect the CVS to be brought back soon, at which point Prashant and I will submit an updated proposal for HiveMind to join the Jakarta project at Apache.

Meanwhile, my frustration with Maven has been growing. I'll probably bite the bullet in convert from Maven to Ant 1.6 + Forrest soon. Perhaps Erik will help?

Monday, February 23, 2004

Comparing HiveMind to Spring

I've started learning a little bit about Spring ... not just to make a comparison, but to look for proper channels for providing interoperability between HiveMind and Spring. I'm just starting through their documentation right now and will record observations as I go.

My intention here is not to bash Spring or start a flame war. I expect this posting to cause a bit of debate, and a chance for others to point out the inaccuracies that are certain to follow below. The final result will likely be a stand alone document, part of the HiveMind documentation. But you have to start somewhere.

Unlike a lot of open source projects, it looks like they have not ignored the documentation issue.

Yes, Tapestry right now gets bashed for bad documentation. That's because the documentation for 2.3 is actually very good, but the framework has jumped to the next release (3.0) and very little of the documentation has been updated. I've been, ahem, busy.

What follows are my observations as I work through the Spring documentation, starting with the Spring Reference.

Already, I'm trying to adjust to this new term, "Dependency Injection". That's Martin Fowler's term for Inversion of Control. To be honest, I think Mr. Fowler's term is a little short ... yes, the way your objects are connected together is a kind of "injection", but the rest of IoC is the Hollywood Principal (don't call us, we'll call you), which from my point of view is largely about lifecycle support ... when do objects get created and configured, how long are they used for, and how do you keep methods from being invoked under incorrect circumstances.

On the other hand, I'm likely to adopt the term collaborator when discussing different services that work together. Yes, it seems obvious once you've read it!

Back to the comparison. HiveMind's Registry seems pretty close to Spring's BeanFactory (or actually, as I realized later in the document, to Spring's ApplicationContext). They are both the ultimate containers, responsible for creating and configuring services and configurations (in HiveMind) and beans (in Spring). So far, as I'm reading, Spring appears to have different containers used in different contexts. By comparison, for services, HiveMind has different service implementation factories ... such as BuilderFactory and EJBProxyFactory (and, of course, you can roll your own).

This is a difference both minor and significant. Minor, because in the end run, you get to have services of different "flavors" ... are they beans or references to EJBs, or something else? Both HiveMind and Spring can define services (or beans). As I dig through the Spring documentation, I'll see just how well having this split works in practice ... for the moment, I think I'm on the right track with HiveMind to make the services heterogeneous within a single "context": the Registry.

The flip side is that Spring's bean factory is less tied to XML than HiveMind. HiveMind is very, very XML centric ... this is due to its configuration aspect, which is all about XML. And HiveMind is using XML in a very XML way, what with the HiveDoc (conversion of HiveMind module descriptors to a human-readable HTML format via XSLT). Spring has a specific implementation of BeanFactory, XmlBeanFactory, that defines the available beans using an XML format, but in Spring, this is pluggable. This is somewhat pluggable in HiveMind as well, since if you can create a ModuleDescriptor (perhaps from a database or somesuch) you can provide it to the RegistryBuilder for incorporation into the HiveMind Registry. But that is not the core intent of HiveMind ... the core intent is to read XML configuration files from META-INF/hivemodule.xml of all visible JAR files.

Spring can define a bean as a singleton or as a prototype. This roughly maps to HiveMind's service models. HiveMind has a richer set of these and uses a bit more runtime magic.

Spring's <bean> and <property> tags are roughly equivalent to the HiveMind BuilderFactory service. It appears that Spring does a bit more work to simplify property assignments ... for example, it does a bit of analysis of the types of properties to be set and automagically converts the string values (from the XML file) to the right type. I know that approach is more easily accepted by folks like Erik Hatcher. Of course, my attitude is that its always best to start strict and gradually ease up than to start loose and try and inject order.

Beyond that, HiveMind's and Spring's approach to IoC type-2 (set dependencies as properties) and type-3 (set dependencies as constructor arguments) are very close. Not a surprise ... only so many ways to skin a cat. However, Spring borrows a bit from PicoContainer, in that it can attempt to autowire collaborators by name or type. For all that, they're own documentation discourages the use of autowiring.

I wasn't sure what to make of Spring's dependency checking. Does it check to see that all properties of a bean get set? What if the bean's service methods look like properties?

So far, as I read the Spring reference, I can already see a point of difference. Spring will instantiate arbitrary beans. HiveMind is organized around interfaces, so when you define a service, you must also provide the interface for that service. The implementation, core service implementation in HiveMind parlance, is secondary, and may not even be provided in the same module. Advanced builder factories may mean that there isn't a particular class ... it may be brewed up at runtime, perhaps as a reference to something else (such as an EJB stateless session bean).

Spring has lifecycle interfaces that beans may implement to know when they are fully initialized, and when they are being disposed. HiveMind has effectively the same thing, plus an additional lifecycle interface that allows poolable services to know when they are returned to the pool. Spring includes a way, inside the XML, to specify a method to invoke (as an alternative to implementing a lifecycle interface) ... this is not a bad idea; I suspect it exists to support instantiating beans you didn't write, and therefore can't make implement the necessary interface.

In HiveMind, you would generally create a simple "shell" service around the collaborating bean to accomplish the same thing. A little more code, perhaps, but generally when you wrap an existing framework (such as Hibernate) as a HiveMind service, you'll define a new interface anyway.

Spring's BeanFactory has a concept of a configurer. The configurer is responsible for post processing the raw input for the BeanFactory (that is, the data parsed from the XML for an XmlBeanFactory). The example usage they give is to read a properties files and do substitutions of Ant-syntax references.

The generality of having multiple (?) configurers is cool, but if that's the only use, it is not as powerful and flexible as HiveMind's symbol sources. Symbol sources fulfill the same role(and even use the same Ant-derived syntax) , but give you a lot of power in setting up a whole list of places that symbol source data can come from at runtime.

Spring's PropertyPlaceholderConfigurer and HiveMind's symbol sources serve the same purpose: that some information needs to be determined at runtime: e-mail addresses, database URLs and so forth.

So far, I'm still confused about the lifecycle of beans relative to the lifecycle of the bean container. Does the bean container instantiate each bean when it starts up or (more likely) on first reference?

One concern I have for Spring with respect to collaborators is chain of creation. If bean A references bean B references bean C, then accessing bean A will result in B and C being created as well. Early HiveMind did the same thing, before I added in alternate service models and the idea of creating a service proxy to control just-in-time service creation.

Further, if C collaborates with A or B, you can get into a reference loop. The Spring bean lifecycle state diagram indicates that beans are created (via default constructor) first, then wired together second. So A, B and C would be created, then B wired to A, C wired to B and possibly A wired to C. Yes, a diagram would be nice here. However, this diagram and the reference to the default constructor doesn't seem to address what happens when using a constructor to inject dependencies on collaborators. It's a bit of a tangled problem, and easy to ignore ... it takes a particular degenerate case to hit a problem, but when that happens in production you are stuck!

Another advantage of the HiveMind approach (using a proxy) relates to co-dependent collaborators when using type-3 IoC. Using Spring or PicoContainer, it may not be possible to accomplish this ... you can't instantiate A by passing B into its constructor when you need an instance of A to pass into B's constructor. Under HiveMind, this is not an issue: A will be constructed with a proxy to B, and B will be constructed with a proxy to A. Order simply doesn't matter.

Ok, so a few of my observations are slightly off; BeanFactory is the bottom layer, and when you add Spring's ApplicationContext, you start to get to something a bit more like HiveMind, where multiple modules can work together.

Spring has, at this context level, I10N support similar to HiveMind's Messages support. It does support different locales simultaneously, whereas in HiveMind, the locale used for all messages is fixed when the Registry is constructed.

Spring's ApplicationContext provides some useful event interfaces; in HiveMind, the same functionality is available in standard services provided in the hivemind module.

Spring has code related to bean manipulation .. accessing named and nested properties. This isn't an issue in HiveMind but will be in Tapestry. Tapestry will continue to use OGNL for these purposes.

Spring works using JavaBeans property editors, so that it can translate property value strings to object values. In HiveMind, you would use translators (on attributes within elements within a schema) to direct how to convert a string to a property value and even do some validation.

Spring AOP appears to be something of a super-set of Tapestry's AOP (service interceptors). Both make use of interceptor proxies. In AOP terms, both weave around advice for object methods by creating a proxy at runtime. Spring can proxy classes whereas HiveMind can only proxy interfaces. It's generally accepted that programming to interfaces, rather than classes, it a better approach. In this area, Spring is giving developers a choice, whereas HiveMind is leading developers by the nose.

HiveMind's interception approach is built around services and service interfaces. The interceptor factory creates a proxy that implements an arbitrary service interface. So instead of saying "apply this advice to this method of this interface" you say "use this service to create an interceptor for this service". In HiveMind, the interceptor proxy will implement all the methods of the service interface. In theory, an interceptor factory could use a set of parameters to control how it is applied to a specific service and service interface. At this time, the capability is there but none of the built-in interceptor factories do that. Going forward, when we develop a Transaction interceptor factory, we'll start doing exactly that.

Originally I thought Spring AOP was about the same as HiveMind service interceptors (I wouldn't call service interceptors AOP, though maybe "AOP-lite"). As I dug further into the documentation, I realized that Spring's AOP is quite a bit more involved, though I suspect it falls short of the features possible with AspectJ.

It is possible to pass properties to a Spring proxy factory bean (the equivalent of a HiveMind interceptor factory service). Again, HiveMind can define a parameters schema, and pass arbitrary XML as the parameters.

HiveMind has the ability to allow multiple modules to contribute interceptors to a given service point. The upside of this is that new capabilities can be added to a service, such as service interface method logging. The downside is that, unlike Spring, we can't rely on the order in which interceptors are specified to be the order in which they should be applied to the service ... we need to add an order attribute for sorting.

Continuing with research; HiveMind has a concept of multiple modules; all modules are peers and can interoperate (contributing to each other). Spring has a container hierarchy, where (for example) a web application context will have child contexts for each servlet. Names of beans are resolved upward, such that the root application context can provide defaults for beans of a given name when not overridden by a servlet configuration. HiveMind has a single level of services (service ids are unique), but using a namespace approach (the qualified id for a service incorporates the unique id for the module ... thus services with fully qualified ids such as hivemind.BuilderFactory or com. myco.myapp.BusinessLogic).

Remember that HiveMind is a services and configuration microkernel. This is the raison d'etre of HiveMind: complementing and integrating a service model with a distributed configuration model ( inspired by the Eclipse plugin model).

Summary:

Concept Spring HiveMind
Inversion of Control (Dependency Injection) Types 2 and 3
(Property setting and by constructor).
Can autowire.
Types 2 and 3. Explicit wiring only.
Multiple modules Yes, hierarchical. An application context may have children. Yes, flat but namespace qualified.
Aspect Oriented Programming Very rich; standards based. Built in ways to target particular methods. Limited to "around" method introductions on interfaces.
Service management Manages singleton beans (or one-shot "prototype" beans). Bean implementation must be provided with bean definition. Many service models, including singleton, threaded and pooled. Service implementations must implement service interface. Service model hidden behind a proxy object, which may be shared between threads. Service implementation may be contributed by different module that service-point definition.
Configuration information Can configure beans only. Bean definition is single place (single XML file). Very rich; configuration-point to compliment service-point. Supports multiple contributions from many modules. Conversion of XML contributions into Java objects. Proxies for just-in-time access and conversion.
Project Documentation Print out the XML? HiveDoc: rich HTML (like Javadoc) describing all services and contributions across all modules.
Integration Integration with Hibernate, JTA, Spring MVC, more? Planned integration with Tapestry and others -- but nothing yet!

Sunday, February 22, 2004

Back from Philly

Just got back from No Fluff Just Stuff and had a really good time. It was a true whirlwind -- flew in Friday night, presentations on Saturday (8:30am and 3:30pm), plus time on the expert panel after lunch. I attended Bruce Tate's sessions on Hibernate and J2EE vs. .Net. Last night was dinner with the whole crew. When NFJS comes to the Boston area, I'll have to get people to a decent restaurant, maybe even a Chinatown excursion.

This seminar was small even for a No Fluff, only seventy five attendees total. Turnout for the Tapestry sessions was a bit disappointing. It was actually the smallest crowd I've ever given the Tapestry spiel to: 5 in the first session I believe, 7 in the second. Bruce and folks said they often get questions about Tapestry during the expert panel ... but not while I was there. Interestingly, when I announced that I was the creator of Tapestry, heads on the expert panel turned ... they thought I was just the author of the book.

I need to tune my presentations a little ... there's a bit too much marketing ("fluff") in them, and I should use the time to cover some more interesting features (such as form input validation) ... that is, more "stuff". There's no point in selling Tapestry to this particular crowd ... they're already somewhat sold in choosing my session over the other three running at the same time. Even so, I got back a lot of positive evaluations. The one bit of Fluff I should add in is to discuss the other members of the Tapestry team, the subject of the most common question between sessions ... a disguised way of asking "how viable is Tapestry?".

I think I'll change the titles, too. Beginning Tapestry: Java Web Components is too generic. Expanding that session to discuss form input validation will show off the power of the framework, but also allow me to change the title to something like Build Powerful Web Forms with Tapestry, which is more in the spirit of NFJS.

With the work of the book finally behind me, I'm beginning to see other things more clearly. I really have been stressed, especially the last few months. One question that came up during the expert session concerned time management ... I stayed quiet because for the last year, I haven't managed my time, the book has managed me. Strangely, despite learning Maven and creating HiveMind, I still don't feel I've kept adequately current ... thus my renewed interest in Spring and Hibernate.

With HiveMind now free, I can put together a session about it. I think an important part of the presentation will be interoperability ... my live demo can show things like accessing a session bean in JBoss as if it were a HiveMind service. I also want to learn a bit more about Spring. What I want is the ability to represent beans managed inside Spring as HiveMind services, plus whatever else is necessary to allow HiveMind to run Spring within itself. I'm sure the Spring guys can do just the opposite (get a HiveMind Registry created as a Spring managed bean).

Also, I'm going to finally take some time to look into Hibernate properly. I'll certainly be doing some Tapestry / HiveMind / Hibernate (Hivernate?) integration. In fact, showing how to use Hibernate properly within a Tapestry application would make another great session for NFJS.

Friday, February 20, 2004

Tapestry In Action -- Printing on Tuesday

Tapestry in Action will be printed on Tuesday, Feb 23 2004. Physical copies of the book will arrive at my house in mid March, at the same time copies arrive at the distribution warehouse. Copies will arrive in book stores, and start shipping from online retailers such as Amazon, about two weeks after that (late March or early April). I'm doing the final, final, final proofreading today, before I split for the Java Freedom Software Symposium.

Thursday, February 19, 2004

HiveMind developers ... Please check in!

Four months ago, we assembled a list of developers interested in forming the core committers for HiveMind when it went into incubation at Apache. Because of the WebCT IP issue, things have been dead quiet since then. Tomorrow morning (USA East Coast time), Prashant will be faxing the software grant for HiveMind to Apache. Once that is received and acknowledged, Prashant will be resubmitting the proposal to the Jakarta General list.

Part of that proposal is the list of initial committers. If you are still interested, please get in contact with me! This isn't a cattle call ... I'm just having trouble reaching a couple of names on the list via e-mail and am hoping those folks monitor this blog.

In addition, you need to sign a Contributor License Agreement (CLA) before you can be given commit access to the Apache CVS servers.

Wednesday, February 18, 2004

HiveMind grant is a go!

Just got an e-mail from Chris Vento, the CTO at WebCT. He's signed the software grant for HiveMind, so we can finally get back to work on it. I'm checking with Prashant Nayak (also at WebCT) to see what's happening there ... I think it's just a matter of Prashant faxing the signed document to the ASF.

HiveMind and event listeners

I'm still very confident that the HiveMind debacle will end, and soon, with the software grant to the ASF.

Confident enough that on my trip to and from San Jose, I opened up the HiveMind source code for the first time in months to add some new features (even with a flakey 'A' key).

It seems to me that a very common use case for HiveMind services is for one core service implementation to register for events produced by another service. In terms of Tapestry, I can imagine services that need to know when the reset service has been activated, so that they can clear their caches.

In alpha-3, you could have the BuilderFactory set a property of your service to an event producer service, then inside initializeService(), you could add this as a particular listener of the producer.

Kind of ugly:

  • You need a property of your core service implementation to store the event producer service, even though you only use it the one time
  • You need to implement Initializable just to do the event registrations

The changes I just made affect BuilderFactory. It adds a new element that can be nested inside <construct>: <event-listener>. <event-listener> allows you to specify another service (using a service-id attribute). This other service is the event producer, which includes methods in its service interface for adding (and removing) listeners of a given type. The constructed service will be added as a listener of events from the event producer service. Just the core service implementation needs to implement the listener interface ... the service interface does not have to extend the listener interface.

The thing to keep in mind with this is that HiveMind is using JavaBeans definition of an event set to find the method to invoke. An event set is to listener interfaces as accessor methods are to a property. An event set is a pair of methods:

  • public void addFooListener(FooListener);
  • public void removeFooListener(FooListener);
(defines an event set named 'foo'). You need both the add and the remove method for the JavaBeans Introspector to recognize the event set.

I'm very happy with this code ... it's another sweet layer of abstraction that will allow all manner of services to quietly interoperate behind the scenes. I can already picture many uses for this in Tapestry 3.1.

This Blog brought to you by the letter 'A'

During my lightening trip out to California yesterday, I had another horrible infrastructure let down: when I got to my hotel, the 'A' key on my laptop keyboard was damaged. No clue why ... it had worked in Phoenix (the stop over on the way to San Jose) but there it was ... the feel of the key was wrong: it needed excess pressure to work, and even then, didn't always work. I had visions of me having to send the entire thing back to Dell for service ... possibly weeks without my laptop!

Fortunately, I follow the principal of WWDGD? (What Would David Goldman Do? -- David being one of my best friends and exceptionally handy at all things electronic or mechanical). David would have bravely pulled up the broken key cap and figured out what was wrong underneath. That's exactly what I did ... and found an anomalous amount of hair in there. Anyway, a careful cleaning, a gentle re-application of the key cap ... and the letter 'a' is back. Useful for words such as 'Tapestry'.

Sunday, February 15, 2004

Garbage collection and performance

A nice article over a IBM's DeveloperWorks: Java theory and practice: Garbage collection and performance

Tapestry went through this same kind of work over back in the 2.0 timeframe (around the time of JDK 1.3). I went to a lot of trouble to pool all sorts of little objects, particularily StringBuffers. Guess what? Performance went down! I knew this because I did some profiling. I stripped all the pooling code out and, even with all those short term instantiations of StringBuffers and the like, performance went back up. Later JDKs have helped even more.

There are too many moving parts in a Java application (too many frameworks, too many layers of too many different kinds of code, too many threads) to predict how performance will be affected by your code changes. As the IBM article points out ... you can easily hurt more than you help.

Wednesday, February 11, 2004

Source code for "Tapestry in Action"

I've gotten a few requests for the source code for Tapestry in Action. For some reason, Manning hasn't made it available yet on thier web site.

As an interrum measure, I've put it up on my personal web site: TapestryInActionSource.zip. Enjoy!

Tuesday, February 10, 2004

Thanks again for Spindle, Geoff!

So, I'm putting together new examples to support my upcoming presentations and this time around, I'm finally getting to use Spindle. It's very impressive ... it takes the normal build/deploy/execute/analyze cycle (the analyze step being the time you take to figure out what caused the exception page to display) and reduces it to a build cycle most of the time. The kind of errors I make all the time (wrong attribute name on an element, mismatched component ids in the template and the specification, missing required parameters on components, and so forth) are caught at build time and flagged like any other kind of error.

Here's a really huge picture that shows just a few of Spindle's features. It's no wonder that Spindle was voted the top Eclipse plugin recently, it's a compelling reason to use Eclipse in the first place ... just as Tapestry is a compelling reason to use Java.

Friday, February 06, 2004

HiveMind relaunch draw near

This time, I gave Prashant a rest, and went right to the top: Chris Vento, CTO of WebCT and the man backing the decision to go open-source with HiveMind.

Where-as Prashant could only guess at what was happening, Chris could be very specific: "I will move on it by next week and get the lics form executed and submitted." The reality has been a crush of work, deadlines, end-of-year reviews, client contracts, and so forth--not any desire to back away from releasing HiveMind as open source.

I'm looking forward to this; I have a bunch of powerful features for HiveMind planned, including a whole suite of JMX related stuff and it's all been on hiatus waiting for this.

In other news ... Noel Bergman found out what was causing the e-mail snafus at Apache for the last week or so. Surprisingly, it was on the Apache side, not the Comcast side! A temporary filter was put in place because of the MyDoom virus that was inadvertently left on. Noel has changed a daily summary report to include details about such things ... hopefully it won't happen again.

Wednesday, February 04, 2004

Sending smoke signals ... voted off the Island by Comcast Apache

It can get a little frightening when you realize that you've taken for granted a technology and it suddenly fails to work.

In my case, it appears that there's a disruption which is preventing mail originating at comcast.net's domain from reaching apache.org's. This may have been going on for a week (its probably related to the massive amount of e-mail from the MyDoom virus).

I'm starting to try and penetrate comcast's protective walls of low-level flunky customer support. Basically, if you are a comcast customer, no mail sent to apache.org (including all the mailing lists) is getting through.

That means, for me, that a bunch of question responses on the mailing lists haven't gone through. I started a vote to release Tapestry 3.0-beta-4 that is in limbo. My business cards have the hlship@apache.org e-mail address (forwarded to hlship@comcast.net) so Comcast customer can't reach me directly.

I may have to setup a Yahoo account, just to be able to get the attention of the Apache infrastructure folks. What next ... no dial tone?

Update: It was Apache's fault after all!

Tuesday, February 03, 2004

Java Freedom Software Symposium by No Fluff Just Stuff

I'll be presenting two sessions on Tapestry at the Java Freedom Software Symposium by No Fluff Just Stuff, which takes place Feb 20-22 in Philadelphia, PA.

I'm pretty excited by this ... not just the chance to do another big Tapestry presentation, but the chance to attend the other sessions (many of which are things I'm dying to get into) and meet the other speakers. I expect to learn a lot ... a lot about other Java open-source technologies and a lot about presenting (these guys are veterans).

Hope to see a few of you folks there ...