Question

I'm packaging a library as an OSGi bundle using maven-bundle-plugin, which uses BND. I noticed BND generated a very long Export-Package list, mainly because it includes many packages that are exported by the library itself in the uses directive of other exported packages.

I (kind of) understand the uses directive. I presume in this case classes of other packages (listed under uses) are used in method signatures (therefore imported) by classes in the exported package.

In this sense, I have two questions:

  1. Is it really necessary to included packages that are exported by the same bundle in the uses directive of an exported package? Those packages are not going to be exported by any other bundle; therefore no split packages.
  2. Is this behaviour a sign that the package structure of the library is incorrectly defined? Several classes used by top level packages are often in sub-packages and vice-versa. This is a library being adapted to be an OSGi bundle. The package structure was not designed to be OSGi friendly.

Here's how most exported packages are listed in the MANIFEST

Export-Package: org.lib.annotation;version="10",org.lib.coverage;version="10";
uses:="javax.measure.unit, org.lib.annotation,org.lib.geometry,org.lib.ref,org.
lib.ref.operation,org.ref.util"

From all packages in above uses list, only javax.measure.unit is imported from another bundle.

maven-bundle-plugin configuration:

<plugin>
  <groupId>org.apache.felix</groupId>
  <artifactId>maven-bundle-plugin</artifactId>
  <version>2.4.0</version>
  <extensions>true</extensions>
  <configuration>
      <instructions>
          <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
          <Bundle-Version>${parsedVersion.osgiVersion}</Bundle-Version>
          <Export-Package>org.lib.*;version=${project.version}</Export-Package>
          <Import-Package>*</Import-Package>
          <_experiments>true</_experiments>
      </instructions>
  </configuration>
</plugin>
Was it helpful?

Solution

This appears to be correct, yes, although it's difficult to say for sure without more details of the code.

To answer your specific questions:

  1. Yes, it is absolutely necessary to do this, because you cannot know that the packages are never going to be exported by another bundle. For one thing, bnd doesn't know this because it only looks at one bundle at a time. More importantly, there will probably be future versions of this bundle, in which case you are going to get multiple exports of the same packages. The uses constraint is then essential to ensure that users of the packages cannot get hold of an inconsistent set of types.

    To illustrate this, suppose you were to modify a class in one package, and then pass an instance of that class as a parameter into an old version of a class in another package. That old class would not understand the object you had given it. Actually the JVM itself will not let this happen, you will get a ClassCastException or a LinkageError... the OSGi uses constraint just prevents us from getting this far.

  2. I wouldn't say the packages are incorrectly defined as such. They are perhaps not well defined. The large number of uses constraints indicates that the packages are highly coupled to each other and might benefit from some reorganising, i.e. moving tightly-coupled classes/interfaces into the same package, maybe merging some packages, etc. Also you don't really want circular dependencies between packages because that makes it difficult to factor out packages into separate modules. There is nothing OSGi-specific about this advice, incidentally.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top