How to track lifecycle changes of OSGi bundles

This post explains how to track changes in the lifecycle state of OSGi bundles, using two different techniques: an OSGi BundleListener and an Eclipse BundleWatcher.

The OSGi Lifecycle

osgi lifecycle How to track lifecycle changes of OSGi bundles
(source: OSGi Service Platform – Core Specification)

Eclipse runs on top of the OSGi runtime, which manages the bundles (components) that make up an application. At any time, each bundle is has one of these lifecycle states:

  • INSTALLED: The OSGi runtime knows the bundle is there.
  • RESOLVED: The bundle is there and all it’s prerequisites (dependencies) are available. The bundle can be started (or has been stopped).
  • STARTING: The bundle is being started. If it has a BundleActivator class, the BundleActivator.start() method is being executed. When done, the bundle will become ACTIVE.┬áNote: Bundles that can be activated lazily (Bundle-ActivationPolicy: lazy) stay in this state until one of their class files is loaded.
  • ACTIVE: The bundle is running.
  • STOPPING: The bundle is being stopped. If it has a BundleActivator class, the BundleActivator.stop() method is being executed. When done, the bundle will become RESOLVED.
  • UNINSTALLED: The bundle has been removed from the OSGi runtime.

BundleListener

The BundleListener interface provides a convenient way to track lifecycle changes. It provides a bundleChanged(BundleEvent event) method, that is called by the OSGi runtime to communicate lifecycle changes.

BundleListener How to track lifecycle changes of OSGi bundles

To receive notifications, a BundleListener is added a BundleContext object. To stop receiving notifications, a BundleListener is removed from the BundleContent. This is shown in the next code snippet:

ActivatorWithBundleListener How to track lifecycle changes of OSGi bundles

You can get this code from my eclipse-examples repository on Github.

To see how this works, we install, start, stop and uninstall a bundle called ‘example.bundle_1.0.0.jar’ using the OSGi Console (-console launch argument). The jar file is located in the example.eclipse.bundlewatcher project. Don’t forget to use three slashes after file:///.

console bundlelistener How to track lifecycle changes of OSGi bundles

BundleListener restrictions and the BundleWatcher

A BundleListener the can only receive notifications after it has been started. It will miss lifecycle events related to bundles being installed as the OSGi runtime starts. The Equinox OSGi runtime will (typically) install and resolve all bundles that are initially available, before starting any of them. This happens before our BundleListener is started.

To monitor the lifecycle changes that happen during the startup of the OSGi runtime we have to hook our code into the runtime itself. The details depend on the OSGi implementation.

Eclipse Equinox has a BundleWatcher interface, that provides a watchBundle(Bundle bundle, int type) method. The framework will call this method to communicate lifecycle changes.

BundleWatcher How to track lifecycle changes of OSGi bundles

To install the the BundleWatcher into the startup process, we need to ‘hook’ into the runtime, using an Equinox Adaptor Hook. This requires the following steps:

  1. You will need org.eclipse.osgi as source code in your workspace (this is already part of my git repository).
  2. In the same parent directory, create a fragment to org.eclipse.osgi (the example.eclipse.bundlewatcher project).
  3. Create a file ‘hookconfigurator.properties’ pointing to your hook configurator class(es).
    hookconfigurator properties How to track lifecycle changes of OSGi bundles
  4. The hook configurator class must implement the HookConfigurator interface and have a no-argument constructor. The framework will call the addHooks(HookRegistry method), to allow you to install your BundleWatcher (in my example the BundleWatcher and HookConfigurator are implemented in the same class).BundleWatcherConfigurator How to track lifecycle changes of OSGi bundles
  5. In your launch configuration, make sure to include the ‘org.eclipse.osgi’ bundle from your workspace (not the Target Platform!).
    lc bundles How to track lifecycle changes of OSGi bundles
  6. Your launch configuration must have the following command line argument (when running outside the workspace, you could put this into the eclipse.ini or config.ini files):-Dosgi.framework.extensions=example.eclipse.bundlewatcherlc arguments How to track lifecycle changes of OSGi bundles
  7. Before you deploy, verify your build.properties to make sure hookconfigurator.properties is included in the .jar file.

You can get this code from my eclipse-examples repository on Github.

To see how this works, we again install, start, stop and uninstall a bundle called ‘example.bundle_1.0.0.jar’ using the OSGi Console. The BundleWatcher output is in red. You can see the bundle watcher fragment and bundle listener bundle being installed and started during startup (before the bundle listener receives any events).

console bundlewatcher How to track lifecycle changes of OSGi bundles

If you are curious about the Equinox Adaptor framework, will find the following links useful:

BundleTracker

Since I’ve been asked about it in the comments, I’ve added a BundleTracker example to my github repository.

I think we all agree that, in general, it is better to use a standardized API than a proprietary one. BundleTracker is a great choice for most use cases. However, there are use cases where the additional API is very useful, e.g. when you are provisioning a system. If you are already committed to using Equinox, then BundleWatcher is an interesting alternative.

Have fun,
Elias.

4 Responses to “How to track lifecycle changes of OSGi bundles”

  1. Neil Bartlett says:

    I’m not clear why anybody would want to use this Equinox-specific BundleWatcher instead of the OSGi-standard BundleTracker. Any thoughts? What have I missed?

  2. Hi Neil,

    the BundleTracker will miss the initial batch of INSTALL events (during start-up). Otherwise it is comparable to the BundleWatcher, and as you point out, a standard OSGi class.

    Best regards,
    Elias.

  3. Neil Bartlett says:

    Hi Elias. I think it’s important to understand what you need this information for. The BundleTracker tells you about all the bundles in a particular state (e.g. ACTIVE)… that includes both the bundles that are already in that start when you start the tracker, AND the bundles that subsequently reach that state after the tracker has been started. This makes it very useful for implementing the Extender Pattern.

    Therefore, BundleTracker doesn’t exactly miss the install events, because if a bundle is active then it must have been installed! It’s merely a matter of timing, i.e. the tracker finds out about the event some time after it happens whereas BundleWatcher apparently gets it in “real time”.

    So I suppose me real question is, what’s your use-case for getting these events in real time?

  4. GianMaria Romanato says:

    I agree with Neil, I am using extensively the OSGi extender pattern and I have been using only BunleListeners and SynchronousBundleListeners. With those two interfaces you can do everything: I would never use the Equinox specific listener as this would imply loss of portability to different OSGi containers.

    Plus, should you need to check the state of bundles that have been already installed/started when your BundleListener is registered, you can always use the BundleContext to get the array of all bundles already known to the framework and cycle the list to inspect their state.

4 responses so far

Written by . Published in Categories: Planet Eclipse, Planet OSGi