OSGi Tutorial

nvisia is an award-winning software development partner driving competitive edge for clients.

There is a great OSGi for Beginners tutorial on TheServerSide. You’ve probably been hearing more and more about OSGi recently and if you haven’t had the changes to research it, you’re probably wondering what the heck it is. So here’s my take on it in a nutshell:

OSGi is like Linux RPM for Java applications today, and will probably be like apt-get tomorrow.

OSGi Today

If you’ve ever used a Red Hat or RPM based version of Linux, you are probably familiar with the situation where you want to install “target_application”, so you download the RPM and try to install it only to find out that you don’t have some library that it depends on installed. So you download that library and try to install it only to find out it depends on another library. And so on, and so on. It can sometimes be a nightmare. (Even Windows users may have encountered an example of this for .NET applications that assume the .NET framework has already been installed.)

That’s more or less what’s available in OSGi containers today, where instead of RPM files, there are OSGi Bundles, which are just jar files with special MANIFEST.MF entries. And the above tutorial does a tremendous job of walking through simple and then progressively more complicated examples (include source code). But here’s a quick excerpt of running and installing a module to an OSGi container (in this case Equinox):

Example: Equinox OSGi Console

$ java -jar org.eclipse.osgi_3.3.2.R33x_v20080105.jar -console
osgi> ss

Framework is launched.

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.3.2.R33x_v20080105

osgi> install file:///workspaces/osgi/tutorial/tutorialbundle.jar
Bundle id is 4

osgi> start 4
Apr 17, 2008 11:57:29 AM tutorial.TutorialActivator start
INFO: started
Apr 17, 2008 11:57:29 AM baselib.BaseService sayHello
INFO: Hello, world!

osgi> stop 4
Apr 17, 2008 1:29:25 PM tutorial.TutorialActivator stop
INFO: stopped.

osgi>

Notice that you simply give it a URL and it downloads it to the container. Then you just run the start command to actually activate it. The stop command to deactivate it, etc. Stop it, install a new version, and start it again without restarting the container, etc. It’s as simple as that. Well, until you consider dependencies…

In this case, it’s installing a bundle that doesn’t have dependencies, but if there were unresolved dependencies, it would complain when you issued the start command. So you can imagine that with complicated dependency graphs, things could quickly get out of hand.

Still, having this ability is MUCH simpler and more powerful than today’s JEE servers which generally each have their own custom way to deploy WAR or EAR files. Also, WAR/EAR files are forced in most cases to include all of their dependencies inside a single huge file, or even worse, rely on some things already being in the container’s classpath. Plus it’s cumbersome to reference resources from another WAR/EAR. All of which makes dealing with WAR/EAR files very clumbsy.

So even today, OSGi offers very nice features compared to JEE app servers. But the real power of this approach is where OSGi is headed tomorrow…

OSGi Tomorrow

If you’ve ever installed Ubuntu Linux, Debian, or other installations that have an “apt-get” like tool, then you know how amazingly elegant this approach is. Consider our RPM example of an application that depends on a library that depends on a library… Well, apt-get takes RPM one step further by not only verifying that dependencies are installed, but also automatically pulling down any missing dependencies from repositories and installing them as well. So with apt-get, to install an application along with all of it’s dependencies, you just run:

apt-get install your_application_name

And then you watch in amazement as apt-get traverses the dependency model, figures out what’s already installed on your machine, and automatically downloads and installs whatever is needed to run “your_application_name”.

Well, OSGi containers haven’t quite tackled the “pulling down the dependencies” problem yet (at least I haven’t seen one that does). But if you look around, you’ll start to notice that they are starting to create bundle repositories:

This is similar to the “RPM Repositories” using the Red Hat RPM analogy. So it’s only a matter of time before we see an “apt-get” type tool that takes advantage of these repositories to automatically install OSGi applications to a container (in fact, it looks like Felix’s repository is most of the way there).

