终止在Tomcat中运行的OSGi-Framework

时间:2013-06-27 08:08:53

标签: eclipse osgi equinox servlet-listeners

根据http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Fguide%2Fua_help_war.htm我设置了一个运行多个eclipse-help-plugins的专用Tomcat服务器。

服务器以及帮助已启动且运行良好。但现在我意识到停止服务器尤其是OSGi-Framework似乎是一个问题。如果部署了帮助战争,我总是要杀死服务器进程,我相信我必须优雅地关闭OSGi-Framework。

经过一番调查后,我想出了一个ServletContextListener的以下实现,它通过调用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");

    }
}

但是FrameworkUtil.getBundle(org.eclipse.core.runtime.adaptor.EclipseStarter.class)总是返回null,所以我永远不会引用BundleContext来停止框架。

修改 我在contextDestroyed()和contextInitialized()中将代码更改为sce.getServletContext()。getAttribute(“osgi-bundlecontext”),但在这两种情况下,我都没有引用bundle上下文。 Bundle上下文始终为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");
    }
}

如何在这种情况下获取bundleContext来停止系统捆绑?或者,如何在服务器关闭时优雅地停止OSGi-Framework?

2 个答案:

答案 0 :(得分:1)

EclipseStarter是启动器应用程序的一部分,因此它在OSGi“外部”,因此它不会被捆绑ClassLoader加载...因此(最后!)它从FrameworkUtil.getBundle()返回null

你需要掌握系统包上下文...在过去的某个时刻你必须拥有这个,因为你成功启动了OSGi。那么为什么不在田野中记住它,或者在停止时间仍然可以看到它?

答案 1 :(得分:0)

查看帮助战争,您应该能够修改web.xml以覆盖桥接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

由于BridgeServlet最终负责通过FrameworkLauncher启动和停止OSGI运行时,因此您应该能够覆盖BridgeServlet并获取FrameworkLauncher实例。 FrameworkLauncher没有提供标准的框架'而是将它包裹在它自己的类加载器和反射魔法周围。

那就是说:BridgeServlet已经负责关闭OSGI框架。除非它被窃听,否则在调用tomcat shutdown时可能会自行停止。

BridgeServlet没有设置osgi-context,我相信这可能只是一个" whiteboard"事情,整个servlet包含在OSGI容器中,而不是像这里那样。