OSGi Bundles: Declarative Services

This post covers some basic OSGi concepts. Also i'll present a Tycho example of service definition in declarative approach.

Why modules

Slicing complex system in modules is crucial approach of complexity reduction 1. This and other aspects explain the growing popularity of OSGi technology in the past years. Since OSGi is very popular today (Nearly every modern Java Application Server and IDE is based on OSGi platform) it is worth to be familiar with it.

OSGI Bundle

OSGi2 is a service platform for software components (dynamic modules) in java. OSGI Components are called Bundles and every application consist of at least one bundle. Bundles are managed by an OSGi platform during the run-time. The OSGi spec defined bundle life-cycle, so Bundles can be

installed

started

stopped

updated

uninstalled

during the run-time without restart of a whole platform.
In other words OSGi introduces a kind of modularization system on top of java core platform.

Oracle is hardly trying to introduce modularization to java platform3. This goal was initially targeted for java 7 but now maybe we will see it in java 9. And it looks like at the moment oracle engineers say - java platform modularization will not be an adoption of OSGi. Even if OSGi Alliance was suggesting such way to go. However OSGi is already partly specified in JSR-291 Dynamic Component Support for JavaTM SE but i'm not sure whether it matters somehow.;)

Manifest

Every OSGi bundle is defined by the manifest. Manifest states symbolic name, version, exported and imported packages (as well as plugin and dynamic dependencies) and more. Here is one example.

Services

Further OSGi provides pre-defined services like Logging, Administration, Http-Server and more. OSGi Platform implements Service management infrastructure, that services use to register and discover. An due modularity and "dynamic" nature of OSGi, services play important role, i would even say, that programming OSGi is always programming Services and "thinking SOA"4.

In the early days services had to be discovered or registered explicitly to BundleContext5. Below is an example with Activator class. Activator's start() method is called every time the Bundle starts.

Declarative Service Definition

But OSGi specification developed and became additional possibilities to define, control and link services. The more advanced concept is called Declarative Services (DS)6. That it is all about relaxing Activator concept by introducing meta description in form of XML and later also in annotations.

Below is an example of implementation of org.osgi.service.log.LogListener which registers himself to OSGi Platform provided LogReaderService. And that service is injected by the OSGi Runtime according to XML description of a Component. Component is a POJO which life cycle is controlled by Service Component Runtime (SCR).

We see Component Implementation class definition and we see there is Reference (A specified dependency of a component). The Reference binds Target Service LogReaderService to our component. In this case this is platform provided Service. Of cause it is possible to declare custom services. The attributes bind and unbind specify Event Methods association with a reference. So this is enough for SCR to manage the life-cycle and injection of LogReaderService to the ConsoleLogger component.

To see something on the console we need someone to call platform provided org.osgi.service.log.LogService.

You can find Logservice project and the logexample project on GitHub (Pease notify that i'm pointing you to the Tag named: simple_services1)

Build

Before see any results we must build our bundles. To be able build it IDE independent there is a pom.xml file included. It uses tycho 0.15 to build and deliver the bundle. You can e.g. execute following to get desired artifacts.

mvn package .{path to pom.xml}pom.xml

And you will find org.holbreich.osgi.logservice-1.0.0-SNAPSHOT.jar in your target folder. Now build Logexample bundle.

Executute

Let's see how it works in a real OSGi Platform. Equinox would be fine, but i tried it with Apache Felix.
First Download the following:

Apache felix distribution

Bundle: Config Admin

Bundle: SCR (Declarative Services)

Bundle: Log

That's all we need.

Then unzip apache felix distribution to some folder.
Also copy downloaded bundles to /bundle folder of apache felix. Now you are ready to start felix.

Now we see the system bundle, Apache Felix Gogo Shell Bundles and also additional downloaded bundles. All bundles are in the active state which is good.
Now we can install custom bundles whit install command.

Works! We see that log service bundle was printing message to console on start of example bundle.

Further Details

There are three component types:

Immediate Component – The component configuration of an immediate component must be activated
immediately after becoming satisfied. Immediate components may provide a service.

Delayed Component – When a component configuration of a delayed component becomes satisfied,
SCR will register the service specified by the service element without activating the component
configuration. It will be activated on demand.

Factory Component – If a component’s description specifies the factory attribute of the component
element, SCR will register a Component Factory service. This service allows client bundles to
create and activate multiple component configurations and dispose of them. If the component’s
description also specifies a service element, then as each component configuration is activated,
SCR will register it as a service.

Simple immediate Component was presented twice in above example. Here is an example of delayed component:

We see that and delayed component provide service. Here the exposed service is implementation of OSGi standard Service interface EventHandler which is part of the Admin Event Service (AES) Specification that describes Publish-Subscribe pattern for OSGI. Property event.topic is also used by AES.

Factory approach is not covered here. We should prefer Blueprint Container if it starts to be complicated that way.