So imagine a world where deploying Java code becomes a simple two step process. First, install your bundle(s) to a bundle repository (probably with a simple HTTP and/or command line interface). Next, request your operations team to install the bundle by running a single “install URL_OF_YOUR_APP” command that connects to the repository and pulls your application’s bundle, and all it’s dependencies into the server.

Toss in public OSGi Bundle Repositories, and you can install third party applications to your OSGi services just by running “install URL_OF_THIRD_PARTY_APP”. So now SaaS providers don’t need to necessarily require that they host the software. The could just give an id/password secured URL where you can install their bundles to your companies OSGi container (which might be another party).

Want to use “grid computing” for batch type applications easily? Just setup an OSGi enabled grid so that you put a work request on the grid, and it takes care of dispatching it to one of the machines on the grid, that machine uses OSGi to dynamically pull down the application bundles, fires off the request, returns the results, and either deletes the bundles or keeps them in a local cache for future requests. Try that with JEE servers.

And OSGi isn’t just limited to server side components. In fact, the most widely used OSGi based application is not server based at all. It’s the Eclipse IDE. Buried deep in the kernel of Eclipse is actually the Equinox OSGi engine, and that’s how the Eclipse plugin system works.

So where does Spring OSGi fit in?

You also might have heard about Spring’s OSGi dynamic module mechanism and be wondering what it is. Well, if you looked at the OSGi stuff, you saw that Bundle’s generally require defining and implementing a BundleActivator that implements this simple interface:

public interface BundleActivator {
    public void start(BundleContext context) throws java.lang.Exception;
    public void stop(BundleContext context) throws java.lang.Exception;
}

This basically allows your bundle to handle lifecycle events with the OSGi container, register listeners, lookup services from the BundleContext, etc.  It’s very similar to things like the JEE ServletContext, EJBContext, or even Spring’s ApplicationContext, except it’s much “slimmer”, leaving advanced functionality up to you the implementor.

Well, that’s extremely simple and flexible, but it means you might have to write a lot of infrastructure yourself for “real” applications to wire everything together (e.g. if you want to expose a Spring service as an OSGi service). And that’s where Spring OSGi comes in. It basically provides a set of bundles that make it easy to expose your Spring beans from your own bundles and use Spring beans from other bundles without having to write a bunch of activators. (It actually does this without needing a BundleActivator under the covers because the Spring Bundles essentially “pull” your services out of your bundles.)

Using Spring OSGi is relatively simple (though it does unfortunately mean XML configuration…). Here is an example Simple Service. So if you start with a normal Spring configuration:

Example: Normal non OSGi Spring applicationContext: simpleservice.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

  <!-- regular spring configuration file defining simple service
       bean. We've kept the osgi definitions in a separate
       configuration file so that this file can easily be used
       for testing outside of an OSGi environment -->

  <bean name="simpleService" class="org.springframework.osgi.samples.simpleservice.impl.MyServiceImpl" />

</beans>

To make this OSGi enabled, you just put this file in the META-INF/spring directory of your jar file that exposes whichever beans you want to export:

Spring OSGi Config File: META-INF/spring/simpleservice-osgi.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:osgi="http://www.springframework.org/schema/osgi"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                      http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">

  <!-- Export the simpleService bean (defined in a separate
       config file in this case) as an OSGi service -->

  <osgi:service id="simpleServiceOsgi" ref="simpleService"
    interface="org.springframework.osgi.samples.simpleservice.MyService" />

</beans>

And then add these entries to your MANIFEST.MF:

Bundle-Version: 1.0
Bundle-SymbolicName: org.springframework.osgi.samples.simpleservice
Bundle-Name: Simple-Service-Sample
Bundle-Vendor: Spring Framework
Export-Package: org.springframework.osgi.samples.simpleservice
Bundle-ManifestVersion: 2

Now create a jar file with those files and your class files and you have a Spring OSGi bundle.

More Info

TLDR Version

OSGi is cool, you should look at it. 

Related Articles