My $0.02 toward election coverage - even handedly searching Google for both candidates:
“A vote for kerry is…”
“A vote for bush is…”
| 2007 | 2006 | 2005 | |||
| 2004 | 2003 | 2002 |
My $0.02 toward election coverage - even handedly searching Google for both candidates:
“A vote for kerry is…”
“A vote for bush is…”
Reading through the documentation that talks about “Configuration Points” I’m struck that there’s a definite missing piece in the puzzle. When I am faced with a brand new piece of software the first thing I do is scan through all the menu items and toolbar buttons that it has. The next thing is to open its options / configuration dialog and scan through and see what is configurable about it. Just doing these two things tells me an awful lot about the piece of software in question. Virtually every piece of software I have encountered allowed some sort of runtime configuration that was persisted in some manner, whether that be in a database or in a file or what have you. While Hivemind is great about reading in the static data that will configure the various services within the application, it doesnt appear to have a clue about runtime, modifiable, persistent configuration. I ran into this a long while ago when writing a Prolog application, wanting to modify the internal decision making tree in the core of the app: it locked me out, wouldnt let me, telling me that the data was read-only. The sense of frustration ran as high then as it does now.
It doesnt seem like there’s a big leap to specify a for an application, with associated , that will be used dynamically to load and save the runtime modifiable options. Hivemind does claim to make life easier yet this oversight seems to let it down.
Open Source programmers generally write code to “scratch an itch” so does this constitute an itch that I should scratch, by writing the code the way I want it to work, and submitting it back to the Hivemind project to use?
More Hivemind - Auto-wiring
My class was derived from JPanel, and the interface didnt declare setBorder() yet the Hivemind auto-wiring of the class on instantiation wanted to try to set that property. Similarly my interface didnt declare a setLayout() either, yet here I am faced with errors that say
SEVERE: Error at file:/C:/Devt/java/hivemind/apps/chronicle/classes/META-INF/hivemodule.xml, line 16: Unable to autowire property border of service com.caffeinatedbliss.chronicle.hiveApp.LoginGUI: There is no service point for interface javax.swing.border.Border.
and
SEVERE: Error at file:/C:/Devt/java/hivemind/apps/chronicle/classes/META-INF/hivemodule.xml, line 16: Unable to autowire property layout of service com.caffeinatedbliss.chronicle.hiveApp.LoginGUI: There is no service point for interface java.awt.LayoutManager.
What’s a person to do? It would be really nice if the auto-wiring had a switch to limit itself to the declared interface in question, as it appears that it’s being driven more by the object itself than the declared interface(s) that it exposes. That, or an explicit list of autowire properties might be nice. I suppose that is what the set-[object | property | configuration | service | resource] methods are for. I suppose it would have been nice to have the documentation explicitly note that auto-wiring the class would attempt to initialize members not declared in the public interface.
Oh, how it feels to live life on the bleeding edge!
Ive been playng with Hivemind - a newly released Apache project. It’s tough being an early adopter as there’s very little meta-documentation to go look at. That is, something other than the documentation written by the project authors themselves. Im not saying that engineer-written documentation sucks or anything (though in most cases, it sucks rocks) but in the case of Hivemind, the documentation is pretty good. What was missing was “war stories” where people talk about the quirks, about how to get going from a standing start, and so on.
Hivemind provides a friendly framework that supports coding according to the “Inversion of Control” (IoC) design pattern (also known as “dependency injection”). Martin Fowler (author of a fantastic book on Refactoring) has written a helpful article on inversion of control on his website. Fowler's article mentions a couple of other IoC containers - namely Spring and PicoContainer. Having looked at them both I have to say that I like Hivemind better than either of them. PicoContainer focuses very closely on dependency injection and object creation in a very admirable, single minded fashion. As a result it’s not quite got the breadth / richness of API and suppor for my purposes.
On startup Hivemind will scan the classpath looking for XML descriptor files to define services and modules that implement the given service descriptions. It assumes that it’s looking for a file called hivemodules.xml in a directory called META-INF. In general, this is where a standard Java manifest file would live in a JAR file, so seems logical enough. I had great trouble getting my hivemodules.xml file to be read, until I remembered that it needed to be in may class path - I added an ant task to copy it across as part of the standard compile process, just to make sure. Of course, that meant I needed to use ant rather than my usual IDE compilation process when the module descriptor file got changed. That, or put my source directory into the runtime classpath (either would work).
I quickly ran into two limitations or issues with Hivemind that I’ll be needing to think about for the future. Fowler's article talked of dependency injection being of particular interest to people who wanted to implement a plugin style architecture; the main application needs to be unaware and independent of the 3rd party plugins that extend it in various ways. That is precisely the case with my open source project, Chronicle Lite, where a clean IoC pattern is used internally. This separation of concerns doesnt use an IoC container to manage the relationships but would benefit from using Hivemind. My problem is that Hivemind doesnt create a classpath dynamically on startup based on JAR files in the execution directory. Chronicle Lite, on the other hand, scans for JAR files and integrates them into the application on startup thereby allowing users to upgrade / enhance the application by simply dropping a JAR file into its directory.
It was the work of a few minutes to integrate Chronicle Lite's PluginScanner with Hivemind and I soon had the IoC container finding module descriptors in JAR files dynamically. (Chronicle Lite code shown in bold)
PluginScanner pluginScanner = new PluginScanner(pluginDirectory, statusReporter); ToolPluginScannerHelper toolPluginScannerHelper = new ToolPluginScannerHelper(); pluginScanner.addHelper(toolPluginScannerHelper); PluginClassLoader classLoader = pluginScanner.getClassLoader(); ClassResolver resolver = new DefaultClassResolver(classLoader); RegistryBuilder builder = new RegistryBuilder(); builder.processModules(resolver); Registry registry = builder.constructRegistry(Locale.getDefault());
I ran into an interesting issue as I was going on with things. It’s “first come, first served” when it comes to module names; the first time that Hivemind encounters a module, it’s added to its internal registry, and subsequent modules of the same name are ignored. Just a little “gotcha”, and certainly not Earth ShatteringTM, but it might bite someone.
What would be awesome would be an option that modules of the same name all coallesce into a single place. That way, all the plugins could live together. The container could still deal with clashes on actual service names within a given module.
I’ve used Log4J in applications but I've not used the JDK 1.4 logger at all. I note from reading online that the Apache commons logging framework (used by Hivemind) is agnostic about certain details, leaving them to the underlying logging framework, but I couldnt find out how to globally turn on logging at a certain level. Grrr. Lack of documentation, or simply my own stupidity, I dont know!
The reason that logging came up was the ability of Hivemind to transparently intercept services to (say) log method entry and exit, log timing / performance statistics and the like. My plugin JAR contained a hivemodules.xml file that said
So it wasnt obvious that when I later defined a logging interceptor that it would used the short name:
But stepping through the code indicated that, yes, my plugin service had been hooked even though I didnt see any logging (see 'inability to control commons.logging' for more details).
Hivemind works, and works well, especially when enhanced with some custom code to provide a dynamic classpath. Time will tell how many people post helpful “war stories” and thereby enhance the already good documentation, but I with the team well with the project and will continue my own investigations.