Thursday, July 28, 2005

nifty toy = Tomcat + MX4J + hivemind.management + mc4j

Just brought up a managed version of Tomcat 5.5 on j2se 1.4 using mx4j and the hivemind.management module . There are just a few gotchas
  • put mx4j.jar and mx4j-remote.jar on tomcat's system classpath, along with bootstrap.jar
  • don't contribute services with performance interceptor to hivemind.management.MBeans
Everything else works cleanly out of the box. It's fun to watch your services drawing nice performance-graphs - just too cool.

Friday, June 03, 2005

Hivemind support for Hibernate Long-Session-Pattern

Finally I got around to dig into HiveMind's concept of service-models. Not much digging, actually it's amazingly simple and intuitive. I've implemented a new service-model called "stateful" which attaches service instances to a User-Session. "Stateful" actually is a bit of a misnomer since threaded and pooled services also hold state for the duration of one request.
Basically all one needs is
  • a persistence service I called ClientStateStorage, which can be provided with an http session for production. Otherwise it uses a simple Map for testing.
  • a service-model extending AbstractServiceModelImpl which works much like the PooledServiceModel
  • six (!) lines of xml to configure the stuff
And the best thing: Deployment by jar-dropping - I really love the way, HiveMind collects its config-data from all visible jars. I won't write another Springish application-context.xml.
Cluster-Failover-Safety is of course an issue because, as I understood it, HiveMind serialises services in a stateless manner (just writing its Id and, upon reading, creating a fresh instance with that id). For my Apps, however, that's not a big enough problem to trouble me much. Server-crashes happen so seldomly ...

Tuesday, May 31, 2005

Bugfix for Tapestry FCKeditor Component

There were bugs in tapfckconfig.js (absolute URL) and the Readme (missing servlet-mapping in web.xml) which prevented the filebrowser from working. The new version is (again) available here

Friday, May 27, 2005

Tapestry FCKeditor component

I've posted an FCKeditor component. It's a preliminary version - error handling support for File-Upload is still missing.
It consists of
  • a custom config-file tapfckconfig.js
  • the editor-component itself
  • a custom engine implementation mapping the filebrowser url's to the filebrowser service.
  • a filebrowser service which makes use of an ...
  • ... extension implementing the FileBrowser interface. This comes with a default implementation which just browses the filesystem of the server. It's easy to replace by a custom implementation supporting, e.g., a database.

Thursday, April 28, 2005

Stateful services in IoC Containers

Do HiveMind & Co. provide stateful services? I don't think so. Should they? As I'm growing increasingly fond of the Hibernate long-session-pattern, I do think so. You'd probably need some means of attaching/detaching some client-id to a thread (a servlet-filter, typically), so, after that the container could maintain same (service-id, client-id) to service-implementation map. In the servlet-case parallel request from the same client could be blocked (synchronised on) - actually this should be the general case - clients wanting to be served concurrently must provide thread id's instead of client ids.
HiveMind's pooled services should already be quite close, only, the pool needs to become aware of the client-id's -- I need to have a look at them.

Tuesday, April 26, 2005

Intercepting Exceptions in Tapestry Listeners

While I'm growing increasingly fond of Tapestry, there's one tiny advantage to Struts-like Action-classes over listener-methods. Namely, taking care of (non-technical) user exceptions by converting them to friendly messages. A common base-class for all pages overriding AbstractComponent's getListeners() method does the trick. I made it return a sub-class of the standard ListenerMap, which, in turn wraps each of the standard IActionListeners it returns into some custom IActionListener taking care of the standard user exceptions like "ObjectNotFound", "NoPermission", "OptimisticLockBroken" and the like by providing a nice message to a page property (or a delegate-bean).
Still, the way you have to unwrap your exception from the ApplicationRuntimeException is somewhat unsatisfactory. It's just too tight coupling to framework-internals. Maybe, there should be some hook in the framework to plug-in custom exception interceptors into listeners.
A nice way would be this: If the page implements an interface IListenerExceptionListener it would be called whenever a listener throws a suitable exception. Now, suitable could mean:
  • Any checked Exception (declared by the listener method)
  • contained in a list of classes (provided via the listener interface or some other means - could use a class to Listener Map instead, to avoid duplicate switching)
  • Any exception at all.

Wednesday, April 20, 2005

If you can't hide it below, hide it above

In one of the last projects, I was involved in, a Web-Controller accessed business logic through a service facade implemented as a Spring-bean hiding a hibernate-pesisted domain model. Transactions (and hibernate sessions) were controlled declaratively at the service facade. Sounds so nice and clean - nice layers not allowed to know certain things about fellow layers. Only, it didn't work out quite so nice.

  • First: Session/TA-state was, in fact, not hidden below the service facade, because domain objects (detached hibernate entities) were used in the service interface, resulting in plenty of LazyInitializationExceptions and duplicate objects. Tedious DTO's (see Fowler on local DTOs) would have avoided this, but at an unacceptably high price of cumbersome code-duplication.

  • Second: The "natural unit of work" in the application was handling one http request. So, the presentation code had to be careful not to call the service facade twice (or otherwise take over session/ta-control explicitly). So, after all, the presentation layer was, indeed coded, without any knowledge of the technical details below the service facade - sadly it had to know them to work properly.


In my current project, hibernate sessions and transactions are controlled almost entirely from a ServletFilter (See Gavin King's long-session-pattern) - and wow: no more LazyInitializationExceptions - nice "per-request-transactions". And the best of it: presentation and business layer are both freed from doing awkward things pertaining to hibernate persistence (re-attaching detached objects, explicitly setting ta-boundaries, pre-loading lazy collections before handing them back to someone who might need them). It's all hidden above. The only thing left to do is to request a fresh hibernate session at some sensible point (e.g. whenever the user is done with one set of "top-level-objects" and requests a new one).
Ah, yes, so Spring turned out to be rather useless in this particular case ...