Monday, January 13, 2014

OSGi Subsytems on Apache Felix

Note: more up-to-date information on getting started with Apache Aries Subsystems can be found here: http://aries.apache.org/modules/subsystems.html

Last year I blogged about running the OSGi Subsystems implementation from Apache Aries. At the time Equinox was the only OSGi framework that had the full Core R5 implementation supported, which is needed in order to run OSGi Subsystems.

With some recent work on the Apache Felix container, it is now very close to supporting the full OSGi R5 specification. One of this first things that I tried with that is to run the Aries Subsystems implementation on it. And it works :)

OSGi Subsystems are a great way to package a number of OSGi bundles together, for example if you want to distribute an OSGi-based application. Subsystems provide a really convenient deployment model, without compromising the modularity of your application. For more background on Subsystems, see my earlier post about how to use OSGi Subsystems to deploy your applications.

What I'm doing here is take the example from that blog post and run it on Apache Felix with Aries Subsystems.

First of all you need the latest and greatest Felix Framework. I always build it as follows:

  svn co http://svn.apache.org/repos/asf/felix/trunk felix
  cd felix/framework
  mvn install 
  cd ../main
  mvn install 

This will give you a framework runtime in the felix/main folder.
Then add the following bundles to the bundle subdirectory:

All of the bundles above have links behind them where they can be downloaded, except for the Felix Coordinator implementation, as this one is very new. You can just build it from the coordinator directory of your Felix checkout. Or, if you prefer to use released components, you can also use the Equinox implementation org.eclipse.equinox.coordinator_1.1.0.v20120522-1841, but in order to run that on Felix you also need the Equinox supplement bundle org.eclipse.equinox.supplement_1.5.0.v20130812-2109.
Finally, I'm adding my little gogo command bundle as described in my older post, to add subsystem:list, subsystem:install, subsystem:uninstall, subsystem:start and subsystem:stop commands to Gogo. You can also download that as a bundle here: subsystem-gogo-command-1.0.0.jar

Ok, let's start up Felix and look what's inside:
.../felix/main $ java -jar bin/felix 
... some log messages appear ...
____________________________
Welcome to Apache Felix Gogo
g! lb
START LEVEL 1
   ID|State      |Level|Name
    0|Active     |    0|System Bundle (4.3.0.SNAPSHOT)
    1|Active     |    1|Apache Aries Application API (1.0.0)
    2|Active     |    1|Apache Aries Application Modelling (1.0.0)
    3|Active     |    1|Apache Aries Application Utils (1.0.0)
    4|Active     |    1|Apache Aries Blueprint Bundle (1.1.0)
    5|Active     |    1|Apache Aries Proxy Bundle (1.0.1)
    6|Active     |    1|Apache Aries Subsystem API (1.0.0)
    7|Active     |    1|Apache Aries Subsystem Core (1.0.0)
    8|Active     |    1|Apache Aries Util (1.1.0)
    9|Active     |    1|Apache Felix Bundle Repository (1.6.6)
   10|Active     |    1|Apache Felix Configuration Admin Service (1.8.0)
   11|Active     |    1|Apache Felix Coordinator Service (0.0.1.SNAPSHOT)
   12|Active     |    1|Apache Felix Gogo Command (0.12.0)
   13|Active     |    1|Apache Felix Gogo Runtime (0.10.0)
   14|Active     |    1|Apache Felix Gogo Shell (0.10.0)
   15|Active     |    1|Apache Felix Resolver (1.0.0)
   16|Active     |    1|Region Digraph (1.1.0.v20120522-1841)
   17|Active     |    1|slf4j-api (1.7.5)
   18|Resolved   |    1|slf4j-simple (1.7.5)
   19|Active     |    1|Subsystem Gogo Command (1.0.0)
   20|Active     |    1|org.osgi.service.subsystem.region.context.0 (1.0.0)

g! subsystem:list
0 ACTIVE org.osgi.service.subsystem.root

Looking at the bundles, you can see the Gogo command line ones that come with Felix, as well as its Bundle Repo. You can also see bundle 20, which is a synthesised bundle that the Subsystems implementation added and which represents the root subsystem. The subsystem:list command reports that there is one subsystem: the root one.

Now let's look at my example applications again. I have the following two subsystems:


Subsystems are a great way to distribute multi-bundle applications, and my two subsystems each contain 2 specific bundles as well as a shared bundle.

Let's install then and see what happens:

g! subsystem:install http://coderthoughts.googlecode.com/files/subsystem1.esa
Installing subsystem: http://coderthoughts.googlecode.com/files/subsystem1.esa
Subsystem successfully installed: subsystem1; id: 1
g! subsystem:start 1
g! lb
START LEVEL 1
   ID|State      |Level|Name
...
   21|Active     |    1|SharedBundle (1.0.0)
   22|Active     |    1|BundleA (1.0.0)
   23|Active     |    1|BundleB (1.0.0)
The three bundles needed by subsystem1 are installed and all started with the subsystem:start command.

