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!

Sunday, July 18, 2004

HiveMind and autowiring

Sometimes the function of a community is to force you in the right direction. With HiveMind, there's the ongoing concern of too-much XML. Erik Hatcher somewhat forced the issue (he can be very incisive) and the response was the controversial Simple Data Language.

However, even that may not have been enough. The SDL is more concise, but your still have a lot to say in it. Over time, the BuilderFactory has been extended, in a number of ways to decrease the amount of SDL you need to put in place. For example, if a service needs to know its service id, it just needs a setServiceId(String) setter method and BuilderFactory will invoke it.

My more recent changes build on a very nice patch supplied by Marcus Brito, which allows you to access a service within the Registry using just its service interface. HiveMind will find the lone service point that implements that service and return it (throwing an exception if no service, or more than one service, implements the interface). Marcus did a good job, supplying a nice patch including JUnit tests (I only needed to do some minor touch ups). I can see how useful the approach is, though there's the danger of it causing problems (what happens at a later date when a second service is introduced?).

I've introduced another form of autowiring into BuilderFactory: after it has set all the properties it knows about (via autowiring and expicit sets) it checks the remaining writable properties. Any such properties that are interfaces are assumed to be services, and the unique service for that interface is located. Again, errors abound when the interface isn't a service, or there is more than one service implementing the interface (an attribute allows autowriting of services to be disabled).

The upshot of this is that you can specify less and less in the module deployment descriptor, and HiveMind will still do the right thing (or, it will provide detailed feedback about what went wrong).

The other big change in HiveMind of late is the concept of object providers. This is (as with much in HiveMind) somewhat abstract but very exciting. Previosly in HiveMind, the schema format identified the type and interpreation of attributes using translators. Is an attribute a configuration id? Then use the configuration translator. Is the attribute a service id? Use the service translator.

This is good as far as it goes, but it tends to promote a kind of propogation of elements. Look at BuilderFactory, which has a bunch of elements for different types: set, set-long, set-service, set-configuration and so forth.

This is also limiting; a property of an object (or service) to be set may be an interface, and it doesn't matter to the object whether that actual instance plugged in is a service or an arbitrary object. Given factory services (such as BeanFactory), its evident that HiveMind services aren't the only interesting objects out there. That's a problem that forces some people to cut-and-paste BuilderFactory to add new ways of supply objects to the constructed service. That's not good!

This is where the new object translator comes it. The translator is driven by a configuration point, ObjectProviders. The configuration defines different prefixes and provides services that know what to do with strings with that prefix.

So, for example, service:MyService will be intepreted as a service id, and bean:MyFactory:name will access a BeanFactory service and ask it for the name bean. There's even a service-property:MyService:propertyName option, to access a service and read a property from it.

For building services, BuilderFactory now has a set-object element. Further, since this is driven by a configuration point, it will be possible to add application-specific prefixes as well! So, once again, HiveMind is object soup, and its getting less important where those objects are coming from.

2 comments:

Unknown said...

Oh, yes. What we need is Scheme to hide the fact that we're using XML in a different syntax. No ... we should be using YAML. Scratch that ... RDF. Whatever. None of that addresses the core issues.

There's an ongoing discussion about whether HiveMind module deployment descriptors should be declarative (as they are today, in whatever syntax you choose) or procedural (scripting, using BeanShell or Groovy or flavor-of-the-month).

I'm pretty dead set against procedural; once you go down that path, HiveDoc becomes completely useless. I think the approach I've outlined in this blog ... making smarter use of code to eliminate the amount of content in the module deployment descriptors, is the way to go.

Unknown said...

Yes, but as soon as you apply that kind of scripting to the MDDs, HiveDoc goes out the window.

If you like that syntax ... fine, write it and have Ant convert it to XML or SDL for you and be on your way.