Java EE specs in OSGi

For ServiceMix 4, I've been working on making sure the Java EE specifications can be used in OSGi. The first step was to release OSGi versions of the various specifications by just adding the needed manifest entries to make them usable in OSGi. This was done inside the Geronimo project (on which I am a committer). This means that since a few months, most of the Java EE specification jars are available as OSGi bundles (you can grab those from maven 2 public repositories.

However, this is not always sufficient. Some of these specifications (mostly JAXB, SAAJ, JAX-WS and Stax) do not work well in OSGi. The mean reason is that the implementation is discovered using different mechanisms by the API. The most commonly used one is to find a file on the classpath in the META-INF/services directory and find the main entry point class of the implementation. Unfortunately, to make this work in OSGi, the client bundle (the one using one of these APIs) has to have the required file in its classpath, which means the inability to use one provided by the runtime in which the bundle is deployed and that it can not be switched without changing and re-compiling the bundle. Another way would be to add a Require-Bundle OSGi manifest so that the classpath of the implementation becomes part of the client bundle, but this also ties the client bundle to the implementation used.

The solution came to me after a chat with Dan Kulp: an OSGi specific discovery mechanism can be easily plugged into these spec jars. It consists in two small classes shared amongst these spec jars: an OSGi bundle activator and another class not tied to the OSGi api that maintain a list of available implementations. The final step if to rewrite the factory of those jars to look inside this map before performing the usual lookup.

This means that in a non OSGi environment, the jar behaves as usual, but when deployed into an OSGi runtime such as ServiceMix Kernel, the spec bundle will be able to locate dynamically the implementation to use. Therefore, the client bundle using the spec jar is now free of any requirements.

Comments

Ade said…
Hi Guillaume, thanks for posting this information up! Can you put in a quick link to an instance of where you've used Dan's technique in the ServiceMIx 4 code? I'd like to take a look in the code!

Thanks again.
Guillaume Nodet said…
Here is a modified factory that uses the two classes mentioned in the blog (which are links to the source code): Stax FactoryLocator.java

You can find pre-built binaries on the following repository.

Btw, I did not say it was Dan's technique, I just said I found this technique while chatting with Dan ;-)
Peter Kriens said…
Nice work! You are addressing a real problem for many of the factory patterns in Java wrt OSGi/strict modularity.

If you can change the spec JAR, then I think there is an even nicer possibility. Instead of prescanning the bundles, you can just also look in the OSGi service registry when the factory is used. An independent bundle will then do the scanning of the implementation jars and register implementations under their factory interface. This scanning bundle is shared between ALL different META-INF/services users. If all spec starts to scan all bundles, this might become expensive.

Also, this would allow implementation JARs to just register their implementations directly. Which opens all kind of nice possibilities like remote implementations, etc.

For interoperation, OSGi services beat class loader hacks anytime imho :-)

But anyway, I think this is great that these compatibility issues are addressed!

Kind regards,

Peter Kriens
Unknown said…
Peter,

I agree with you. This was discussed on the Geronimo list a while back, http://www.nabble.com/Geronimo-specs-jars-in-OSGi-td16726438s134.html.

There, Guillaume pointed out the added benefit of running multiple versions, e.g. jaxb 2.0 / 2.1, concurrently. The problem is with legacy code that would not have the requisite service registration code.

Good blog BTW.


Regards,
Alan
Anonymous said…
I think the best way of finding an implementation would be that the implementation factory simply registers itself as an osgi service. So we do not need any scanning. You simply look up which services offer the given spec (interface).

But I also think that in many cases it is perfectly in order that you simply package jars like an XML Parser with each bundle that needs it. I do not think that OSGI services have to be used for fine granular things. They are much more useful for modularizing your business aplication than for basic libs.
lg said…
I know that's been close to a year after you posted this in your blog, but there is a bug in the implementation that reads from "META-INF/services/*" as it is not able to handle comments in the file, should trim the input and move to the next line if (once these ops were executed) the line has a space or tab or is zero length.
Of course, the best would be to use ServiceLoader, but I do know that that is not an option as the requirement is just too high.
Guillaume Nodet said…
Thanks Lucas, I've raised a bug at SMX4-277 so it should be fixed in the next release.
Anonymous said…
you have a nice site.thanks for sharing this site. various kinds of ebooks are available here

http://feboook.blogspot.com

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...