OSGi Diaries – Creating A Bundle

Covers turning the simple web app from the first installment into a simple web app using an OSGi Bundle.

Advertisements

In the first installment, I outlined a simple web application. In this post, I will be turning that application into two parts – an OSGi bundle, with a client web app.

But before we get into that, let’s go over setting up the environment.

Installing Glassfish v3

The first step is to get Glassfish v3 and install it. Unfortunately, the OSGi features are still on the bleeding edge, so you can’t even get buy with the “prelude” release – I used a recent “promoted” build from the start of September. The Glassfish Promoted Builds page has the full list – there’s a handy “latest” section at the bottom. I use the ‘latest-glassfish-unix.sh’ script, but there’s a Windows build if your perversions take you that way…

Once you’ve downloaded, simply run the script or EXE file. This should launch a GUI that will prompt you through the installation process. Take note of where you install it to, though – I’ll be referring to that as $GF3 in my examples.

If you like, feel free to test your installation by installing the simple application. This can be done via the command line as:

# in the status_app directory
mvn clean package
# start the domain - domain1 - if it's not already started.
$GF3/bin/asadmin start-domain
$GF3/bin/asadmin deploy --contextroot /statusApp target/status_app.war

You should now be able to go to http://localhost:8080/statusApp/index.html and test the app.

An OSGi Primer

OSGi technology is the dynamic module system for Java™.

What exactly is OSGi, anyway? I’m not an expert, so my definition won’t be quite right, but here’s the way I’ve been looking at it: OSGi is a classpath manager on steroids, and an attempt to get out of classpath hell. Basically, an OSGi container is a container for bundles. Bundles specify what Java packages they export, and can specify what packages (or other bundles) they need. And the container takes care of the wiring.

No nasty “class not found” errors because you’re missing a JAR – you get told of them at deploy time. No complicated class loader issues which mean two classes aren’t equal – the OSGi container gives your classes to you in one class loader. No possibility of getting errors about Log4J being configured because it’s accidentally on your classpath: your classpath consists of only what you say you want in your bundle.

Diagram showing how an OSGi class space works.
Diagram showing how an OSGi class space works.

So what is an OSGi bundle? Well, the simplest example of an OSGi bundle is a standard Java JAR file – with a few extra entries in the MANIFEST.MF file. The manifest file is used to configure the OSGi bundle – to let it know what packages or bundles to import, which packages to export, and so forth. A full list of the standard manifest headers can be found in Chapter 3 of the OSGi Core Specification.

Overview of the sample application

The sample application consists of 8 files at this stage:

status_app/pom.xml
The Maven POM file
status_app/src/main/java/net/twasink/osgispike/bean/Counter.java
Very simple counter; keeps the count in a static variable. This is just a POJO with no external dependencies
status_app/src/main/java/net/twasink/osgispike/web/IncrementServlet.java
Servlet mounted on /Increment. Causes the counter to increase.
status_app/src/main/java/net/twasink/osgispike/web/StatusServlet.java
Servlet mounted on /Status. Causes the counter to increase.
status_app/src/main/resources/net/twasink/osgispike/web/increment.html
Template for the increment servlet.
status_app/src/main/resources/net/twasink/osgispike/web/status.html
Template for the status servlet.
status_app/src/main/webapp/index.html
Simple "welcome" page for the application
status_app/src/main/webapp/WEB-INF/web.xml
Configuration file for the web app

Creating the bundle

Okay, that’s the background information out of the way. The task now is to get the Counter out of the web app and into a new bundle. The first part was simple enough: I just created a new empty project and moved the counter there, resulting in a structure like this:

counter_bundle/pom.xml
The Maven POM file.
counter_bundle/src/main/java/net/twasink/osgispike/bean/Counter.java
Very simple counter; keeps the count in a static variable. This is just a POJO with no external dependencies

Package structure showing the sample app broken into two parts
Package structure showing the sample app broken into two parts

In order to keep the webapp compiling, I had to go back and add a dependency to the new counter_bundle module. Because I want to use OSGi to manage the classpath, I put this dependence at the provided scope.

If you’ve been playing along, then we now have two modules – the counter_bundle JAR and the status_app WAR. We need to turn the counter_bundle into an OSGi bundle and then deploy it. To do this, we need to add the following to the MANIFEST.MF file:


Bundle-Version: 1.0-SNAPSHOT
Export-Package: net.twasink.osgispike.bean

Because I’m using Maven to do the builds, I did this by tweaking the maven-jar-plugin configuration – you can see that in the sample files later.

Now I’m ready to build and deploy the bundle. There are a few ways to do this, but the one that worked for me was to copy the JAR file into the autodeploy-bundles directory in the glassfish domain.


# in the counter_bundle directory
mvn clean install
cp target/counter_bundle.jar $GF3/glassfish/domains/domain1/autodeploy-bundles/

If you’re monitoring the Glassfish logs, you’ll should see a reference to ‘Started bundle: ‘ appear within a few seconds.

We can now rebuild and redeploy the status app, and we will be using the new bundle. This works because Glassfish puts OSGi bundles into the app server classpath.


# in the status_app directory
mvn clean package
$GF3/bin/asadmin deploy --force=true --contextroot /statusApp target/status_app.war

Try hitting the index page, and you should see it’s all working.

Wrapping up.

That’s all that’s involved in creating an OSGi bundle – at least a very simple one. They can become more complicated, as we’ll see in subsequent posts, but the mechanics don’t change very much.

As with all posts in this series, I have the source code available; it’s available under either the Creative Commons license (as per the blog) or under the aptly-named WTFPL. It’s not very much code.

The bundle we have built is still a little basic. The counter is still using a static variable to store its data, and new instances are being created by the servlets at will. In the next instalment, we shall convert this simple bundle into a (still simple OSGi Service – this will allow the counter to become a POJO without the static.

Author: Robert Watkins

My name is Robert Watkins. I am a software developer and have been for over 18 years now. I currently work for people, but my opinions here are in no way endorsed by them (which is cool; their opinions aren’t endorsed by me either). My main professional interests are in Java development, using Agile methods, with a historical focus on building web based applications. I’m also a Mac-fan and love my iPhone, which I’m currently learning how to code for. I live and work in Brisbane, Australia, but I grew up in the Northern Territory, and still find Brisbane too cold (after 16 years here). I’m married, with two children and one cat. My politics are socialist in tendency, my religious affiliation is atheist (aka “none of the above”), my attitude is condescending and my moral standing is lying down.

4 thoughts on “OSGi Diaries – Creating A Bundle”

  1. I apologise to anyone who finds the font-resizing a little odd; I had to rebuild my blog theme last night due to a stuff-up on my part, and I haven’t got the sizes right yet.

  2. One gotcha for anyone experimenting – the webapp will obtain a reference to the Counter at servlet init time – probably when you first hit the pages. If you re-deploy the Counter bundle, this change is NOT picked up until you restart or redeploy the web app. This isn’t a bug, as such – more a side effect of the naive approach being used here.

    This particular style of deployment is probably best for utility libraries, like Spring or HIbernate, or other technology frameworks.

    I will cover ways to pick up changes to bundles being used later.

    I have no idea of Glassfish resolves version conflicts on the in the application server’s classpath – so don’t ask. 🙂

      1. Thanks, Sahoo. That’s basically what I thought, but I didn’t want to commit to that.

        I will be covering hybrid applications in a few entries – I’ve been spending a lot of time reading your blog recently, and would highly recommend it to others.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s