Navigating OSGi - Extending Your Software to Embed an OSGi Framework


Dec 12, 2017

Navigating OSGi - Extending Your Software to Embed an OSGi Framework

Navigating Open Sea_OSGI Blog Header

You have your software in place, but you need a better way of allowing your technical users to extend the platform. Most Java developers are aware of OSGi, but embedding an OSGi framework into your product seems like a huge undertaking. Further clouding the path is the uncertainty of exactly how OSGi works. For many Java developers OSGi feels more like trying to navigate the open sea rather than something they would want to play with.

Why Use OSGi within my Existing Software?

Some of the primary reasons to embed OSGi within your application is so that developers can:

  • Deploy functionality at runtime without having to stop the primary application
  • Run multiple versions of the same library, at the same time, within the same JVM
  • Separate and protect plugins from the core functionality and classpaths

Which Library to Use?

We, at dotcms, decided to use Apache Felix. The Equinox Eclipse project is also a solid option depending on what you are looking to do. Felix stays pretty close to the latest spec but both libraries have similar feature sets. In addition, Felix is better built to be embedded into an existing WAR. Both Equinox and Felix can do this but Equinox recommends, by default, embedding your server into Equinox, not the other way around.

eclipse screen grab

This is how Eclipse runs, which is what Equinox is primarily built for, so this makes sense.

If you use Jboss or Weblogic you can use the OSGi implementations they ship with, but we prefer to remain more agnostic and not rely on the underneath app server for something like OSGi.  As of the writing of this article, none of the other major implementations implement OSGi framework spec 6.

For more info see:

How to Embed OSGi

At dotCMS we were faced with the issue of needing to provide our users with the ability to deploy what we call Dynamic Plugins. A Dynamic Plugin is a plugin that can be deployed and undeployed at runtime, meaning without a server restart. The plugins needed to be able to override current functionality as well as add new functionality to our existing WAR. This involves adding Servlets, Spring Containers, Filters, Java Classes, REST Endpoints, etc.

In our case, we weren’t starting a new project where the entire app would be centered around OSGi (i.e. Eclipse), we already had an existing WAR on which we needed to add OSGi.

The great news is that OSGi is not difficult to embed. Essentially it boils down to the config and code example shown below.

First you need to add the library dependency to your project. This would be adding the JARs for either Apache Felix or Eclipse Equinox. Next you need something to start OSGi. Being a web application, we used a listener:


As an example consider the following:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.felix.framework.FrameworkFactory;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.launch.Framework;
public class OSGiListener implements ServletContextListener {

    private final String OSGi_LOAD_DIRECTORY = "/path/to/OSGi/bundles";

    public void contextInitialized(ServletContextEvent servletContext) {

        Map<String, String> osgiConfig = new HashMap<>();
        osgiConfig.put(Constants.FRAMEWORK_STORAGE, "/path/to/OSGi/cache");
        osgiConfig.put(Constants.FRAMEWORK_STORAGE_CLEAN, "true");
        try {
            FrameworkFactory frameworkFactory = ServiceLoader.load(FrameworkFactory.class)
            Framework framework = frameworkFactory.newFramework(osgiConfig);

            BundleContext bundleContext = framework.getBundleContext();
            BundleManager bundleManager = new BundleManager(bundleContext);
        } catch (Exception ex) {
            System.out.println("OSGi Failed to Start");
    public void contextDestroyed(ServletContextEvent arg0) {
        // stop framework
    public class BundleManager {
        private BundleContext bundleContext = null;
        public BundleManager(BundleContext bundleContext) {
            this.bundleContext = bundleContext;
        public void load() throws Exception {

            ArrayList<Bundle> availableBundles = new ArrayList<Bundle>();
            //get and open available bundles
            for (URL url : getBundles()) {
                Bundle bundle = bundleContext.installBundle(url.getFile(), url.openStream());

            //start the bundles
            for (Bundle bundle : availableBundles) {
                try {
                } catch (Exception ex) {
                    System.out.println("Failed to start bundle " + bundle.getSymbolicName());

        private List<URL> getBundles() {
            List<URL> bundleURLs = new ArrayList<>();
            //load into bundleURLs the URLS for OSGi_LOAD_DIRECTORY
            return bundleURLs;

For more information see the following links:

What We Learned

  • BND is your friend. BND is a library to help you build OSGi plugins.
  • The default Gradle plugin for BND stinks. I would recommend looking at this library for building BND plugins. I find Gradle good for OSGi plugins, just not its default plugin.
  • Keep OSGi libraries separate from your Web App underneath. When we first got into OSGi, we provided all the libraries we had on the classpath to OSGi. Felix has a mechanism for exporting the libraries to the OSGi bundles. In hindsight, we learned that it is best for bundles to provide their own libraries or to use services from other bundles. This keeps things clean and easier for development.

OSGi is a great way to allow developers to deploy new functionality in an existing web application while keeping it protected and separate from other things within the main application. Following the instructions above, and heeding our lessons learned, it is not difficult to embed OSGi within your own application.

Recent Posts

Container Orchestration: Running dotCMS in Kubernetes

Organizations are always looking for ways to make their technology infrastructure more flexible and scalable, and dotCMS is no different. That is why we have invested significant developer time and resources into scaling dotCMS with containers like D...

Content as Infrastructure: a Headless CMS that Works With You (Not Against You)

Having a headless CMS isn’t the end game. To truly orchestrate customer experiences across touchpoints (not to mention internal employee experiences), you need a headless CMS that works with you rather than against you.

How Hyper-Personalization Helps Improve the Employee Experience

Improving the employee experience is high on every enterprise’s priority list. Here’s how hyper-personalization can help.

Content as Infrastructure: It's Time To Build Around Your Content

dotCMS is taking Content as a Service (CaaS) a step further. Our customers are making content their infrastructure both internally and externally. How are you using content?