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

2

14

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?

Scampi answered 8/8, 2019 at 14:15 Comment(0)
C
19

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? :-)

Cyanic answered 8/8, 2019 at 15:8 Comment(3)
Thank you for clearing this up for me. This is exactly what I needed to fully understand the bigger picture. I have been reading parts of the core spec, but it was a lot of information to process and kind of lost a good overview. Thank you very much!Scampi
Regarding your disappointment: the big deficiency of the OSGi specs is the lack of exactly this kind of background information providing insights in intends, relationships of mechanisms due to historical developments etc. Positive examples of how to write easily readable specifications are many IETF RFCs such as this one. The introductory informal sections provide the reader with the background knowledge and examples to easily understand the formal sections. Trying to master OSGi, you get this kind information only through contributions like this one.Tend
I find that an unfair accusation since virtual everything stated in this piece is also in the OSGi that I linked, including lots of detailed pictures. All OSGi specs do start with background information. However, when we wrote it we were often accused that spec was so complicated because there were so many pages ... This stuff is complicated because it does not resemble familiar technology, not because it is not well documented or has some inherent complexity.Cyanic
M
7

The requirements and capabilities model is an extension of the Import/Export package model. Actually you can express a package import as a requirement and a package export as a capability.

Exporting / Importing packages allows for loose coupling. You export an API and the client imports it. This way the client only needs to know about the API so loose coupling is achieved.

At a later stage when you assemble the application out of bundles this loose coupling makes it difficult to automate the process.

If you just provide your client bundle to a resolver then it can only automatically find that you need the bundle that provides the API. If the implementation of the API is in a different bundle then the resolver has no way to know that you need it.

This is where requirements can help. Let's take the HTTP Whiteboard model. A bundle that want to publish a servlet needs to import the servlet api package but is also needs to express that it wants an implementation of the osgi http whiteboard.

This can be expressed by the requirement with namespace="osgi.implementation", name="osgi.http", version="1.1.0". As this is difficult to writer by hand there is annotation support for it.

@HttpWhiteboardServletPattern("/myservlet")
@Component(service = Servlet.class)
public class MyServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        resp.getWriter().println("Hello");
    }
}

The annotation @HttpWhiteboardServletPattern indirectly translates to the requirement above.

So when you build a bundle with this class it will import the servlet api package and also have a requirement for an http whiteboard implementation.

Now if you look at an implementation bundle like the felix http service you will see that it provide the capability for the whiteboard impl.

So if you have a OSGi repository with your bundle, the servlet API and the felix http service. Then the resolver can provide you with a complete application if you only give it your bundle.

Mountebank answered 8/8, 2019 at 15:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.