1
votes

according to http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Fguide%2Fua_help_war.htm I set up a dedicated Tomcat server that runs several eclipse-help-plugins.

The server and also the help is up and running well. But now I realized that stopping the server especially the OSGi-Framework seems to be a problem. I always have to kill the server process if the help-war is deployed and I believe that I have to shutdown the OSGi-Framework gracefully.

After some investigation I came up with the following implementation of a ServletContextListener, that stops the system-bundle by calling bundleContext.getBundle(0).stop():

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.FrameworkUtil;

public class OsgiShutdownListener implements ServletContextListener {

    /** {@inheritDoc} */
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        Bundle bundle = FrameworkUtil.getBundle(org.eclipse.core.runtime.adaptor.EclipseStarter.class);
        BundleContext bundleContext = bundle.getBundleContext();
        try {
            bundleContext.getBundle(0).stop();
        } catch (BundleException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    /** {@inheritDoc} */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("starting");

    }
}

But FrameworkUtil.getBundle(org.eclipse.core.runtime.adaptor.EclipseStarter.class) always returns null, so I never get a reference to a BundleContext to stop the framework.

EDIT: I changed the code to sce.getServletContext().getAttribute("osgi-bundlecontext") in contextDestroyed() and contextInitialized() as well, but in both cases I get no reference to the bundle context. Bundle context is always null.

public class OsgiShutdownListener implements ServletContextListener {

    private BundleContext bundleContext;

    /** {@inheritDoc} */
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // Bundle bundle =
        // FrameworkUtil.getBundle(org.eclipse.core.runtime.adaptor.EclipseStarter.class);
        // this.bundleContext = bundle.getBundleContext();

        ServletContext context = sce.getServletContext();
        this.bundleContext = (BundleContext) context
                .getAttribute("osgi-bundlecontext");
        try {
            this.bundleContext.getBundle(0).stop();
        } catch (BundleException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    /** {@inheritDoc} */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext context = sce.getServletContext();
        this.bundleContext = (BundleContext) context
                .getAttribute("osgi-bundlecontext");
    }
}

How do I get a bundleContext in this situation to stop the system bundle? Or how do I gracefully stop the OSGi-Framework when the server shuts down?

2
What is the value of sce.getServletContext().getServletContextName()? I'm wondering what the name of the servlet is that is raising the event, and whether the servlet has the OSGI framework attached as a ServletContext attribute.Sheena Artrip
sce.getServletContext().getServletContextName() is null because its called by the container at shutdown.shylynx

2 Answers

1
votes

EclipseStarter is part of a launcher application, therefore it is "outside" OSGi, therefore it does not get loaded by an bundle ClassLoader... therefore (finally!) it returns null from FrameworkUtil.getBundle().

You need to get hold of the system bundle context... at some point in the past you must have had this because you successfully started OSGi. So why not remember it in a field, or otherwise arrange for it still to be visible at stop time?

0
votes

Looking at the help war, you should be able to modify the web.xml to override the bridge servlet.

http://grepcode.com/file/repository.grepcode.com/java/eclipse.org/3.5/org.eclipse.help/webapp/3.4.0/web-archive/help/WEB-INF/web.xml?av=f

http://eclipsesrc.appspot.com/jsrcs/org.eclipse.equinox.servletbridge/src/org/eclipse/equinox/servletbridge/BridgeServlet.java.html

Since the BridgeServlet is ultimately responsible for starting and stopping the OSGI Runtime through FrameworkLauncher, you should be able to override BridgeServlet and grab the FrameworkLauncher instance. The FrameworkLauncher doesn't provide a standard 'Framework' and instead wraps it around it's own class loader and reflection magic.

That said: the BridgeServlet is already responsible for shutting down the OSGI framework. Unless it is bugged things should probably stop by themselves when calling tomcat shutdown.

BridgeServlet doesn't set osgi-context, I believe that might only be a "whiteboard" thing, where the entire servlet is contained within an OSGI container, and not the other way around like here.