Google Plus Logo
Twitter Logo
Facebook Logo

Bundle non-OSGi dependencies with Maven

When we work with OSGi, a problem we always have is how to work with dependencies non OSGi Ready.

This is not a really great problem because there we can work with. There is essentially two solutions :

  • Embed the JAR files within the bundle. That is to say putting the JAR file into the bundle JAR and reference it in the Manifest
  • Wrap the JAR files with an OSGi Manifest. Namely, transform the JAR into an OSGi bundle.

Personnaly, i doesn't like the first solution, because for me, having a jar into a jar sounds really weird and bad and i prefer to have real OSGi Bundle. With wrapping, if i need this library in an other bundle, i doesn't have to do anything.

But, yes there is a but, wrapping a jar is much complicated than embedding. Because, we much transform the JAR into a real OSGi Bundle. That is to say that we much create a new JAR with a Manifest, importing all the needed packages, exporting all the necessary packages, computing the names and version, ...

If we must do that by hand, that could be really long and hard to do.

We can do that in a simple way using Maven 2 and the maven-bundle-plugin that can generate an OSGi jar embedding the other using the BND tools. With some configurations, we can simply create a totally valid OSGi Bundle. To make several bundles  easily, i created a simple parent pom (i take the first sources from Spring Blog) and all the modules of this parent project will be simple project to wrap a dependency.

Here is the parent pom i use :

<?xml version="1.0" encoding="UTF-8"?>
<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>org.jtheque</groupId>
    <artifactId>jtheque-osgi-wrap</artifactId>
    <name>jtheque-osgi-wrap</name>
    <packaging>pom</packaging>
    <version>1.0</version>

    <modules>
        <!-- Modules -->
    </modules>

    <properties>
        <export.packages>${export.package}*;version=${unpack.version}</export.packages>
        <import.packages>*</import.packages>
        <private.packages>!*</private.packages>
        <symbolic.name>${pom.groupId}.${pom.artifactId}</symbolic.name>
        <embed-dep>*;scope=compile;type=!pom;inline=true</embed-dep>
        <unpack-bundle>false</unpack-bundle>
    </properties>

    <build>
        <directory>${env.BUILD_HOME}/dependencies/${symbolic.name}</directory>

        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <version>1.2.0</version>
                <configuration>
                    <unpackBundle>${unpack.bundle}</unpackBundle>
                    <instructions>
                        <Bundle-Name>${artifactId}</Bundle-Name>
                        <Bundle-SymbolicName>${symbolic.name}</Bundle-SymbolicName>
                        <Bundle-Description>${pom.name}</Bundle-Description>
                        <Import-Package>${import.packages}</Import-Package>
                        <Private-Package>${private.packages}</Private-Package>
                        <Include-Resource>${include.resources}</Include-Resource>
                        <Embed-Dependency>${embed-dep}</Embed-Dependency>
                        <_exportcontents>${export.packages}</_exportcontents>
                    </instructions>
                </configuration>
                <extensions>true</extensions>
            </plugin>
        </plugins>
    </build>
</project>

That really simple, we use some properties to generify the process to have really simple modules.

Here is an example to wrap the substance look and feel library :

<?xml version="1.0" encoding="UTF-8"?>

<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/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>org.substance</groupId>
    <packaging>bundle</packaging>
    <artifactId>org.jtheque.substance</artifactId>
    <name>apple-extensions</name>
    <version>6.0.0</version>

    <parent>
        <artifactId>jtheque-osgi-wrap</artifactId>
        <groupId>org.jtheque</groupId>
        <version>1.0</version>
    </parent>

    <properties>
        <unpack.version>6.0.0</unpack.version>
        <export.package/>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.substance</groupId>
            <artifactId>substance</artifactId>
            <version>6.0</version>
        </dependency>
    </dependencies>
</project>

Like you can see, that's really simple and that generates a great OSGi Bundle. Here i didnt' specify any export package. Doing that all the packages are exported except the ones containing impl or internal.

Thats it :)

I hope that this post will be useful to some of you.

Comments

Comments powered by Disqus