Alex headshot

AlBlue’s Blog

Macs, Modularity and More

SpringSource App Platform and bundle repository

2008, eclipse, osgi

The recent announcement of the SpringSource Application Platform has created a lot of interest in the OSGi framework. It will undoubtedly be a great driving force to introduce the platform to those that haven't heard about it before, even if they don't initially end up using anything of OSGi directly.

The best part of the announcement is the creation of the repository, which unlike OBR (or to a lesser extent Orbit) will contain a number of key open-source projects suitable for use as OSGi bundles. The Felix team have been doing a great job in encouraging the adoption of OSGi metadata in Apache Commons projects, but most libraries don't (at the moment; but expect the tide to turn this year). The implication is that this repository is supported and will track new versions as they come out, much like Maven's repository.

OBR has a slightly different outlook - it offers a place for existing bundles to be housed. Given that the main benefit of the SpringSource repository is housing things that aren't already bundles, and the fact that it is transitively closed, makes it a great investment as a base to build on, even if you're not using the SSAP.

Orbit is closer to the SS repository, but suffers from a couple of major flaws. The first is legal; there's a strict IP policy about what goes in, and this takes time to complete. So of doesn't have the latest-and-greatest all the time (although one can expect Ganymede to be not too far behind when it is released later this year). But there's a ramp-up time to getting code in there - for example, the Apache Harmony project (disclaimer: to which I have contributed in the past) has been asked to provide a preview build of their next milestone specifically so that it is available to start the toboggan run of the IP process in time for Ganymede's release.

The second is probably more important — not only are individual bundles versioned, but rather the entire repository is versioned. This wastes space for mirrors (who often end up with multiple copies of exactly the same bits) and as a consequence, the releases of orbit ate infrequent. But if you are building and need a bundle that isn't there, you have to go through the wait-and-see approach to when it gets in.

The net effect is that Orbit is basically useless for anyone other than Eclipse committers who have no choice but to use it; and even then, they may opt to hold internal references instead. It's certainly not useful for the general OSGi-building community at large to be able to build from.

The only problem with the repository SSAP (Update: Glyn corrected me that only the standard OSGi headers are used in the repository) is the use of non-standard headers (which many don't like). Although these should be transparent for other OSGi users, it does somewhat tie you down to the SSPA if you go the route of using the Import-Library or Import-Bundle (and the arguments for it are less than convincing). There may be problems with the existing Import-Package or Require-Bundle, but the right way to get those fixed is by percolating them up through the JSR-type review process or by feedback to the OSGi. Perhaps OSGi 4.2 (or 5.0) will have these headers in, in which case it's less of a problem since the playing field is level again.

The big thing that I believe is missing from the point of that post is that you can do this all already with Require-Bundle. The former might be best practice, but it's trivial to satisfy the needs of a 'library' by defining a bundle to represent that library and then have dependencies re-exported:

Bundle-Name: hibernate
Bundle-Version: 1.2.3
Require-Bundle: org.hibernate.foo;visibility:=reexport

One can then depend on the 'hibernate' bundle, and should hibernate as a whole be updated, we are isolated from that change. The point of Import-Package is that it can isolate you from bundle name changes (or moving across split bundles) — but that's exactly the same here. Should Hibernate be bought by Sun (they seem to be doing a lot of that lately) and the (implementation) bundle is renamed to com.sun.hibernate, we only need to change this façade to point to the new name, and all is well.

There are some OSGi people who can't understand the need for OSGi bundles without code, because that's all they think of. But there are many reasons to have an OSGi bundle that doesn't have any code; one might use it for distributing versioned resources (such as a set of stylesheets as used in docbook editing, although sadly that's not included in XSL tooling). Whether there's code in the same bundle or not, it's easy to use Bundle.getEntry() (be carfeul about using getEntry vs getResource/getResourceAsStream) to load code from another bundle in the system, and arguably the data should be independent of the code so that it's possible to upgrade the stylesheets independently from the processing tools that use them.

Taking that a step further ... why require any resources? The Manifest.MF is a resource, and you can store information in that which is useful from an interrogation point of view. In fact, once you've got a bundle in the dependency list, it's easy to find the bundles that depend on it, since there's a handy getRequredBundles() call available from PackageAdmin that you can use. To address Glyn's post:

Yes, it is certainly possible to use a "visibility:=reexport" façade as a way of implementing libraries, but the design intent gets lost along the way and you have to resort to some careful naming conventions if the runtime is to "understand" libraries and manage them in any meaningful way.

Consider a situation where a library is deployed into the Platform and then some applications are deployed that import the library. Later an administrator comes along and is considering upgrading the library and wants to know which applications currently depend upon it to assess the impact. The runtime needs to be able to report the dependencies at the level of applications and libraries.

Firstly, the above uses standard OSGi headers to achieve its dependency goals. Secondly, if the intent is to filter out the ones that are considered 'libraries' (for some vague hand-wavy definition of 'library') then it's easy to add an additional header SSAP-Library: true (although it should be noted that values like 'true' and 'false' are generally not considered good practice either). The dependency tool can then look for bundles which contain this magic field, and report on the bundles that depend on it by a two-pass look at all the bundle's dependencies. What's wrong about the Import-Library solution is that it mixes the two concerns; 'what is a library' with 'what does this depend on'.

I've suggested in the past that Eclipse features should be bundles (and installable separately) in their own right. I've even proposed that the feature dependency should in fact be bundles (as the above example) and that you know the feature is installed correctly if the bundle's state is RESOLVED as opposed to INSTALLED. For some reason, this aspect of the OSGi platform is currently underused, and there's no technical reason for it to be so, only bias against the orthodoxy that an OSGi bundle must contain code.