Building a modern Java app with Eclipse, Maven, OSGi, and Spring DM (Part 2)

July 9th, 2009  |  Published in development  |  4 Comments

Continuing from yesterday’s post about Maven, I’m going to briefly discuss our approach to handling OSGi.

Every module that we build, whether it’s a JAR or a WAR, is packaged as an OSGi bundle. Originally we relied on the maven-bundle-plugin from Apache Felix to generate the MANIFEST.MF files every time the package phase was executed. As the manifest was dynamically generated, we were careful to never check in the generated manifest, as it would result in errors when a developer or our continuous integration system attempted to build the product and would inadvertently clobber the read-only manifest file.

As part of the plug-in configuration we originally hand-coded each and every package import, although recently we’ve been relying more on bnd’s ability to scan bytecode and only adding imports for packages referenced from Spring application contexts or other non-bytecode sources. This has made the process much easier, but there is still a chance that you could end up with a ClassNotFoundException or NoClassDefFoundError if you’re not careful (more on that in a moment).

We have also recently switched to generating the manifest file once and then checking it into Perforce. The static manifest means that when we import the modules into Eclipse we can take advantage of the PDE tooling to edit and maintain the manifest. It also allows us to have the modules (bundles) automatically added to the Eclipse target platform, making it easy to run the product and debug it from within the Eclipse IDE.

One downside to these approaches is that there is still duplicated metadata between Maven and the maven-bundle-plugin/OSGi because they do not share a common metadata source. Our practice of relying on bnd to pick up most imports has minimized this to some degree. We expect that future improvements to Maven, PDE, and other OSGi tooling will eliminate the problem entirely.

Testing

OSGi metadata is challenging to get right the first time, so early on we established the practice of creating OSGi integration tests for each bundle that was produced. The purpose of the tests is to verify that the correct packages are being imported/exported from a bundle, that no implementation classes slip into the export list, and that any services or service references are correctly registered/resolved. One of my colleagues wrote an abstract class that takes away much of the pain of programmaticaly starting Eclipse Equinox and automatically loading in our third-party dependencies, so all the individual test authors needs to do is essentially reproduce the OSGi metadata/contract in JUnit form (we’re currently using Spring DM’s OSGi tests support).

So far the tests have been rather successful at identifying missing dependencies prior to deployment. The only real downside to this approach is the duplication of metadata in the test cases.

Recommendations

  1. Rely on bnd’s bytecode scanning technique to pick up most package imports instead of explicitly adding them to the maven-bundle-plugin’s configuration.
  2. Explicitly add packages referenced from XML files (Spring, Hibernate, etc.) and for classes that are dynamically loaded. Hibernate or other frameworks that use cglib/javassist can be particularly difficult to get right if you’re not extremely careful.
  3. Make sure your modules always have a manifest file with OSGi metadata so you can take advantage of the Eclipse PDE tooling.
  4. Run your bundles in an environment as similar as possible to your target platform prior to deploying in production so you can ensure that all the necessary dependencies have been specified and are present in the environment.

Tags: , , ,

Responses

  1. Andy Wilkinson says:

    July 10th, 2009 at 7:28 am (#)

    Kyle, with regards to manifest generation, you might be interested in Bundlor: (http://www.springsource.org/bundlor). In addition to the bytecode scanning that bnd supports, it will also generate imports from Hibernate and Spring XML files among others. There’s more information on the detection support available here: http://static.springsource.org/s2-bundlor/1.0.x/user-guide/htmlsingle/user-guide.html#detecting. There’s more to come in this area, e.g. M5 will add support for scanning web.xml files too.

  2. kyle says:

    July 10th, 2009 at 8:44 am (#)

    Andy, that’s good to hear. One of my colleagues tested out Bundlor and ran into some problems with either it or STS that he was unable to resolve, which is why we haven’t been using it. I’ll check with him and see if he has details of exactly what went wrong.

  3. Andy Wilkinson says:

    July 11th, 2009 at 12:41 pm (#)

    Thanks, Kyle. If you can get the details from your colleague I’d love to hear them so that we can fix the problem he was encountering (if it’s not already fixed).

  4. Victor says:

    July 24th, 2009 at 3:55 am (#)

    Typo in Recommendations #3: \Eclilpse\