OSGi Getting Started

By Michael N. Lipp

Mastodon Follow

View GitHub Project


Part 1: The container

Part 2: Simplest Bundle

Part 3: Simple Bundle

Part 4: Eclipse (OSGi) Plugin

Part 5: Bndtools

Part 6: Shift in Perspective

Part 7: Modules and Services

Part 8: Accessing a Service

Part 9: Tracking a Service

Part 10: Using a Service

Part 11: Providing a Service

Interlude: Cleaning up

Part 12: Configuration Admin

Part 13: Service Components

Part 14: Repositories

Part 15: Versions

Shift in Perspective

When presenting their software, OSGi framework providers tend to focus—not surprisingly—on the capabilities of the product. Among those is the possibility to deploy bundles dynamically from a console. We’ve used this capability throughout this introduction to test our bundle in various development stages. This might lead to the impression that the OSGi framework is a heavy weight—or at least light heavy weight—container1, which is not true.

A more appropriate perspective on the OSGi framework focuses on the aspect that it is a framework: an environment providing some generic functionality to facilitate the development of software (see the more exhaustive explanation on Wikipedia). A characteristic of frameworks (contrary to libraries) is that they implement the startup code. The user-written code is invoked by the framework in a framework dependent way2.

The capability to deploy bundles dynamically is a genuine functionality of the OSGi core framework, providing a console isn’t. A minimal application using the OSGi framework therefore consists of the framework implementation and at least one bundle. Contrary to some other frameworks, OSGi doesn’t provide the main method. In order to get things started, a minimal application must implement a “launcher” that creates an instance of the framework, installs the bundle and starts the framework (which activates the installed bundle in turn). You can find a sample launcher in the OSGi Core specification3.

To simplify this task, Bndtools provides support for assembling an application that consists of a framework, your chosen bundle(s), and some application startup code (though not a minimal version). Switch to the “Run” tab of the bnd.bnd graphical editor.

Bndtools Run tab

We’ll stick to using Felix here. Choose org.apache.felix.framework;version='[7.0.3,7.0.3]' as OSGi framework and JavaSE-11 as execution environment ①. The bundle under development is automatically added to the “Run bundles” ②. Use the button “Export” at the top right ③ to create the application. Test the created jar by running it with jar -jar your.jar.

Looking at the content of the created jar, we find something like this (empty directory entries and source files removed):

   335 Thu Jan 06 17:26:24 CET 2022 META-INF/MANIFEST.MF
   722 Fri Feb 01 00:00:00 CET 1980 aQute/launcher/agent/LauncherAgent.class
   675 Fri Feb 01 00:00:00 CET 1980 aQute/launcher/pre/EmbeddedLauncher$Loader.class
 12939 Fri Feb 01 00:00:00 CET 1980 aQute/launcher/pre/EmbeddedLauncher.class
  4836 Thu Jan 06 17:26:24 CET 2022 jar/SimpleBundle-bnd.jar
378246 Mon Nov 22 15:55:00 CET 2021 jar/biz.aQute.launcher-6.1.0.jar
773807 Fri Dec 03 15:59:50 CET 2021 jar/org.apache.felix.framework-7.0.3.jar
  3352 Thu Jan 06 17:35:30 CET 2022 launcher.properties
    57 Thu Jan 06 17:35:30 CET 2022 start
    48 Thu Jan 06 17:35:30 CET 2022 start.bat

Basically, the content appears as expected. There is the Felix framework jar and our bundle. The EmbeddedLauncher.class4 and the bit.aQute.launcher provide the startup code that is configured—from the settings on the “Run” tab—by the launcher.properties.

Looking at the sizes, you find that the core of the OSGI framework is about 770k, the “basic offset” for using OSGi. The size of SimpleBundle-bnd.jar appears to be a bit high, considering its simple content. Unpacking it reveals that it contains the source code of our classes in addition to the bytecode (the same applies to biz.aQute.launcher-6.1.0.jar). Including the source code is the default behavior when bnd builds a jar. The source is put into the jar under OSGI-OPT/src where “OSGi-aware” IDEs will find it in a debugging session.

If you want the command shell to be part of your application again, add the bundles org.apache.felix.gogo.shell, org.apache.felix.gogo.runtime and org.apache.felix.gogo.command in the “Run Bundles” field. Start the application with the augmented set of bundles and you can e.g. check the running bundles with felix:lb as you did before. To simplify application launch during development, Bndtools provides the “Run” button on the “Run” tab. It immediately starts the environment that you found in the exported bundle in the previous part.

Bndtools will remain the tool of choice for the remainder of this introduction. It’s basically an Eclipse integration for the command line tool bnd5. The tool bnd is in turn at the core of all OSGi build tools that I have encountered. While it provides some sophisticated functions, it’s easy to get started with, and the configuration and action directives in bnd.bnd are straightforward and easy to understand.

  1. Especially if you know something about J2EE. 

  2. OSGi uses the BundleActivator, this should have become obvious already. 

  3. You should really have a look at the code in order to gain a thorough understanding of what happens. Nevertheless, I’m going to proceed with the ready-made solution here in order to avoid loosing my focus. 

  4. Don’t ask me why this class has come back to us from the future. 

  5. This is a bit unfair. Its possibility to deploy the bundle under development into a running framework gives you a really fast development cycle. I failed to find a description of this feature in the documentation, so it took me some time to find out about it. Make some change to the source code (adding a space somewhere is sufficient) while the OSGi framework that you started with the “Run” button is running. Save the source file. As you can see from the log messages, the bundle under development is stopped, reinstalled, and restarted automatically.