Search code examples
web-applicationsosgiwarosgi-bundleembedded-osgi

Embed OSGI in war


I am interested in adding an OSGI container into my WAR but I can't find a tutorial or a documentation on how to do this. I found some things that are not useful at all. I am interested in Felix implementation and Atlassian implementation.

I am willing to do this so that my war accepts plug-ins and I can dynamically extend my Web app and also deploy it to any Web server.

Any links to a documentation or something? Any help is appreciated.


Solution

  • Adding an OSGi Framework launcher to a web application is not a big deal.

    You need to add a listener to start the framework launcher in your web.xml

    <listener>
      <listener-class>at.badgateway.StartupListener</listener-class>
    </listener>
    

    The startuplistener could look like this

    public class StartupListener implements ServletContextListener {
    
    //vars
    
        @Override
        public void contextInitialized(ServletContextEvent event) {
            // set props
        Map<String, String> config = new HashMap<String, String>();
        config.put(Constants.FRAMEWORK_STORAGE, "path to cache");
        config.put(Constants.FRAMEWORK_STORAGE_CLEAN, "true");
    
            try {
                        // get framework and start it
                FrameworkFactory frameworkFactory = ServiceLoader.load(FrameworkFactory.class).iterator().next();
                framework = frameworkFactory.newFramework(config);
                framework.start();
    
                        // start existing bundles
                bundleContext = framework.getBundleContext();
                starter = new MyBundleStarter(servletContext, bundleContext);
                starter.launch();
    
            } catch (Exception ex)  
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent arg0) {
             // stop framework
        }
    }
    

    Take care of MyBundlestarter class in the upper quote, it is the class which activates all bundles contained in your war. (e.g. /WEB-INF/Osgi-Bundles)

    import org.osgi.framework.Bundle;
    import org.osgi.framework.BundleContext;
    public class MyBundleStarter{
    
        private BundleContext bundleContext = null;
    
        public void launch() throws Exception {
    
            ArrayList<Bundle> availableBundles= new ArrayList<Bundle>();
            //get and open available bundles
            for (URL url : getBundlesInWar()) {
                Bundle bundle = bundleContext.installBundle(url.getFile(), url.openStream());
                availableBundles.add(bundle);
            }
    
            //start the bundles
            for (Bundle bundle : availableBundles) {
                try{
                bundle.start();
                }catch()
            }
    
        private List<URL> getBundlesInWar() throws Exception {
            // returns a list of URLs located at destination
        }
    }
    

    Last but not least, you have to add an osgi framework to your project.

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

    or

        <dependency>
            <groupId>org.eclipse.osgi</groupId>
            <artifactId>org.eclipse.osgi</artifactId>
        </dependency>