DEV Community

Cover image for Undestanding Java OSGI framework
Dhanushka madushan
Dhanushka madushan

Posted on

Undestanding Java OSGI framework

OSGI is a framework used in building complex Java applications that contain multiple components. With OSGI, you can build Java application that can load dynamically. When you are building a basic Java application, you might create a jar file for each module and load it with the class path. But, with the OSGI framework, you can load OSGI jar file dynamically whenever you needed.
Lets discuss some of the terminologies and concepts that you should know about OSGI framework:

Bundle

Bundle is the OSGI module that contain all your logics. Bundle is a jar file that contain your business logic that provide some service. Other than a regular jar file, it also contain information about how it supposed to work in OSGI runtime in MANIFEST.MF file. These information include a bundle name, version, exported and imported libraries.
Following is a sample definition of OSGI bundle definition:

 Bundle-Name: Hello World
 Bundle-SymbolicName: org.dhanushka.helloworld
 Bundle-Description: A Hello World bundle
 Bundle-ManifestVersion: 2
 Bundle-Version: 1.0.0
 Bundle-Activator: org.dhanushka.Activator
 Export-Package: org.dhanushka.helloworld;version="1.0.0"
 Import-Package: org.osgi.framework;version="1.3.0"
Enter fullscreen mode Exit fullscreen mode
  • Bundle-name is used to identify the bundle. This is just a optional string value.
  • Bundle-SymbolicName is a unique identifier for the bundle. This follows the common java package naming standard.
  • Bundle-Description is a description about what this bundle does.
  • Bundle-ManifestVersion is versioning used by OSGI framework to read bundle manifest.
  • Bundle-Version is the version number you allocated for the OSGI bundle.
  • Bundle-Activator is the starting point of your module. You bundle can have multiple class implementations. OSGI use this property to mark what is the class that used as starting point of the bundle. We will discuss about bundle activator more later.
  • Export-Package is a set of packages that you need to expose to other OSGI bundles. If you didn't specify export packages, then other OSGI bundles unable to access classes in your OSGI bundle.
  • Import-Package is a set of packages that required to your OSGI bundle. You should import packages in here if you need to refer any other OSGI bundles.

Bundle is simply a module that contain all of your programming logics. You can import another bundle functionality into it and expose your own functionality to other bundles.

Services

Services are the way how each of the bundles are connected together. As I have already explained, multiple bundles can be connected together to provide some service.
Check the following sample bundle implementation that has activation method on it:

public class Activator implements BundleActivator {
    private BundleContext context;

    @Override
    public void start(BundleContext context) throws Exception {
        System.out.println("Starting");
        this.context = context;
    }

    @Override
    public void stop(BundleContext context) throws Exception {
        System.out.println("Stopping");
        this.context = null;
    }
}
Enter fullscreen mode Exit fullscreen mode

In this source code, the bundle activator is the Activator class. When the OSGI starting up it start executing the start method. This is much similar to the main method. When the OSGI framework stopping, it trigger the stop method. Whenever you add this bundle into the OSGI runtime, it will start execution by calling the start method and end its execution by calling the stop method.
As you can see, this bundle does not have any dependency with other OSGI bundles. It can start its execution independently. In some scenarios, you might need to start this bundle when some conditions are met. Until condition satisfy, OSGI runtime does not call the start method.
This can be achieved with references. References let you to call start method once given conditions are met. Check the following modification done to the Activator class:

public class Activator implements BundleActivator {
    private BundleContext context;

    @Override
    public void start(BundleContext context) throws Exception {
        System.out.println("Starting");
        this.context = context;
    }
        @Reference(
            name = "activator.service",
            service = ActivatorService.class,
            cardinality = ReferenceCardinality.MANDATORY,
            policy = ReferencePolicy.DYNAMIC,
            unbind = "unsetActivatorService")
    protected void setActivatorService(ActivatorService activatorService) {
            // Set values
     }

    protected void unsetActivatorService(ActivatorService activatorService) {
            // Unset values
    }

    @Override
    public void stop(BundleContext context) throws Exception {
        System.out.println("Stopping");
        this.context = null;
    }
}
Enter fullscreen mode Exit fullscreen mode

In this code, other than previous start and stop method, there are another two methods. @Reference annotation used here to mark these dependencies. Here, we have given a service name and service class. Under the reference annotation, we defined the cardinality as mandatory. Since the cardinality marked as mandatory, to trigger start function, setActivatorService should be satisfied. If the cardinality is optional, then it is not mandatory to call setActivatorService to start this bundle. This method can be triggered from another bundle. Following is a sample code, how to trigger setActivatorService method.

context.getBundleContext().registerService(ActivatorService.class.getName(), activatorService, null);
Enter fullscreen mode Exit fullscreen mode

Here, the activatorService is the object that contain details that need to send to the setActivatorService. Once this method get called, OSGI bundle will start the ActivatorService start method.

You can build more advanced applications by using the OSGI framework. You build dynamically pluggable components with dependency injection design pattern.

Discussion (0)