Table of Contents

How to Include Third-Party Jars in Your Component

The process of including third-party JARs into your bundle is probably the most difficult and tricky part of creating new OSGi bundles.

The issue is that OSGi likes to know all of the java packages (note: packages, not classes) that your bundle requires, as well as all of the java packages that your bundle produces.

There is an automatic tool which scans through all of your code looking for packages that it requires (including requirements of all of your embedded JARs). This tool is the Felix Maven Bundle Plugin (BND) the documentation of which can be found here.

The maven-bundle-plugin does a lot of useful things (creates the manifest, copies JARs, copies classes, constructs the JAR, etc.), so it's an essential part of the build process.

The problem is that the plug-in will return errors whenever there appears to be a mismatch - i.e. a package required by your code which is not imported. This is, unfortunately, a very common occurrence because many programmers are very lazy about their “import” statements and the code included in their distributions. The upshot of all this is that the plugin will often say “your package needs this” when, in fact, it doesn't (primarily because it is unreachable code).

How do you know that it is safe to ignore these “improperly required” packages? Basically, if your component passes its unit tests, then you are guaranteed to not need any of the additional packages stated by the bundle program.

Preparations

First check the following in your project's “pom.xml” file:

  1. The “maven-bundle-plugin” plugin is listed in your pom.xml as one of the plug-ins in the <build> section of your pom.xml file.
  2. That the plugin/configuration/instructions section of your maven-bundle-plugin contains sections for Bundle-Activator, Private-Package, and Import-Package.
  3. Make sure it says <packaging>bundle</packaging>. This goes after the <artifactId> tag.

Your Third-Party JARs Should be Specified as Maven Dependencies

Your third-party JARs should be specified as dependencies of your project in the “dependency” section of your Maven pom.xml file. Eclipse actually provides quite a nice editor for specifying dependencies in a pom.xml file. The scope for all dependent JARs must be “compile” and cannot be “provided”.

This means, of course, that you will need to know the “groupId” and the “artifactId” for all of your third-party JARs. This information can usually be located by browsing your third-party JAR's web site, or one of the public repository centers:

However, if it is impossible to locate a maven repository which contains your third-party JAR, then you will need to load the JAR into your local repository manually. This can be done with a Maven command, for example:

