Saturday, July 25, 2009

Installing OSGi bundles with dependencies

One of my favorite features of OSGi is you can write jars/bundles that provide code and/or services to other jar/bundles. However, one of my least favorite features of OSGi is how you can't just install a single jar, as most likely, that bundle will require packages and services from other bundles in order to work. Passing a list of bundles with instructions to install them in a certain order sucks.

To help solve this deficiency, there is the OSGi Bundle Repository (OBR), which is a bit like Maven 2's dependency management in that when you install a bundle using it, OBR can look at external repositories to find any required dependencies and install them as well. Unfortunately, a) there is barely any documentation or code samples out there on integrating OBR into your OSGI application and b) having an OSGi app go out to the internet to download other bundles at runtime just plain scares me; take Maven's penchant for downloading the internet and put that "feature" into your production application... *shudder*.

The solution I came up with uses the dependency resolution aspect of OBR but without needing any network access. Instead of installing a bundle directly, you install an ".obr" file, which is a zip file with the following layout:
main-bundle1.jar
obr.xml
dependencies/dep-bundle.jar
dependencies/dep-bundle2.jar

When installed, the installer looks at the obr.xml and determines if the main bundle can be installed as is. If there are any missing dependencies, it takes them from the "dependencies" directory and installs as necessary. Therefore, only the necessary bundles are installed yet OBR doesn't go out to the network, and, bottom line, you can again distribute and install one file.

The obr.xml file is the standard OBR descriptor file that describes the main bundle and all its dependencies. The dependency bundles are packaged in the .obr zip only to be used if needed during installation. For example, if user A installs the .obr file on their osgi system that already contains dep-bundle.jar, then the installation process will only install dep-bundle2.jar. If user B has neither, then the installation process installs both dependency bundles.

There are other options I found (PAR, DeploymentAdmin) for grouping bundles, however, they tend to exist as a way to define multiple bundles as a single, possibly indivisible, unit, but in our case, dependencies are meant to be shared between bundles of different origins. Did I miss anything or is this the best option for achieving my goals?

Friday, July 17, 2009

Greasemonkey for Maven 2

Few things are more tedious than crawling through hundreds of lines of Maven 2 output to discover which test failed, mojo didn't execute correctly, or error was thrown during integration tests. After using git for my primary version control tool, I'm spoiled with its lovely full-color output, so why can't I have that for Maven 2?

Turns out, there is a ticket open in the Maven JIRA project for this, but so far, there doesn't seem much traction, and fixing it for me now would involve forking Maven again, which I'd rather not. Therefore, I decided to take the Greasemonkey approach and write a wrapper around the Maven output so that I can format it exactly how I want.

Introducing the Console Colorizer, a command line tool for wrapping Maven execution, then feeding its output through a Lexer that adds VT100 color codes where appropriate. This approach is suprior to the usual colorizing the logging output, because I can match any text and highlight it any way I want. Going a bit farther, I could even detect certain bits of output and execute arbitrary code, like sending a Growl or IM notification. All this without modifying any Maven Java code.

Compare this raw Maven 2 output:


With this:


It is so much easier to see that the test failed, and what warnings your Maven plugins are complaining about. This tool works by wrapping the Maven main execution and running the System.out through a JFlex lexer. The lexer is nice because it allows me to define tokens via regular expressions, yet remain very fast and compact. A few VT100 codes allow me to add the coloring.

Of course, this same technique could be applied to any Java program, or any program at all if you really wanted to, but for now, I think it'll do nicely to clean up Maven 2 a bit.

Goodbye JRoller

After some four or five years, it is time to move off of JRoller. That site goes down more often than a...well, you get the point. Let's see how blogger treats me...