Tapestry Training -- From The Source

Let me help you get your team up to speed in Tapestry ... fast. Visit howardlewisship.com for details on training, mentoring and support!

Saturday, October 23, 2004

Upgraded HiveMind to Forrest 0.6

The Forrest team recently announced Forrest 0.6. When I first switched HiveMind away from Maven, a key concern was documentation, and Forrest provides much more and better functionality than Maven.

However, like Maven, with Forrest you venture forth from the narrow blessed path at your own risk. I had much trouble getting HiveMind's documentation to build to my liking under Forrest. The tool is complex, with many, many, moving parts (including Cocoon !) and will often create wrong output, rather than report an error.

In 0.5, I discovered that I had to include <index href="index.html"/> in my site.xml file to get the tabbed navigation views to work properly.

The upgrade to 0.6 is supposed to be simple but I found a number of problems:

  • The imported Ant script doesn't work (details in the forrest-user mailing list). Even if it did, it would pollute my project with many additional targets. My workaround was to re-invoke Ant using the patch Ant libraries shipped with Forrest (!)
  • Had to completely rebuild the skinconf.xml file
  • cli.xconf had to be changed, and it was necessary to create a project.configfile entry in my forrest.properties file
  • Forrest 0.6 kept emitting the exact same file as index.html at each level of my project. This was not only the wrong information for the hivemind, hivemind-lib and hivemind-examples folders, but didn't render because relative paths to the style sheets were broken. The only workaround I found, and this is very ugly, is to change all the document hrefs in my site.xml to use complete paths to each file (i.e., <index href="hivemind/index.html"/>).
  • I've been getting various errors related to wholesite.html and wholesite.pdf, so I turned that off.

All told, I spent quite a few hours getting this working to this level, most of it the kind of blind thrashing that's necessary when tools don't validate properly, or report problems usefully. Many times I strongly considered working backwards to Forrest 0.5.

The results so far are a cut above what we had before. The smaller fonts are good (as is the JavaScript based font-size control). There are a number of layout glitches (at least under FireFox) related to long entries in the left-side menu. I with I had more control over what menu items start expanded (maybe I do have that, but Forrest documentation is paradoxically pretty poor and I've yet to find it).

Forrest 0.6 also gives you more control over style, by making it easy to integrate some custom CSS styles into the default stylesheet (this is part of skinconf.xml) and allowing all elements to accept a class attribute.

Overall, I'd give Forrest a C+ as a grade; the final results once working are a good B+/A- ... but the process for getting there (especially when factoring in the pain of an upgrade) has to be considered. The cost of adoption can be extraordinarily high, especially if you have an existing project and existing documentation.

Fortunately, unlike the Maven team, the Forrest team recognizes this at least as far as their version numbers; 0.6 indicates that it is still an alpha or beta release and they know they have some distance to go before they can call it a true product.

[FIXED] Abandoned by Google Mail

It's funny how quickly you can become dependent on a service ... and if it's a free service, with no support, that can be a problem. In my case, it's Google Mail, which no longer lets me log in (it hangs for a while with the "Loading ..." message, then pops up a window about trying again later).

I've let myself get dependent on GMail for nearly all of my Tapestry and HiveMind correspondence but there seems to be no support outside of this support group. Is it moderated? My posting about this problem hasn't shown up. I'm not the only one with this problem, but since Google Mail doesn't have any accessible support, I'm a bit hosed!

If and when I get this resolved, I may rethink my usage of GMail. It's fast, convienient, and searchable ... but none of that is helpful if you can't depend on it!

Updated 10/26: And GMail is back again. I added a bug to their support system (only accessible once logged in) complaining that ... their bug system is only accessible once logged in!

Thursday, October 21, 2004

Speaking at NoFluffJustStuff this weekend

I'll be speaking at the Boston No Fluff Just Stuff this weekend (Oct. 22 - 24th). My three sessions (Tapestry forms, Tapestry components, HiveMind) are all on Sunday, but I'll be around the entire weekend. Jay has been experimenting with alternatives to the expert panel, such as "Birds Of A Feather" or other smaller, more focused interactions and that I like and am more comfortable with.

Tuesday, October 05, 2004

Now that's handy

[Eclipse Clover View]Clover has always been useful (and Cenqua has always been generous with licenses for open source projects), but I finally got around to installing their Eclipse Plugin. It's not perfect, but it is simple and it does work. My old procedure was the run my tests using Ant to build the code coverage, then switch back and forth from a web browser to my source code. This is much, much easier (though the markers for lines that have not executed are a bit too subtle ... I'd prefer a change in background color, as with the HTML report).

