Mikhail Potter

Pluggable architecture with Apache Felix

JVM does not support dynamic component model. To solve this issue OSGi (Open Services Gateway initiative) was found. OSGi is a framework that allows to deploy modules and libraries on the fly. To use the framework you need to install and start OSGi container (e.g. Apache Felix, Eclipse Equinox, Knophlerfish, ProSyst etc.) and then you can add and remove bundles (libraries and modules in OSGi terminology) to it dynamically. In the post you will find how to create basic application with pluggable architecture using Apache Felix. The source of the whole application can be found on GitHub.

The project could be divided into two parts: extensible host application (osgi-host module) and pluggable bundles (hello-api, hello-en-bundle, hello-es-bundle).

Host application

As was mentioned host application should start OSGi container and provide API for loading / unloading bundles. To achieve this, it is required to add a dependency on Apache Felix Framework:

<dependency>
    <groupId>org.apache.felix</groupId>
    <artifactId>org.apache.felix.framework</artifactId>
</dependency>

And write a couple lines of code to start OSGi container:

felix = Felix(configMap)
felix?.start()

As you can see, Felix constructor accepts configuration map as an argument. The map should define which packages and bundles should be lunched on startup. In our example configuration looks the following:

val configMap = StringMap()
configMap.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA,
              "kotlin; version=1.0.6," +
              "kotlin.jvm.internal; version=1.0.6," +
              "com.mvpotter.osgi.hello; version=1.0.0")

val list = listOf(activator)
configMap.put(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP, list)

The first block specifies required packages, they are

The last line defines bundle activators that will be launched on startup. It is necessary to launch HostActivator to have an access to BundleContext. It allows to manage bundles: install, start, stop, uninstall, list, find bundle services and so on. Complete list of Apache Felix properties can be found in documentation.

Bundles

Bundles are built using Felix maven-bundle-plugin. All you need to do is specify packaging

<packaging>bundle</packaging>

and add required attributes to bundle manifest file

<plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>
    <configuration>
        <instructions>
            <Export-Package>com.mvpotter.osgi.hello.impl</Export-Package>
            <Bundle-Activator>com.mvpotter.osgi.hello.impl.ProviderActivator</Bundle-Activator>
        </instructions>
    </configuration>
</plugin>

hello-api bundle defines interfaces that should be implemented by other bundles and further used by the host application. Other bundles contain class with API implementation and activator that registers its service in bundle context.

main.kt file shows how to register bundles from provided JAR files by host application and invoke their service methods. Apache Felix documentation provides useful tutorials on creating and consuming bundle services.

#osgi