Bundling third party dependencies in ServiceMix 4

I'd like to talk a bit about third party dependencies in ServiceMix 4.

ServiceMix 4 is based on OSGi and when deploying applications to it, you have two choices:
  • use the JBI packaging
  • use the OSGi packaging

The first solution is a good thing if you want to abide by the JBI specification completely or if you want to use non OSGi aware components. However, you'll come into the known limitations of the JBI packaging with respect to classloaders: the JBI specification is quite limited in this area.
The second solution is more powerful as, in addition to being able to leverage the OSGi classloader mechanisms, you'll also be able to access the OSGi registry, thus registering or retrieving services in the registry.

However, when using the OSGi packaging, you need to deal with third party dependencies. OSGi is becoming more and more popular, so more and more projects are now distributing the jars as native OSGi bundles. But not all have converted to OSGi yet. And of course, you also need to transform your own jars into OSGi bundles.

Costin Leau has covered most of the aspects of creating OSGi bundles in his blog post. But there are a few tweaks that I want to talk about.

When repackaging a library as an OSGi bundle, one as to take care about package imports. I had a question recently about a problem when repackaging c3p0. This library is a JDBC connection pool, so it needs the class for the JDBC driver to be available in its classpath. A simplistic way to handle the problem is to force an optional import of the package containing the driver you use. This would be something like:
 Import-Package: *, com.mysql.jdbc;resolution:=optional

The drawback is that you tie your mysql bundle to the driver you use, which will break things if you want to switch to another database.
OSGi has a solution for such things which is called Dynamic Imports. This is needed when a library uses the Class.forName() method to load classes dynamically, such as the c3p0 library. The big difference between static imports and dynamic imports is that dynamic imports are resolved ... dynamically. This means that when the Class.forName() method is called, the OSGi framework will look for the requested package and wire it to your bundle at runtime. The OSGi headers would look like:
 Import-Package: *
DynamicImport-Package: *

But this feature must be use with caution, and only when possible to avoid having unwanted wiring between bundles.

A second use case if the legal problems encountered while dealing with proprietary software of non liberal open source licenses. IANAL, so take the following with the appropriate caution and check with your legal department before doing anything. Back to the point: proprietary software often forbid any modification to the jars. In such a case, the only alternative is to embed the jar in an OSGi bundle. Basically, when you repackage a library into an OSGi bundle, you extract the content of the jar, add some OSGi headers to the manifest, and rebuild the jar. There is an alternative though, which is to create a bundle and include the full jar inside it. The bnd tool and felix bundle plugin for maven (which uses bnd) both support that and you end up with using the Bundle-Classpath header:
 Import-Package: *
Bundle-Classpath: .,bin/mysql-connector-java-5.1.6.jar

The only drawback is that the bundle jar can not be used anymore in a non-OSGi environment.

Before bundling a jar, check the existing bundle repositories (the ServiceMix one or the SpringSource one) for an existing bundle. And if you write one for an open source library, feel free to submit a patch if you want ServiceMix to host it...

Happy bundling!

Comments

Anonymous said…
It would be very useful having in SMX the bundles for the most common databases (mysql, postgres,oracle?,freedts,..)...

Thanks
http://www.redaelli.org/mateo/
Thomas Gill said…
How do you install Oracle jdbc driver jar in ServiceMix/Fuse. Do you have to modify the manifest. I tried putting in lib and also osgi install. Did not work
Guillaume Nodet said…
Thomas,
I think the easiest way to install such a non OSGi driver is to use the wrap pax url handler which is already available in ServiceMix.

Popular posts from this blog

SSH Server in Java

ServiceMix Kernel is a small container based on OSGi. The latest release allows external clients to connect to it and issue commands using a simple protocol implemented on top of TCP or SSL. However, this remoting protocol has some drawbacks as the internals makes it unable to do another remote login from a remote session. In addition to that, completion and history do not really work great. So I've been thinking about using the SSH protocol, which is widely used, secured, with tons of different clients available. Unfortunately, no SSH server is available in Java. Over the past weeks, I've been working on implementing this SSH server, based on the IEFT specifications, the JSch SSH client library, and the OpenSSH server source code. The server itself is based on Apache Mina which is a great framework for using NIO. The project is available at http://code.google.com/p/sshd/ and although there are lots of limitations right now, the basics of the SSH protocol work. I plan t...

Apache Karaf

ApacheCon was really interesting this year! Recently, a lot of people have expressed a real interest in ServiceMix Kernel , our generic OSGi distribution for server side applications. We've been discussing moving this subproject into Apache Felix for several reasons: raise the visibility and awareness on ServiceMix Kernel attract a broader community Several Apache projects are planning to use ServiceMix Kernel as their container: this includes Apache James , Apache Directory and Apache ActiveMQ . The Apache Sling community is also willing to contribute to this effort along with some other groups like the OPS4J project. During this discussion, a name as been proposed by Jamie Goodyear: Apache Karaf . A carafe is a small container used for serving wine and other drinks (http://en.wikipedia.org/wiki/Carafe). In similarity to the name the Kernel allows applications to be more easily handled, and improves their characteristics (much like a bottle of wine left to breath in a dec...

Camel Endpoint DSL

Camel Endpoint DSL One of the new features of Camel 3.0  is an Endpoint DSL.  This new API aims to provide a type safe replacement for the URLs that are used in Camel to designate the consumer or producer endpoints.  These URLs provide 3 things: the scheme of the URL identifies the component to use, a unique name or id for the endpoint, and a set of parameters to customize the endpoint behavior. Here is an example of an FTP consumer endpoint definition: from( "ftp://foo@myserver?password=secret& recursive=true& ftpClient.dataTimeout=30000& ftpClientConfig.serverLanguageCode=fr" ) .to( "bean:doSomething" ); There are several drawbacks with such constructs : no type safety, bad readability and no simple completion. So we now use the meta model, which is currently extracted from the source using an annotation processor and written in various JSON files, to generate a fluent DSL for each endpoint.  The same...