OSGi brings a lot of good software engineering to the table but it has two true innovations. The first, and reasonably well known is the service model. This innovation is reasonably well understood due to the overlap with web services.
However, the second innovation is so far out of the mainstream that even many OSGi developers have only a vague understanding. (Although many a developer starts to fall in love with the Bndtools resolver. It is a very hard to beat way to assemble applications.)
What I think is the second true innovation is the Requirements & Capability model (C-R).
The ugly name might be part of the problem, however, I think its problem is that it is not recognized. In marketing, I was taught, you generally want to describe a new product how it differs from a well-known product. True innovations are hard to explain and therefore hard to sell. I will try one more time though.
The problem that started this was Bndtools. A few months ago I was editing a Java file in Bndtools and one of the imports could not be found. Expecting to have to edit the
bnd.bnd file, where all the dependencies are listed, I accidentally hovered over the Quick Fix. Surprise, it contained a quick fix to add exactly the bundle to the build path that I had in my mind. Where did that come from?
After some scanning of the Git log, I saw that one of the frequent committers, Fr. Krieg, had donated this extremely useful PR already a long time ago, I’d never noticed it before. He had written a quick fix processor that took the missing import and then did a search in the workspace repositories for the exported packages. Bndtools repositories maintain a lot of metadata about the bundles you’re working on as well as the external dependencies. Bndtools keeps all of this metadata dynamically up-to-date with the changes in the workspace or external snapshots. No need to initiate some build step to get your IDE in sync!
The reason that Fr. Krieg could search for a package name is that the repositories contain the exported packages as a Capability. In the C-R model, Capabilities and Requirements are bound to a Namespace; the definition of what attributes a Capability has. For example, the
osgi.wiring.package Namespace is reserved for Export-Package and Import-Package. Since the model is generic, Fr. Krieg could create a generic query to find all Resources (the bundles) that provided the package capability he was looking for.
Recently we discussed that it would also be interesting to find a bundle by the name of the class only. For example,
BundleContext should be able to find the
osgi.core, or most framework bundles. This is a lot less straightforward to implement than packages. After all, the existing repositories already contained the capabilities for each package; There is no such capability for the class names to not make the capabilities too large.
There is a performance issue to watch here. Some workspace repositories are very large and downloading all JARs can be prohibitive. One huge advantage of the OSGi XML format is that using lightweight repositories can be quite cheap. We should be careful to minimize the amount of data.
The solution was to reduce the data is by using Bloom filters. A Bloom filter is a set of hashes. A value is likely present if its hash is in the set, if not it is guaranteed absent.
Most often the set of hashes is kept as a bitmap for fast in-memory access. However, depending on the density, you can also store the hashes as numbers in a set.
Bloom filters are an imperfect, but very cheap way, to find out the presence of a value. In this case, the value is the class name without the package name. For example, we use the hash of
BundleContext in the
org.osgi.framework package. The hash code used is the standard Java String
hashCode, this code is consistent between different JVM’s.
Since the set of class names in an exported package are not that large, and a hash is typically quite small (it is an
int), we can add these hashes to the package capability as an attribute. Attributes are not limited to strings, they can be of the following types:
Version, and lists of these. I opted to use the
The trick is, of course, to get these hashes into the repositories. In Bndtools we have a class
ResourceBuilder that is used by bnd whenever a bundle must become a Resource. I extended this class to add these class name hashes automatically. Since this class is probably the most widely used source of OSGi metadata, this will become widespread quickly. Fortunately, several repository types in Bndtools always index so they directly support this. Among these Repository types is the very popular Maven Bnd Repository. This means that for most Bndtools users, this will work out of the box.
So take a step back. We were able to add a major function to Bndtools, a quick fix from a class name, by changing only a few parts. This was possible because the C-R model is generic. The quite extensive machinery that makes the C-R model so effective for both the OSGi Framework as well as the Bndtools IDE, is oblivious of what those capabilities and requirements mean. By providing a flexible and extendable data model, new applications can be added without having to change anything in the core.
The C-R model is amazingly powerful and it never ceases to amaze me what you can achieve with very little effort. At a customer, with hundreds of thousands of gateways, we used the C-R model to completely revamp their ad-hoc deployment and development; this worked very well. Quite surprising how many things you find when you start catching errors early. Sadly, it is not much loved because I think that developers do not recognize it.
If you got interested, you might want to read a paper Tim Verbelen, Ghent University, and I recently wrote about using the C-R model in machine learning.
I hope I piqued your interest … You can get started with Bndtools on the workspace page. The 5.0 version contains the previous package search function. To use the experimental class name find feature go to the installation page Update Site section to install the current snapshot.