And let's add the second subsystem...
g! subsystem:install http://coderthoughts.googlecode.com/files/subsystem2.esa
Installing subsystem: http://coderthoughts.googlecode.com/files/subsystem2.esa
Subsystem successfully installed: subsystem2; id: 2
g! subsystem:start 2
g! lb
START LEVEL 1
   ID|State      |Level|Name
...
   21|Active     |    1|SharedBundle (1.0.0)
   22|Active     |    1|BundleA (1.0.0)
   23|Active     |    1|BundleB (1.0.0)
   24|Active     |    1|BundleC (1.0.0)
   25|Active     |    1|BundleD (1.0.0)

As expected, the two new bundles for subsystem2 are now also installed. And, because we're talking about a feature subsystem here, where everything is shared, the SharedBundle (21) is not installed a second time, but rather reused from subsystem1. 

The topic of subsystems is much bigger. Subsystems can provide a certain level of isolation, they can work with Repositories for provisioning and you have a lot of options wrt to what you can put inside an .esa file: you can put all the bundles in there that your application needs, or you can just have a textual descriptor that declares your main bundles and let the OSGi Resolver and Repository find the dependencies and deploy these for you. Details about these various options can be found in the OSGi Subsystem spec (chapter 134 in the OSGi R5 Enterprise spec). 

All in all good news - Subsystems now works in Apache Felix as well. Right now you need to build the latest snapshot, but hopefully we'll have a Felix Framework release for this soon!

7 comments:

Cristiano Gavião said...

Nice article David ! thanks.
what do you think about to write a post about the use of a Repository Service with Subsystem ? ;)

David Bosschaert said...

@Christiano - I'm actually working on that. Hopefully soon :)

Unknown said...

Great tutorial. I'm a beginner in OSGi and much interested with Subsystems. Please could you give me some insight about which parts of the specification I should study to make Subsystems interact with the Repository for provisioning?

David Bosschaert said...

Hi Bleza,

You can find information on the Repository/Subsystems integration in chapter 134 of the Enterprise R5 spec. Just search for the word repository in there and you'll find the details. I'm still planning to write a blogpost about it too, but no time just yet. However I did recently give a presentation about it that contains some details (including screenshots from a demo, and the bundles that I used). You can find that presentation here: http://www.slideshare.net/bosschaert/provisioning-osgi-subsystems.

Unknown said...

Hi David,

I’m currently working on a project where we decided to embed an OSGI framework inside our existing enterprise application. I’d really appreciate if you could give me some guidance about two points related to provisioning and packaging.

The first issue I have is that when I start my framework (Apache Felix here); there is nothing in there except the system bundle itself. For example, in order to add blueprint support, you need to install and start a set of bundles. We currently packaged this set of bundles as a .zip file and wrote some custom code in order to iterate in the content of this zip and install the contained bundles in the framework. We did the same for others functionalities. As I understand it now, we should rather use subsystems (feature type as bundles have to be shared) here, right? But my question is, how do I have to deploy the bundles needed to support subsystems in my framework then? In addition, as we won’t use any bundle repository (the application is meant to be deployed at customer site and therefore needs to include everything it needs), is there really an advantage of using .esa file instead of .zip files?

The second issue I have is that our application is currently packaged and delivered to customers as an .ear file. We therefore would like to embed our bundles (.esa, .zip or .jar files) inside this .ear file. Does that sound appropriate to you? How could I achieve this? I was thinking about using one or several subfolders containing a file with a name following a convention such as core.bundles, myapp.bundles… And then use the class loader to locate these resources and installing all the bundles (.esa, .zip, or .jar files) found in their parent directory. Is there any cleaner or more standard approach I could use?

Thanks in advance,
Anne-Catherine

David Bosschaert said...

Hi Anne-Catherine,

On the first issue, this is a little bit of a chicken-and-egg issue :) You are correct that a plain framework does not have subsystem support so it needs to be added somehow. If you are running the Felix framework on its own, you can put the required bundles in the bundle directory of the Felix distribution. However, in your case as your application is packaged as an .esa file this probably does not work. In that case you will probably need to do your own initial provisioning, which will effectively be looping over the bundles that you want to install when the framework starts. You can look at the Felix AutoProcessor which is the thing that processes the bundle directory. It's probably quite similar to what you're doing already.

If you don't use a bundle repository integration and you also don't use subsystem isolation (i.e. application/composite) there is probably minimal benefit in using .esa files over the .zip files you're doing right now, although there might be benefit in packaging your artifacts as .esa files if you also deploy them in other contexts where subsystems are supported.

On your second comment, an .ear file is supposed to contain everything that is your application. It probably already contains various jar files and possibly .war files. I think it makes sense to put your .esa files in there too, although there really is no standard defined for this, so it's really up to you. As long as you don't violate the .ear spec you should be good :)

Best regards,

David

David Bosschaert said...

Note that most bundles mentioned in this post have newer releases available. For a more up-to-date list of bundles see here http://aries.apache.org/modules/subsystems.html