Meanwhile, it's time to fill in some of gaps in my code coverage test suite!

Monday, October 04, 2004

Worst Eclipse Crash --- Ever

Somehow, after years of flawless service, my Eclipse workspace just self-destructed. Don't know what caused it, it just freaked out while I was switching between projects. My .log file says:

!SESSION Oct 04, 2004 18:44:07.894 ---------------------------------------------
eclipse.buildId=I200406251208
java.version=1.4.1_01
java.vendor=Sun Microsystems Inc.
BootLoader constants: OS=win32, ARCH=x86, WS=win32, NL=en_US

!ENTRY org.eclipse.osgi Oct 04, 2004 18:44:07.894
!MESSAGE An error occured while automatically activating bundle org.eclipse.core.resources (27).
!STACK 0
org.osgi.framework.BundleException: Exception in org.eclipse.core.internal.compatibility.PluginActivator.start() of bun
        at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:975)
        at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:937)
        at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:421)
        at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:293)
        at org.eclipse.core.runtime.adaptor.EclipseClassLoader.findLocalClass(EclipseClassLoader.java:110)
        at org.eclipse.osgi.framework.internal.core.BundleLoader.findLocalClass(BundleLoader.java:371)
        at org.eclipse.osgi.framework.internal.core.BundleLoader.requireClass(BundleLoader.java:336)
        at org.eclipse.osgi.framework.internal.core.BundleLoader.findRequiredClass(BundleLoader.java:914)
        at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:399)
        at org.eclipse.osgi.framework.adaptor.core.AbstractClassLoader.loadClass(AbstractClassLoader.java:93)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:255)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:315)
        at org.eclipse.ui.internal.ide.model.WorkbenchAdapterFactory.(WorkbenchAdapterFactory.java:26)
        at org.eclipse.ui.internal.ide.model.WorkbenchAdapterBuilder.registerAdapters(WorkbenchAdapterBuilder.java:33)
        at org.eclipse.ui.internal.ide.IDEWorkbenchAdvisor.initialize(IDEWorkbenchAdvisor.java:155)
        at org.eclipse.ui.application.WorkbenchAdvisor.internalBasicInitialize(WorkbenchAdvisor.java:165)
        at org.eclipse.ui.internal.Workbench.init(Workbench.java:789)
        at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:1325)
        at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:254)
        at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:141)
        at org.eclipse.ui.internal.ide.IDEApplication.run(IDEApplication.java:96)
        at org.eclipse.core.internal.runtime.PlatformActivator$1.run(PlatformActivator.java:335)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:273)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:129)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:324)
        at org.eclipse.core.launcher.Main.basicRun(Main.java:183)
        at org.eclipse.core.launcher.Main.run(Main.java:644)
        at org.eclipse.core.launcher.Main.main(Main.java:628)
Caused by: org.eclipse.core.internal.resources.ResourceException: The resource tree is locked for modifications.
        at org.eclipse.core.internal.resources.WorkManager.checkIn(WorkManager.java:93)
        at org.eclipse.core.internal.resources.Workspace.prepareOperation(Workspace.java:1628)
        at org.eclipse.core.internal.resources.Workspace.close(Workspace.java:298)
        at org.eclipse.core.resources.ResourcesPlugin.shutdown(ResourcesPlugin.java:324)
        at org.eclipse.core.internal.compatibility.PluginActivator.start(PluginActivator.java:52)
        at org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:958)
        at java.security.AccessController.doPrivileged(Native Method)
        at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:954)
        ... 30 more
