OSGi: What's the difference between Import-Package/Export-Package and Require-Capability/Provide Capability?

BramCoding :

I am currently working with the OSGi framework but I have a question about some concepts that are not 100% clear to me. I have searching for it myself but I could not find a decent answer that clearly explains it.

In a bundle his manifest header 2 of the headers that get used are Import-Package and Export-Package. The names speak for themselves: a demand for a certain package and a offering of a certain package. In order to get that package (or give that package), the complete bundle must be installed in the framework where the Import is needed.

But then we get to the part of the Requirements-Capabilities model. This can practically do the same as the Import-Package and Export-Package headers. There are also headers for this Requirements-Capability model: Require-Capability and Provide-Capability. Again these stand for demanding something and for providing something.

I know that Requirements-Capability model was only introduced later on in the development of the OSGi specification(s). Can't exactly find at what year and version it was presented.

But,

  • Why has this been added to the specification? I don't see what it has more to offer than what the Import/Export-package already offered: creating dependencies on other packages/bundles?

  • Could someone give me a better understanding in the difference (pro's and con's) between these 2 sets of concepts?

Peter Kriens :

When we started with OSGi in 1998 we had some clear requirements but of course, no clear view of what would come out of it. So we started to explicitly model the requirements and capabilities we had: packages. The Import-Package requires a capability and that capability is provided by an Export-Package.

In 2003 Eclipse wanted to start using OSGi but they need a facility to require another bundle, they did not like the idea of exporting and importing all their packages. Actually, at that time they failed to see the benefit of packages. To satisfy them we added Require-Bundle and Fragment-Host (another one of their desires that turned out not to be so good.)

After we specified OSGi 4.x with these extensions we starting thinking about a repository, Richard had developed the Oscar Bundle Repository. Analyzing the situation with the new headers in OSGi 4.0 it became clear that the implementation of Import-Package looked a lot like Require-Bundle, and even resembled Fragment-Host processing.

In 2006 Richard S. Hall and I wrote RFC 112 proposing a more generic model that captured the semantics of the existing dependency model but was not specific for each type of requirement. I.e. for the Framework resolver the Import-Package and Require-Bundle only differ in their namespace. Thinking of Import-Package as a generic requirement and Export-Package as a generic capability made the repository model extremely simple. Even better, it was extendable since we could always add more namespaces. This made the resolver completely independent of the actual namespaces used.

After some very heated discussions, the OSGi Core Platform Expert Group decided to accept the basic idea and developed the Requirements and Capabilities specifications. Although this was originally a model for the repository, it turned out to be highly useful for the Framework itself. We decided therefore to adapt the existing specifications to this model. OSGi 4.3 internally models the Import-Package, Export-Package, Require-Bundle, etc. as requirements and capabilities of a resource (the bundle). For backward compatibility, we kept the existing headers but they are internally translated to requirements and capabilities.

Then finally to the answer to your question. Over time the OSGi specifications added more and more namespaces. A namespace is like a type for a Requirement and a Capability. It defines the semantics of a set of properties of a Capability in that namespace. A Requirement is a filter expression that is asserted on those properties. A Resource has a set of Capabilities that are provided to the runtime when all its Requirements are satisfied. It is the task of the Resolver to find a set of resources that are all satisfied with each other's capabilities and capabilities provided by the runtime.

For example, we added the osgi.ee namespace that defines exactly on what VM's the bundle can run. We added the osgi.extender namespace that models a dependency on an external program like the Service Component Runtime (SCR). Most SCR components do not require any package from the SCR itself, we tried hard to make them as independent as possible. However, a SCR component will sit useless unless some bundle in the runtime provides the SCR functionality. Notice that this cannot use Require-Bundle because there are multiple implementations of SCR. I think there are about 20 namespaces. Each namespace is defined in a Namespace class.

This model has given the OSGi a number of advantages:

  • Cohesion Although the specification has added many namespaces the resolver implementations never had to change since they worked on the generic model.
  • Fine-Grained OSGi bundles are unique in how they describe their dependencies in a very fine-grained way. All module systems I know tend to use the simple module-to-module dependency that does not allow substitution.
  • Flexible Since the Framework reifies the dependencies between bundles it is possible in runtime to leverage these dependencies. For example, in OSGi enRoute I linked a bundle to its web page traversing these runtime wirings.

I personally consider the Requirements and Capability model of OSGi one of its best kept secrets. As far as I can see it could be used in a lot of areas to improve many development projects into the world of software engineering.

The only disappointing part in this question is that I thought we'd described this pretty well in the Core specification? :-)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=124268&siteId=1