Osgi 无法以编程方式启动捆绑包

Osgi 无法以编程方式启动捆绑包,osgi,osgi-bundle,embedded-osgi,Osgi,Osgi Bundle,Embedded Osgi,注意:在我的例子中,如果有必要的话,我正在使用apachefelix实现 我已经编写了一个包,我正在使用它作为测试。这是一个非常简单的“Hello World”捆绑包,在启动/停止时只需将消息打印到标准输出即可: public class Activator implements BundleActivator { @Override public void start(BundleContext context) throws Exception { Syst

注意:在我的例子中,如果有必要的话,我正在使用
apachefelix
实现

我已经编写了一个包,我正在使用它作为测试。这是一个非常简单的“Hello World”捆绑包,在启动/停止时只需将消息打印到标准输出即可:

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
文件,当我通过
apachefelix
console从标准发行版()部署上述包时,该包启动并打印出消息,因此发布该文件是毫无意义的


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

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");
    }
}
据我所知,bundle已安装,但最后4行表明由于某种原因,
bundle.start()
被忽略


您能告诉我,我缺少了什么来完成这项工作吗?

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

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

  • ApacheFelix的官方文档中有关于将框架嵌入主机应用程序的信息。不幸的是,只有一个例子使用了
    apachefelix
    定制机制,使得它无法移植到其他实现中。令人困惑的是,如果要创建可移植解决方案,应该使用
    init()
    getBundleContext()
    。以下引用整条注释:
  • 警告felix.systembundle.activators的配置属性特定于felix框架实现。如果您希望您的代码与其他框架实现协同工作,那么应该在框架实例上调用
    init()
    ,并直接使用
    getBundleContext()
    。否则,方法将非常相似

  • JavaDoc for无参数版本的
    init()
    方法不提及初始化与启动框架不同,尽管
    init(FrameworkListener…
    有此类信息
  • 在调用start之前,该框架实际上不会启动

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