Embedding OSGi

From Protege Wiki
Revision as of 13:44, August 7, 2009 by Tredmond (talk | contribs) ((checkpoint save))

Jump to: navigation, search

Embedding OSGi inside a host application

There are many reasons to embed OSGi inside a host application:

  • the host application may have an extension mechanism that offers plugins no classloader protection from other extensions. This means that version problems can crop up between different extensions.
  • you have an existing OSGi implementation (e.g. Protege 4) which you want to run in a non-OSGi application setting.

There are several examples of OSGi showing up on the web. In particular, the Apache and Equinox groups have teamed up to devise a scheme that works with tomcat. Inside the OSGi environment, bundles see the standard OSGi servlet services which are transparently mapped to the underlying tomcat implementation. In response to a potential Protege developer who was having serious classloader problems I implemented the following demonstration of how a plugin for a host application can be implemented inside a embedded OSGi environment. The demonstration can be checked out and run by executing ant run.

In the HostApplication project, I simulated the host application (Host.java). This application finds and initializes a plugin (PluginImpl.java). I did not simulate the plugin mechanism inside the host application; the call to initialize the plugin is a simple call to a member of the PluginImpl class. The PluginImpl class then immediately starts up OSGi and the work of the plugin is then done in the OSGi environment.

EmbeddedOSGiArch.png

There are two main points that this example is intended to demonstrate. First, the OSGi application is able to call host services. To do this, when the plugin is initialized it saves a static copy of itself; the plugin is a singleton. This singleton becomes a reference point for the host application services that are needed in the OSGi environment. When the Activator is started in the OSGi implementation it can find the plugin by using the static PluginImpl.getInstance() method and then access and call host application services through that reference.

My example included a class loader conflict. There is a library (conflict.jar) used by the host application. The plugin for the host application needs to use the same routines from the library but needs to use a different version of the library (conflict-v2.jar). OSGi has many very flexible mechanisms to ensure that this isolation takes place and I will describe three different ways of isolating these libraries here.

First and most simple, the OSGi environment can be simply configured not to expose certain java packages supplied in the host application environment. The classes loaded by the host application environment's class loader are introduced to the OSGi environment through the system bundle. The set of packages are visible to the system bundle can be controlled by a configuration parameter called

     org.osgi.framework.system.packages

If you examine this declaration in the configuration file (look at the end of the fourth line) you will see that the conflicting library is explicitly included:

   org.osgi.framework.system.packages=...,org.example.conflict;version="1.0.0"

Note the version information, this will be important later. If this entry is removed then OSGi environment will not be able to load this class from the host application class loaders.

Second, bundles in the OSGi framework can control where and how they load their classes. For example , the manifest of one of the bundles running in the OSGi environment explicitly imports the library definitions in conflict. Note the first line from that manifest below:

Import-Package: org.example.conflict;version="2.0.0",
 org.example.host,
 org.example.plugin,
 org.osgi.framework,
 org.osgi.service.packageadmin
Bundle-ClassPath: .

If this import is removed, then