Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I share non-OSGi libraries between bundles in an OSGi container?

Tags:

osgi

I came across this question when trying to share the Struts packages among multiple bundles inside an OSGi container. I wanted to avoid both duplicating dependencies inside the bundles and introducing a new dependency between them (by having one bundle export its internal dependencies for the other to share).

It turns out the answer is very easy if you happen to use Maven, and if you aren't, you can still use the Maven solution to learn how to create the same result with some other mechanism.

I found this approach useful multiple times during my project, so I'll post an example here.

like image 879
Hanno Fietz Avatar asked Aug 05 '09 19:08

Hanno Fietz


2 Answers

An additional path for those not so keen on maven, unable to port, or perfectly happy with ant/ivy

I've found the that easiest way to accomplish the stated task is to turn the non-OSGi library into an OSGi library by letting the manifest export every package and add on some approriate symbolic names / versions. I've been able to do this VERY easily with bnd via ant tasks (or even direct command line invocation). There are also repositories which contain "osgi-ified" version of many popular libraries. Some libraries (joda-time) are already shipping with correct OSGi manifests.

like image 160
basszero Avatar answered Sep 29 '22 12:09

basszero


Using Maven, it is very easy to create an OSGi bundle from any library. However, I think the same result can be created with other mechanisms, too. The Maven solution helped me understand how it works.

Creating the bundle is done by creating a project which has the library as a dependency and then packaging the project using the maven-bundle-plugin from the Apache Felix project and specifying the library packages with the Export-Package instruction. I used this to share Google Protocol Buffers between bundles inside an OSGi container:

<?xml version="1.0" encoding="UTF-8" ?>
<project>
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example.lib</groupId>
  <artifactId>protobuf-dist</artifactId>
  <version>2.1.0</version>
  <name>Google Protocol Buffers OSGi Distribution</name>
  <packaging>bundle</packaging>

  <dependencies>
    <dependency>
      <groupId>com.google.protobuf</groupId>
      <artifactId>protobuf-java</artifactId>
      <version>2.1.0</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <extensions>true</extensions>
        <configuration>
          <instructions>
            <Export-Package>com.google.protobuf</Export-Package>
          </instructions>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

If you want all transitive dependencies rolled into the bundle, too, use the bundleall goal of the plugin.

The plugin recognizes and honours existing OSGi manifests in the dependency.

You can also use the bundle plugin to just create the manifest and tell the jar packaging plugin (or the jar-with-dependencies builtin assembly) to use that manifest via the archive section. The plugin's page linked above shows how to do that.

like image 40
Hanno Fietz Avatar answered Sep 29 '22 13:09

Hanno Fietz