【问题标题】:Cannot start bundle programmatically无法以编程方式启动捆绑包
【发布时间】:2017-11-05 05:38:37
【问题描述】:

注意:在我的情况下,如果这很重要,我会使用 Apache Felix 实现。

我已经编写了我用作测试的捆绑包。这是一个非常简单的“Hello World”捆绑包,在启动/停止时只向stdout 打印消息:

public class Activator implements BundleActivator {

    @Override
    public void start(BundleContext context) throws Exception {
        System.out.println("Hello, World.");
    }

    @Override
    public void stop(BundleContext context) throws Exception {
        System.out.println("Goodbye, World.");
    }

}

还有一个 MANIFEST 文件,因为当我通过标准分发 (Apache Felix) 控制台从标准分发 (which can be downloaded here) 部署上述捆绑包时,该文件相当没有意义,因此捆绑包开始并打印出消息。


我尝试做的下一步是使用编程方法部署相同的捆绑包。不幸的是,这对我不起作用。我的代码如下所示:

public static void main(String[] args) throws Exception {
    FrameworkFactory frameworkFactory = getFrameworkFactory();
    Framework framework = frameworkFactory.newFramework(null);

    System.out.println("BundleID = " + framework.getBundleId());
    System.out.println("State = " + getState(framework.getState()));

    framework.init();

    System.out.println("BundleID = " + framework.getBundleId());
    System.out.println("State = " + getState(framework.getState()));

    BundleContext bundleContext = framework.getBundleContext();
    bundleContext.addBundleListener((event) -> {
        System.out.println("Bundle Changed Event");
    });
    bundleContext.addFrameworkListener((event) -> {
        System.out.println("Framework Event");
    });
    bundleContext.addServiceListener((event) -> {
        System.out.println("Service Changed Event");
    });

    Bundle bundle = bundleContext.installBundle("file://<absolute-path-to-bundle-jar-same-as-above");

    System.out.println("BundleID = " + bundle.getBundleId());
    System.out.println("State = " + getState(bundle.getState()));

    bundle.start();

    System.out.println("BundleID = " + bundle.getBundleId());
    System.out.println("State = " + getState(bundle.getState()));
}

private static FrameworkFactory getFrameworkFactory() throws IllegalStateException {
    ServiceLoader<FrameworkFactory> loader = ServiceLoader.load(FrameworkFactory.class);

    FrameworkFactory factory = null;
    for (FrameworkFactory iterator : loader) {
        if (factory != null) {
            throw new IllegalStateException("Ambiguous SPI implementations.");
        }

        factory = iterator;
    }

    return factory;
}

private static String getState(int state) {
    switch (state) {
    case Bundle.UNINSTALLED:
        return "UNINSTALLED";
    case Bundle.INSTALLED:
        return "INSTALLED";
    case Bundle.RESOLVED:
        return "RESOLVED";
    case Bundle.STARTING:
        return "STARTING";
    case Bundle.STOPPING:
        return "STOPPING";
    case Bundle.ACTIVE:
        return "ACTIVE";
    default:
        throw new IllegalStateException("Unknown state");
    }
}

输出如下:

BundleID = 0
State = INSTALLED
BundleID = 0
State = STARTING
Bundle Changed Event
BundleID = 1
State = INSTALLED
BundleID = 1
State = INSTALLED

据我所知,bundle 已安装,但最后 4 行表明 bundle.start() 因某种原因被忽略。

您能指出我缺少什么来完成这项工作吗?

【问题讨论】:

    标签: osgi osgi-bundle embedded-osgi


    【解决方案1】:

    经过一小时的调试和更仔细地阅读javadoc,这种情况正在发生,因为框架只是被初始化而不是被启动。要使示例工作,您只需在framework.init() 之后添加framework.start()(或者只需调用framwork.start(),如果需要,它会调用framework.init())。

    我将留下这些信息,因为有一些令人困惑的事情:

    1. Apache Felix 的官方文档包含有关将框架嵌入主机应用程序的信息。不幸的是,只有一个例子使用了Apache Felix 自定义机制,这使得它不能移植到其他实现中。令人困惑的是warning note,如果您想创建便携式解决方案,您应该使用init()getBundleContext()。全文引用如下:

    警告 felix.systembundle.activators 配置属性特定于 Felix 框架实现。如果您希望您的代码与其他框架实现一起使用,您应该在框架实例上调用init() 并直接使用getBundleContext()。否则,方法将非常相似。

    1. init()方法的无参数版本的JavaDoc没有提到初始化与启动框架不同,尽管init(FrameworkListener...)有这样的信息。

    在调用 start 之前,该框架不会真正启动。

    【讨论】:

      猜你喜欢
      • 2015-02-06
      • 2019-06-28
      • 2021-08-08
      • 1970-01-01
      • 2015-07-04
      • 2011-11-09
      • 2012-04-12
      • 2018-10-07
      • 2012-10-10
      相关资源
      最近更新 更多