mvn install:install-file -DgroupId={JAR's group-id} -DartifactId={JAR's artifact-id} -Dversion={JAR's version number} -Dfile={filename/location of the JAR to load} -DgeneratePom=true -Dpackaging=JAR

For example:

mvn install:install-file -DgroupId=javax.transaction -DartifactId=jta -Dversion=1.0.1B -Dfile=jta-1.0.1B.JAR -DgeneratePom=true -Dpackaging=JAR

And then make sure that the JAR's groupId and artifactId (and version) are specified as a dependency in your pom.xml file.

If the Third Party JAR Is Not in a Public Repository

You can download the third-party JAR from the owner's website, and then install it into the a repository. This is done using the following command:

mvn deploy:deploy-file -DgroupId={GROUPID} -DartifactId={ARTIFACTID} -Dversion={VERSIONNUM} -Dpackaging=JAR -Dfile={PATH-TO-JAR-FILE} -DrepositoryId=stPublic -Durl=http://repository.giraffplus.com/artifacts/public/

This makes building our components which depend on these third-party JAR files easier to build.

For example, if I added the TEST libraries to our repository using the following:

mvn deploy:deploy-file -DgroupId=test -DartifactId=test -Dversion=1.0 -Dpackaging=JAR -Dfile=test-1.0.JAR -DrepositoryId=stPublic -Durl=http://epository.giraffplus.com/artifacts/public/

anyone building the application that need it will no longer have to manually install the TEST libraries onto their own local repository. Instead, Maven will automatically download it from the GiraffPlus repository.

Creating the Bundle

Now we're ready to try and create the bundle. Note that it is almost guaranteed to return errors which will need to be corrected. Do not fret.

Run the Maven command (with the working directory set to your component's directory) to create your bundle:

mvn clean package

NOTE: Make sure you see the following in your output:

[INFO] [bundle:bundle]

If not, this means that your <packaging> is not correct. See “preparations” above.

To build without running the unit tests (typically much faster):

mvn -Dmaven.test.skip=true clean package

Embedding Dependencies

If you get the following error, you will need to go through the following procedure to include your third-party JARs into your bundle:

[ERROR] Error building bundle org.giraffplus:test-component:bundle:0.0.1-SNAPSHOT : Unresolved references to...

This process can be time-consuming and frustrating, so be warned.

1. Embed dependencies of the JARs which are specified in your POM as dependencies.

For example:

<Embed-Dependency>test</Embed-Dependency>
<Embed-Transitive>true</Embed-Transitive> 

In the above example, “test” is the artifact name of the dependency that I want to embed. The above should be added to the plugin/configuration/instructions section of the maven-bundle-plugin in your project's pom.xml file. If you have multiple dependencies to include, specify them all separated by commas. If you have lots and lots of dependencies, you could say “*” for Embed-Dependency. For example:

<Embed-Dependency>*</Embed-Dependency>
<Embed-Transitive>true</Embed-Transitive> 

2. Run the "mvn clean package" command again.

3. Still errors.

Once you've done this, all dependencies are included. However, there will still likely be many java packages which can not be found by the maven bundle plug-in.

If maven didn't include the JARs for these packages automatically, then clearly these packages are not required for actual execution of the software. What happens is that these packages represent code in your dependent libraries which import other packages that are never used (spurious imports or unreachable code).

Unfortunately, the maven bundle plug-in doesn't know the difference. It believes that this code is required, and so it prints an ERROR.

The only way around this is to list these packages in the <Import-Package> directive, with a bang (i.e. “!”) before them. You can use wildcards to eliminate whole groups of them.

For example:

 <Import-Package>com.searchtechnologies.aspire.services,org.osgi.framework,org.w3c.dom,
          org.osgi.service.http,org.osgi.service.cm,javax.*,org.w3c.dom,org.w3c.dom.*,
          org.osgi.util.tracker,org.xml.*,org.osgi.service.log,
     !android.*,!com.sun.*,!dalvik.*,!junit.*,!org.apache.avalon.*,!org.apache.log,
     !org.apache.lucene.*,!org.apache.tools.*,!org.apache.xml.resolver*,
     !org.apache.xmlbeans.impl.*,!org.gjt.*,!org.jaxen.*,!org.relaxng.*,!sun.io</Import-Package>

Notice that the packages listed at the beginning of <Import-Package> are ones that I actually need. It's the ones at the end (with the “!”) which are called out by the 3rd party libraries, but which (according to the Maven dependency hierarchy) are never actually needed for normal operations.

Go through all of the unresolved references and add each one to the end of the Import-Package statement with the “!” character before it. Notice that you can lump some of them together with wildcards if that's helpful.

After some time, and lots of executing of the “mvn” command, eventually should have a complete Import-Package statement and your bundle will be created.

Verifying Your Bundle

Open up the bundle .JAR file and verify the following:

Problems You May Discover Running Your Bundle in Apache Felix

First, try running your bundle in the application.

If your bundle installs but does not start, try installing the bundle by hand within the Felix console. For example:

  -> install file:bundles/test/...
  ...
  -> start 12
  org.osgi.framework.BundleException: Unresolved constraint in bundle 12: package; (package=javax.jms)

Notice the unresolved constraint above. This is something which will need to be added to your POM as an imported package. Change your pom.xml file, add the package to the Import-Package statement, re-build your bundle JAR, and then try again.

Other Hints and Tricks

If you make changes to the framework, you'll likely need to re-run “mvn install” on the framework before those changes will be visible in your project.

You can find more information here:

http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html

Also, check out the BND documentation page for additional options (Maven bundle plugin is based on BND, so the syntax for specifying imports/exports is the same):

http://www.aqute.biz/Bnd/Bnd

Specifically, look at the “Import Package” section:

http://www.aqute.biz/Bnd/Format#import-package

APPENDIX: Packages provided by the System Bundle

Note that you will need to import these with &lt;Import-Package&gt; if you use them, or if any of your 3rd party JARs use them.

javax.accessibility,version=1.6.0
javax.activation,version=1.6.0
javax.activity,version=1.6.0
javax.annotation,version=1.6.0
javax.annotation.processing,version=1.6.0
javax.crypto,version=1.6.0
javax.crypto.interfaces,version=1.6.0
javax.crypto.spec,version=1.6.0
javax.imageio,version=1.6.0
javax.imageio.event,version=1.6.0
javax.imageio.metadata,version=1.6.0
javax.imageio.plugins.bmp,version=1.6.0
javax.imageio.plugins.jpeg,version=1.6.0
javax.imageio.spi,version=1.6.0
javax.imageio.stream,version=1.6.0
javax.jws,version=1.6.0
javax.jws.soap,version=1.6.0
javax.lang.model,version=1.6.0
javax.lang.model.element,version=1.6.0
javax.lang.model.type,version=1.6.0
javax.lang.model.util,version=1.6.0
javax.management,version=1.6.0
javax.management.loading,version=1.6.0
javax.management.modelmbean,version=1.6.0
javax.management.monitor,version=1.6.0
javax.management.openmbean,version=1.6.0
javax.management.relation,version=1.6.0
javax.management.remote,version=1.6.0
javax.management.remote.rmi,version=1.6.0
javax.management.timer,version=1.6.0
javax.naming,version=1.6.0
javax.naming.directory,version=1.6.0
javax.naming.event,version=1.6.0
javax.naming.ldap,version=1.6.0
javax.naming.spi,version=1.6.0
javax.net,version=1.6.0
javax.net.ssl,version=1.6.0
javax.print,version=1.6.0
javax.print.attribute,version=1.6.0
javax.print.attribute.standard,version=1.6.0
javax.print.event,version=1.6.0
javax.rmi,version=1.6.0
javax.rmi.CORBA,version=1.6.0
javax.rmi.ssl,version=1.6.0
javax.script,version=1.6.0
javax.security.auth,version=1.6.0
javax.security.auth.callback,version=1.6.0
javax.security.auth.kerberos,version=1.6.0
javax.security.auth.login,version=1.6.0
javax.security.auth.spi,version=1.6.0
javax.security.auth.x500,version=1.6.0
javax.security.cert,version=1.6.0
javax.security.sasl,version=1.6.0
javax.sound.midi,version=1.6.0
javax.sound.midi.spi,version=1.6.0
javax.sound.sampled,version=1.6.0
javax.sound.sampled.spi,version=1.6.0
javax.sql,version=1.6.0
javax.sql.rowset,version=1.6.0
javax.sql.rowset.serial,version=1.6.0
javax.sql.rowset.spi,version=1.6.0
javax.swing,version=1.6.0
javax.swing.border,version=1.6.0
javax.swing.colorchooser,version=1.6.0
javax.swing.event,version=1.6.0
javax.swing.filechooser,version=1.6.0
javax.swing.plaf,version=1.6.0
javax.swing.plaf.basic,version=1.6.0
javax.swing.plaf.metal,version=1.6.0
javax.swing.plaf.multi,version=1.6.0
javax.swing.plaf.synth,version=1.6.0
javax.swing.table,version=1.6.0
javax.swing.text,version=1.6.0
javax.swing.text.html,version=1.6.0
javax.swing.text.html.parser,version=1.6.0
javax.swing.text.rtf,version=1.6.0
javax.swing.tree,version=1.6.0
javax.swing.undo,version=1.6.0
javax.tools,version=1.6.0
javax.transaction,version=1.6.0
javax.transaction.xa,version=1.6.0
javax.xml,version=1.6.0
javax.xml.bind,version=1.6.0
javax.xml.bind.annotation,version=1.6.0
javax.xml.bind.annotation.adapters,version=1.6.0
javax.xml.bind.attachment,version=1.6.0
javax.xml.bind.helpers,version=1.6.0
javax.xml.bind.util,version=1.6.0
javax.xml.crypto,version=1.6.0
javax.xml.crypto.dom,version=1.6.0
javax.xml.crypto.dsig,version=1.6.0
javax.xml.crypto.dsig.dom,version=1.6.0
javax.xml.crypto.dsig.keyinfo,version=1.6.0
javax.xml.crypto.dsig.spec,version=1.6.0
javax.xml.datatype,version=1.6.0
javax.xml.namespace,version=1.6.0
javax.xml.parsers,version=1.6.0
javax.xml.soap,version=1.6.0
javax.xml.stream,version=1.6.0
javax.xml.stream.events,version=1.6.0
javax.xml.stream.util,version=1.6.0
javax.xml.transform,version=1.6.0
javax.xml.transform.dom,version=1.6.0
javax.xml.transform.sax,version=1.6.0
javax.xml.transform.stax,version=1.6.0
javax.xml.transform.stream,version=1.6.0
javax.xml.validation,version=1.6.0
javax.xml.ws,version=1.6.0
javax.xml.ws.handler,version=1.6.0
javax.xml.ws.handler.soap,version=1.6.0
javax.xml.ws.http,version=1.6.0
javax.xml.ws.soap,version=1.6.0
javax.xml.ws.spi,version=1.6.0
javax.xml.xpath,version=1.6.0
org.ietf.jgss,version=1.6.0
org.omg.CORBA,version=1.6.0
org.omg.CORBA.DynAnyPackage,version=1.6.0
org.omg.CORBA.ORBPackage,version=1.6.0
org.omg.CORBA.TypeCodePackage,version=1.6.0
org.omg.CORBA.portable,version=1.6.0
org.omg.CORBA_2_3,version=1.6.0
org.omg.CORBA_2_3.portable,version=1.6.0
org.omg.CosNaming,version=1.6.0
org.omg.CosNaming.NamingContextExtPackage,version=1.6.0
org.omg.CosNaming.NamingContextPackage,version=1.6.0
org.omg.Dynamic,version=1.6.0
org.omg.DynamicAny,version=1.6.0
org.omg.DynamicAny.DynAnyFactoryPackage,version=1.6.0
org.omg.DynamicAny.DynAnyPackage,version=1.6.0
org.omg.IOP,version=1.6.0
org.omg.IOP.CodecFactoryPackage,version=1.6.0
org.omg.IOP.CodecPackage,version=1.6.0
org.omg.Messaging,version=1.6.0
org.omg.PortableInterceptor,version=1.6.0
org.omg.PortableInterceptor.ORBInitInfoPackage,version=1.6.0
org.omg.PortableServer,version=1.6.0
org.omg.PortableServer.CurrentPackage,version=1.6.0
org.omg.PortableServer.POAManagerPackage,version=1.6.0
org.omg.PortableServer.POAPackage,version=1.6.0
org.omg.PortableServer.ServantLocatorPackage,version=1.6.0
org.omg.PortableServer.portable,version=1.6.0
org.omg.SendingContext,version=1.6.0
org.omg.stub.java.rmi,version=1.6.0
org.omg.stub.javax.management.remote.rmi,version=1.6.0
org.osgi.framework,version=1.4.0
org.osgi.framework.hooks.service,version=1.4.0
org.osgi.service.packageadmin,version=1.2.0
org.osgi.service.startlevel,version=1.1.0
org.osgi.service.url,version=1.0.0
org.osgi.util.tracker,version=1.3.3
org.w3c.dom,version=1.6.0
org.w3c.dom.bootstrap,version=1.6.0
org.w3c.dom.css,version=1.6.0
org.w3c.dom.events,version=1.6.0
org.w3c.dom.html,version=1.6.0
org.w3c.dom.ls,version=1.6.0
org.w3c.dom.ranges,version=1.6.0
org.w3c.dom.stylesheets,version=1.6.0
org.w3c.dom.traversal,version=1.6.0
org.w3c.dom.views,version=1.6.0
org.w3c.dom.xpath,version=1.6.0
org.xml.sax,version=1.6.0
org.xml.sax.ext,version=1.6.0
org.xml.sax.helpers,version=1.6.0