pragone.com
desarrollo, comunidad y monetización
agrégalo a del.icio.us

Welcome to OSGI land

Lately I’ve been able to play around with loads of new technologies/frameworks (new to me, of course). Among these I should probably mention: JGroups, Hazelcast, Neo4J… But the one I’m working more these days is OSGI.

I find OSGI particularly interesting because it solves one of the big drawbacks I saw to development in Java: deployment and management of component versioning (something that’s not a problem in scripting languages like PHP).

Yet, the learning curve in OSGI is particularly steep, I guess because it’s really becoming mainstream just recently, so I thought I would share what an OSGI novice has been able to learn about it in a week of development and a lot of reading (and I mean a LOT).

What is OSGI? And what is it for?

OSGI itself is “just” a set of specifications about how you can go about building highly modularized, dynamic applications. That’s why when you got to the OSGI Alliance web site the only download you’ll find are the specs. Take the chance and download them, store them somewhere (you’ll need them… just not now).

So if OSGI is “just” a compendium of specifications, how do I use it?

You need to get your hands on one of the implementations/frameworks. The base for every OSGI App is an OSGI Framework. Its on top of that you build your OSGI Application.

The main open source OSGI Frameworks are:

  • Eclipse Equinox: Is Eclipse Foundation’s version of it. It serves as the base for the popular Eclipse IDE, which is in itself an OSGI application.
  • Apache Felix: Is Apache Foundation’s implementation. It’s also very used by a lot of people.
  • Knoplerfish: Is another Open Source OSGI “service platform”. I think it’s quite used too, but I don’t think you can compare it’s community to any of the previous two.

Once you have one of these up and running you can start bulding/deploying bundles to it… but what is an OSGI bundle?

An OSGI bundle is the main building block of an OSGI application. To better understand it let’s dive deeper into how OSGI works.

How does OSGI works?

In Java, every Class is brought to live by a ClassLoader. Whenever you use a class (whether its one you’ve built or a java.lang one), a ClassLoader is used to fetch it from a directory or JAR in your ClassPath and load it in the JVM.

A ClassLoader can only load a class once, and that’s why when you modify a class in a stand alone app you need to restart the JVM for the changes to take effect. To overcome this “limitation”, the OSGI frameworks create several ClassLoaders (one per bundle), if you need to reload the classes in a bundle, the Framework disposes the ClassLoader associated with the bundle and creates a new one. OSGI Frameworks are not the only ones that use this mechanism, Servlet Containers (like Tomcat or Jetty) do the same, and that’s how you can reload servlets without taking down the web server.

This sounds like a great idea, but it must be handled with a lot of care. For example, when several ClassLoaders are used you could end up with more than one Singleton, and static variables of one class having different values depending on the ClassLoader you use. To make matters even worse, the Java 2 platform silently introduced the concept of Thread Context ClassLoader (A ClassLoader that’s associated with a Thread and not necessarily used to load the classes used in it).

A good article on this topic is: Find a way out of the ClassLoader maze.

But no tool is good or bad in itself, it all depends on how you use it, and this is where the Specs of OSGI come into play establishing a well defined way to manage ClassLoaders. And this is how bundles where born.

What is a bundle?

A bundle is the minimum unit of reloadable content, and “is comprised of Java classes and other resources, which together can provide functions to end users” (OSGI R4 Core Specs, page 27). In practice a bundle is a Jar file with a special META-INF/MANIFEST.MF. In this manifest, the bundle specifies what packages (as  in java.lang) it exposes to other bundles, what packages it needs from other bundles, an optional Activator class (to customize the life cycle of the bundle) and many other things.

But let’s create a simple bundle to understand this better. Our TestBundle is a Jar with this content:

  • META-INF/MANIFEST.MF
  • com/testbundle/Activator.class
  • com/testbundle/exported/Concatenator.class

The manifest contains the following:

Manifest-Version: 1.0
Bnd-LastModified = 1281229346082
Build-Jdk = 1.6.0_20
Built-By = pragone
Bundle-Activator = com.testbundle.Activator
Bundle-ManifestVersion = 2
Bundle-Name = testbundle
Bundle-SymbolicName = com.testbundle.testbundle
Bundle-Version = 0.0.1.SNAPSHOT
Created-By = Apache Maven Bundle Plugin
Export-Package = com.testbundle;uses:="org.osgi.framework",com.testbundle.exported
Import-Package = org.osgi.framework;version="1.2"
Tool = Bnd-0.0.357
The important parts here are:
  • Import-Package: indicates what packages this bundle needs to function, particularly org.osgi.framework is a package that is always  provided by the OSGI Framework
  • Export-Package. indicates what packages owned by this bundle are made available to other bundles. e.g. com.testbundle.exported
  • Bundle-Activator: the name of a class that implements org.osgi.framework.BundleActivator

The code of the activator is pretty simple:

package com.testbundle;

import org.osgi.framework.BundleActivator;

import org.osgi.framework.BundleContext;

public class Activator implements BundleActivator {

public void start(BundleContext context) throws Exception {

System.out.println(“Test Bundle starting”);

}

public void stop(BundleContext context) throws Exception {

System.out.println(“Test Bundle stopping”);

}

}

To “execute” this bundle do the following:

  1. Download an OSGI framework. Let’s use Equinox for this examples. Get org.eclipse.osgi_<version>.jar from  http://download.eclipse.org/equinox/ (I’m using version 3.6)
  2. Save the jar file to a new directory in, say, your desktop. Let’s assume this directory is called “<DESKTOP>/osgi”
  3. Download the test bundle source code from here. Untar/Unzip it to a location of your liking.
  4. In a terminal/command prompt, go to the folder where the content of the bundle was unpacked and type: “mvn package” (This assumes you have Maven installed. If you don’t… what are you waiting for, go get it)
  5. Once Maven has finished execution, a new folder called target will be created and in it a file called: testbundle-<VERSION>.jar, copy this file to the “<DESKTOP>/osgi” folder.
  6. Still on the terminal/command prompt go to the “<DESKTOP>/osgi” folder and type:
    java -jar org.eclipse.osgi_<version>.jar -console
  7. You should see a “osgi>” prompt. type:
    install file:testbundle-<VERSION>.jar
  8. Now type:
    start 1
  9. You should see a message indicating: “Test Bundle starting”

That’s it, you just got your first OSGI app up and running.

Now let’s try some Class updating magic. Go into the source code if the TestBundle and modify the source of Activator.java changing the two System.out.println from:

System.out.println("Test Bundle starting"); -- to --> System.out.println("New Test Bundle starting");

and

System.out.println("Test Bundle stopping"); -- to --> System.out.println("New Test Bundle stopping");

repeat steps 4 and 5 from above in a new terminal and then in the terminal running our OSGI app type:

osgi> update 1

You should see:

Test Bundle stopping
New Test Bundle starting

Nice, huh?, the old version was stopped, the new jar loaded and the new version was started. Now that’s what I call a Hot Deployment.

What’s next?

In the next articles, I’ll talk about the BundleContext, bundle Services, Service Trackers, Tools when working with OSGI and resources

sin comentarios... »

No comments yet.

RSS feed de los comentarios. TrackBack URL

deja un comentario

Del.icio.us

enlaces de interés