OSGi Framework Extension as a Maven Project

In a previous post I explained how to extend an OSGi framework such that more classes are visible inside the framework from the outside world. This posting provided a very simple example to generate Framework Extension Bundle using a single file and calling the JAR tool from the command line. Here I will expand on this example by creating a Maven 2 project, which may be used in environments where Maven 2 is used for project builds.


As a first step, we need a Maven 2 project descriptor. To create this beast, we have to decide, how we build the project. I generally use the Apache Felix Maven Bundle Plugin to build my projects as OSGi bundles. This great plugin comes with support for Maven 2 packaging but also provides goals to call if the packaging functionality should not be used.

Before talking too much, let me just present a project descriptor, which I know works. After that I will explain why I did it, like I did it.


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ch.meschberger.sample</groupId>
<artifactId>ch.meschberger.sample.sysext</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>System Bundle Extension Sample</name>
<description>
This sample bundle extends the System Bundle export
list with the com.sun.image.codec.jpeg package such
that OSGi bundles may refer to Sun's JPEG implementation
without the OSGi framework itself to provide it in a
non-portable way.
</description>

<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<forceCreation>true
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
<manifestEntries>
<Export-Package>com.sun.image.codec.jpeg</Export-Package>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>1.4.3</version>
<executions>
<execution>
<id>bundle-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
<configuration>
<instructions>
<Bundle-Category>sample</Bundle-Category>
<Fragment-Host>system.bundle; extension:=framework</Fragment-Host>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>


First of all, I use plain old jar packaging. This allows me to have more control over the manifest generation. The problem is, that the Bundle plugin removes any packages from the Export-Package header of the generated manifest which happen to not be present in the final JAR file. This is very good in all cases except in our case, which may of course be considered a special case.

So we use jar packaging. Still I like the wonderful setup of the Bundle plugin when it comes to setting the required OSGi manifest headers. Fortunately, the Bundle plugin allows me to generate a manifest file as if the packaging would be bundle. This is the manifest goal.

Consequently, in the sample above, packaing is set to jar and the Bundle plugin is configured to generate a manifest file with the standard headers plus the Fragment-Host header required to mark the bundle as Framework Extension Bundle. For the Jar plugin to include the generated manifest we refer to it with the manifestFile configuration element, which requires us to add the explicit Jar plugin configuration not normally needed.

Now, we have the Bundle plugin generate the standard headers, we have the Jar plugin use that manifest but still we have two issues: First the Bundle plugin does not have the Export-Package header definition, which would be useless because it would be removed anyway. And second, the Jar plugin would complain, because it has nothing to package.

The first issue is fixed by adding a manifestEntries element to the Jar plugin configuration, which lists the missing Export-Package header.

The second issue is just as easy to solve as the first: We just force the creation of the JAR file by setting the forceCreation parameter.

Unfortunately the Bundle plugin does not create the destination folder into which the generated manifest file is placed. To have this folder created, just create an empty src/main/resources folder. This causes the destination to be created.

That's it. We now just have to use Maven to build that project and we are done and can use it.

Kommentare

Unknown hat gesagt…
Hi Felix,
sorry for reheating this old topic, but I'm trying to create a Fragment bundle to make com.sun.xml available for some data binding frameworks.

The fragment seems to work, but my Export-Package instruction is ignored.
I've used the same block as you listed above. I can also see my Export-Package entry in the "Manifest Headers" block in Felix, but the "Exported Packages" line shows up empty. Do you have any idea what the reason for that is?

Thanks so much!
fmeschbe hat gesagt…
Hi Matthias,

Thanks for your comment.

You say, that you see the entry in "Felix" ? Do you mean you look at it with the Apache Felix Web Console ? If so, the actual exports are not shown with the fragment bundle but with the host bundle, which is the system bundle in this case. Look at the exports of the system bundle and you will see the com.sun.xml exports.

You might also notice that your fragment bundle is in state RESOLVED which means that the fragment bundle is resolved and thus bound/wired with the system bundle.
Unknown hat gesagt…
Awesome, thanks. Yes, I meant the Felix console, and I noticed the packages getting added at the system bundle, just like you mentioned. Thanks again!

Beliebte Posts aus diesem Blog

OSGi Bundles require Classes from the Environment

LinkedHashMap's hidden (?) features

To embed or to inline ?