Monday, 9 December 2013

Creating a java service wrapper for an OSGi application

I admit, I have my doubts if somebody actually is interested in this.

And, probably, this is one of the worst sentences you could start your blog post with ;)

On the other hand, as you are actually reading this, you have found this page. So, you might have searched for it. Meaning, you really might be interested in learning how to create a service for an OSGi application!

First, a quick definition:

When I talk about "services" here, I mean things like "windows services" or "unix daemons", i.e. programs running in the background (which can be started automatically when the computer boots and which can react to system events).

An "OSGi application" in the context of this blog post is an executable jar file (created with bndtools). If somebody is interested in how you'd create such an executable jar file, let me know and I will write a blog post about it ;)).

Setup and Preparation

Let's assume we have the executable OSGi jar file, one you'd start from the command line like "java -jar myosgiapp.jar". And, let's assume we are on some unix machine (windows should work more or less the same way).

How to turn that into a service?

The - from my observation - most popular library for creating services is called the tanuki java service wrapper and is available under various licences (there should be one satisfying your needs).

In my case, I downloaded the community edition and unzipped it:

   tar -zxvf wrapper-linux-x86-64-3.5.23.tar.gz  

Checking out the documentation you will learn that there are four ways to create services; we will use #4 (which is about turning executable jars into services).

I create a new directory

  mkdir servicetest
 cd servicetest

and follow the instructions, that is, I create a couple of subdirectories:

  mkdir lib
  mkdir conf
  mkdir bin
  mkdir logs

and copy some files from the downloaded tanuki directory:

  cp <path_to_tanuki>/bin/wrapper bin
  cp <path_to_tanuki>/src/bin/ bin/myosgiapp
  chmod 755 bin/myosgiapp

As you can see, I renamed into myosgiapp. Let's change that file a little bit. Open an editor and adjust the APP_NAME and APP_LONG_NAME to something that suits you.

Some more stuff to do:

  cp <path_to_tanuki>/lib/ lib
  cp <path_to_tanuki>/lib/wrapper.jar lib

and, last bit, the configuration file and the actual program

  cp <path_to_tanuki>/src/conf/ conf/wrapper.conf
  cp <path_to_osgijar>/myosgiapp.jar lib


First thing to update in your wrapper.conf file is this property:

set it to

Furthermore, this here: (...)

should be set to<path_to>/lib/wrapper.jar 


and (I know, we have to set the myosgiapp.jar a second time)<path_to>/lib/myosgiapp.jar

Enter... the service

Now, as a reward for all this messing-around-with-files-and-dirs, you should be able to run 

  bin/myosgiapp start 

Your application should now have started as a service, giving you some PID on the console as an indication that everything went fine. Run

  bin/myosgiapp stop 

to shutdown the application and check the log under logs/wrapper.conf to see it things happened the way they should have happened. Omitting the start or stop instruction will give you a list of available command options.

There are a lot of things to consider when shutting down an application like this... basically, what tuniki does in this simple case, is a "System.exit(0)". You should create a shutdown hook to make your application disappear more gracefully.

And now?

Congrats! You are the first one ever to read this line!

Just kidding ;) Thing is, that I don't really know how many use cases there are to do a thing like this. In my case, what I want to achieve is the following:

  1. commit new code in some bundle participating in my OSGi app
  2. let jenkins build the changed bundle and run the tests
  3. if "still green", let jenkins build, test and deploy the whole app
  4. if "still green", let jenkins shut down the running demo app and restart it
The goal is to create a reliable continuous delivery chain for an OSGi application.

As usual, feedback is welcome ;)