Root exception:
org.eclipse.core.internal.resources.ResourceException: The resource tree is locked for modifications.
        at org.eclipse.core.internal.resources.WorkManager.checkIn(WorkManager.java:93)
        at org.eclipse.core.internal.resources.Workspace.prepareOperation(Workspace.java:1628)
        at org.eclipse.core.internal.resources.Workspace.close(Workspace.java:298)
        at org.eclipse.core.resources.ResourcesPlugin.shutdown(ResourcesPlugin.java:324)
        at org.eclipse.core.internal.compatibility.PluginActivator.start(PluginActivator.java:52)
        at org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:958)
        at java.security.AccessController.doPrivileged(Native Method)
        at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:954)
        at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:937)
        at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:421)
        at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:293)
        at org.eclipse.core.runtime.adaptor.EclipseClassLoader.findLocalClass(EclipseClassLoader.java:110)
        at org.eclipse.osgi.framework.internal.core.BundleLoader.findLocalClass(BundleLoader.java:371)
        at org.eclipse.osgi.framework.internal.core.BundleLoader.requireClass(BundleLoader.java:336)
        at org.eclipse.osgi.framework.internal.core.BundleLoader.findRequiredClass(BundleLoader.java:914)
        at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:399)
        at org.eclipse.osgi.framework.adaptor.core.AbstractClassLoader.loadClass(AbstractClassLoader.java:93)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:255)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:315)
        at org.eclipse.ui.internal.ide.model.WorkbenchAdapterFactory.(WorkbenchAdapterFactory.java:26)
        at org.eclipse.ui.internal.ide.model.WorkbenchAdapterBuilder.registerAdapters(WorkbenchAdapterBuilder.java:33)
        at org.eclipse.ui.internal.ide.IDEWorkbenchAdvisor.initialize(IDEWorkbenchAdvisor.java:155)
        at org.eclipse.ui.application.WorkbenchAdvisor.internalBasicInitialize(WorkbenchAdvisor.java:165)
        at org.eclipse.ui.internal.Workbench.init(Workbench.java:789)
        at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:1325)
        at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:254)
        at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:141)
        at org.eclipse.ui.internal.ide.IDEApplication.run(IDEApplication.java:96)
        at org.eclipse.core.internal.runtime.PlatformActivator$1.run(PlatformActivator.java:335)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:273)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:129)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:324)
        at org.eclipse.core.launcher.Main.basicRun(Main.java:183)
        at org.eclipse.core.launcher.Main.run(Main.java:644)
        at org.eclipse.core.launcher.Main.main(Main.java:628)

!ENTRY org.eclipse.osgi Oct 04, 2004 18:44:07.924
!MESSAGE Application error
!STACK 1
java.lang.NoClassDefFoundError: org/eclipse/core/resources/IProject
        at org.eclipse.ui.internal.ide.model.WorkbenchAdapterFactory.(WorkbenchAdapterFactory.java:26)
        at org.eclipse.ui.internal.ide.model.WorkbenchAdapterBuilder.registerAdapters(WorkbenchAdapterBuilder.java:33)
        at org.eclipse.ui.internal.ide.IDEWorkbenchAdvisor.initialize(IDEWorkbenchAdvisor.java:155)
        at org.eclipse.ui.application.WorkbenchAdvisor.internalBasicInitialize(WorkbenchAdvisor.java:165)
        at org.eclipse.ui.internal.Workbench.init(Workbench.java:789)
        at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:1325)
        at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:254)
        at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:141)
        at org.eclipse.ui.internal.ide.IDEApplication.run(IDEApplication.java:96)
        at org.eclipse.core.internal.runtime.PlatformActivator$1.run(PlatformActivator.java:335)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:273)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:129)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:324)
        at org.eclipse.core.launcher.Main.basicRun(Main.java:183)
        at org.eclipse.core.launcher.Main.run(Main.java:644)
        at org.eclipse.core.launcher.Main.main(Main.java:628)

And that's no help.

From an hour or more of careful experimentation, I determined that deleting the file C:\workspace\.metadata\.plugins\org.eclipse.core.resources\.snap lets Eclipse start back up ... but loses all my projects. This includes my current project (no uncommitted changes) as well as my jakarta-tapestry project (yes, uncomitted changes!).

Sometimes the computer knows when you are having a bad day, and decides to make it worse!

Friday, October 01, 2004

Royalty Check

Wow! Tapestry In Action has sold enough copies over the last six months to not only pay back the original advance Manning gave me, but even go over and kick me back a modest royalty check. I'd forgotten that could even happen. With some big announcements in the works for Tapestry and for myself, all hopefully feeding into book sales, I bet this isn't the last check I see from them!

Competition is good, right?

