Jason Tesser
Director of Engineering

Navigating OSGi - Extending Your Software to Embed an OSGi Framework

Dec 12, 2017

By: Jason Tesser

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.

Filed Under:


‚ÄčOn-Demand Demo

Get a complete demo of the dotCMS Content Management System. This webinar covers all the major features of the platform, including editing and managing content, creating pages, creating content types, building custom workflows and more.

Get On-Demand Demo

Recommended Reading

Developing a Github Flavored Markdown Plugin

Recently, we were asked if dotCMS can deliver Github flavored Markdown content. We thought that developing a Markdown would be a great example of how easy it is to extend dotCMS with OSGi plugins.

Accessing Spring Beans from an OSGI Plugin

dotCMS has a built-in OSGI plugin that allows a developer to use the standard Spring Web MVC framework. This post shows how to also create and access Spring Beans from other classes, such as a Control...

dotCMS 5.1: A Minor Release With Major Updates

dotCMS 5.1 is here! In line with our efforts to provide enterprise brands with a Content as a Foundation, empowering them to build, orchestrate and deploy their digital experience platform, dotCMS 5.1...