Just noticed on the GoogleAd side bar of my own blog that ArcMind (Rick Hightower's consulting/training company) is offering Tapestry Training. The outline is exactly what I'd like to be presenting ... fortunately or not, I've been so bottled up working on a large Tapestry project that I've made no progress on my own equivalent course.

I've talked with Rick a few times and I've worked with Drew Davidson (whose also associated with ArcMind, and is the creator of OGNL). These are guys who have used Struts, JSF and Tapestry in anger (that is, as part of real production work). I've been encouraging Drew to write a fair comparison of Tapestry and JSF; I think it would be a valuable document for JSF and Tapestry users alike, as well as providing the Tapestry team with even more direction.

Hopefully, ArcMind's offering will be a success, and will grow the Tapestry community by more than he steals away from me :-).

Using Tapestry's Table component

Tapestry's Table component is very powerful and very flexible. The Table component can draw information from a variety of sources ... everything from in memory to an external database via SQL and everything in between. The component can handle column sorting automatically, can work inside a Form, and can be broken apart into smaller pieces so that you can provide your own look and feel for parts of it (such as the navigation control for moving between pages of results). You can configure it using a short string, or provide any of several modeling objects to control pagination, data access, column content and order and so forth. Whew!

All that power and flexibilty makes it hard to pick up; John Reynolds has taken up the guantlet and come up with a kind of interactive tutorial and guide to this important Tapestry component.

Maybe he'll follow up with a guide to the Tree component? We can only hope!

Tuesday, September 28, 2004

[Off Topic] Roller Coaster Tycoon 3 demo

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

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

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

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

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

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

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

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

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

Alas, back to work for now!

Wednesday, September 22, 2004

Feedback++: Going beyond Line Precise Error Reporting

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

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

HiveMind 1.0 final tomorrow!

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

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

Thursday, September 16, 2004

Tapestry 3.1 and backwards compatibility

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

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

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

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

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

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

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

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

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

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

Wednesday, September 15, 2004

Whew! Full speed ahead!

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

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

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

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

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

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

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

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

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

Tuesday, September 07, 2004

[Off Topic] VoteOrNot.org

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

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

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

Saturday, September 04, 2004

NEJUG - Erik Hatcher on Lucene

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

Progress on all fronts

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

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

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

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

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

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

Saturday, August 28, 2004

ScrapeSDL -- Convert SDL back to XML

With the release of HiveMind 1.0-rc-1, I've managed to "strand" a number of HiveMind users who had adopted SDL (Simple Data Language). SDL is no longer supported.

ScapeSDL.zip is an Eclipse project containing code that can convert an SDL file into an XML file. It's what I used to convert all the SDL in HiveMind itself back into XML (though I did have to do a bit of manual reformatting).

Tapestry and HiveMind at ApacheCon

Last year, I did a short, 60 minute, session on Tapestry at ApacheCon ... and I really think that launched things for me. I got a lot of good feedback on Tapestry and on my speaking style, and its opened a number of doors for me.

This year at ApacheCon, I'll be doing a long session on Tapestry on Sunday that will cover most of the material in my two normal Tapestry sessions (form building and component building). Additionally, I'll have a HiveMind session late on Wednesday. Details may someday be posted on the ApacheCon schedule.

Erik Hatcher, Matt Raible, and many others will be there. It was a good time last year (of course, I did bring my wife, Suzanne).

I'm spending too much time in Vegas, for someone who doesn't gamble. I was there in April for TheServerSide Symposium, I'll be there in October for a friend's birthday, and back in November for ApacheCon. Thankfully, I have my rolling laptop case (what a difference that makes when your laptop weighs in at about 15 pounds!).

Wednesday, August 25, 2004

HiveMind 1.0-rc-1

Following a successful vote (notable only for the absence of a vote from Knut), I'm building out HiveMind 1.0-rc-1 at this very moment. That's Release Candidate 1 ... and I expect to be rolling to a final 1.0 release very quickly.

There are a boat-load of plans for 1.1 and I hope that, unlike Tapestry's lethargic pace, we can get a 1.1 out in just a matter of months or even weeks.

"Invite 6 friends to GMail" -- It's open season!

I've built up six GMail invites ... drop me an email at hlship AT gmail DOT com if you'd like one. First come, first served.

Update: Sorry, all gone!