使用嵌入式OSGi容器

nab*_*lex 5 java osgi apache-felix

我正在构建一些我希望作为OSGi包公开的模块,而没有任何与OSGi库的实际依赖关系.看来这可能是使用声明性服务选项.

但是因为我对OSGi很新(至少在创建捆绑包方面)我想测试它是否一切正常,为此我想建立一个小的嵌入式OSGi环境.

目前我有一个导出API的bundle,还提供了单个接口的stub实现.

我按照以下教程设置了一个环境:

嵌入式felix实现似乎正常工作,但有两个问题:

Bundle bundle = felix.getBundleContext().installBundle("/path/to/bundle.jar")
bundle.start();
System.out.println(bundle.getRegisteredServices());
Run Code Online (Sandbox Code Playgroud)

这打印出来,null所以当捆绑看起来好了,它似乎没有暴露任何服务.

其次,我想知道是否必须做一些特殊的事情才能使声明性服务更新并运行.我的maven依赖是:

<dependencies>
    <dependency>
        <groupId>org.apache.felix</groupId>
        <artifactId>org.apache.felix.framework</artifactId>
        <version>4.2.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.felix</groupId>
        <artifactId>org.apache.felix.scr</artifactId>
        <version>1.6.2</version>
    </dependency>
</dependencies>
Run Code Online (Sandbox Code Playgroud)

基于此处的电子邮件主题:http://mail-archives.apache.org/mod_mbox/felix-users/201111.mbox/%3CAE48C9B8172EFC48A028B60E8D6F96660143A5F336@sausexmbp02.amd.com%3E

我试图将包添加到felix启动属性:

map.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "org.apache.felix.scr; version=1.6.2");
Run Code Online (Sandbox Code Playgroud)

然而,乍一看这似乎有点乐观.如何为嵌入式felix引擎启用声明性服务?

nab*_*lex 6

这两个问题的解决方案是在加载我自己的bundle之前加载"scr"jar(用于解析声明性服务)作为bundle.

因为jar位于我的maven存储库中并且它应该跨系统工作,所以下面的一些代码从它所在的任何地方加载scr jar:

    URL url = getClass().getClassLoader().getResource("org/apache/felix/scr/ScrService.class");
    String jarPath = url.toURI().getSchemeSpecificPart().replaceAll("!.*", "");
    framework.getBundleContext().installBundle(jarPath).start();
Run Code Online (Sandbox Code Playgroud)

在这一点之后,我加载了自己的捆绑包,并正确检测到其中的服务.

在旁注中,您可以通过向初始映射添加一些属性来启用日志记录:

    map.put("ds.showtrace", "true");
    map.put("ds.showerrors", "true");
Run Code Online (Sandbox Code Playgroud)

更多属性可以在http://felix.apache.org/documentation/subprojects/apache-felix-service-component-runtime.html找到.

为了将来参考,这里是我用来启动和运行的所有代码

private void initialize() throws BundleException, URISyntaxException {
    Map<String, String> map = new HashMap<String, String>();

    // make sure the cache is cleaned
    map.put(Constants.FRAMEWORK_STORAGE_CLEAN, Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);

    // more properties available at: http://felix.apache.org/documentation/subprojects/apache-felix-service-component-runtime.html
    map.put("ds.showtrace", "true");
    map.put("ds.showerrors", "true");

    System.out.println("Building OSGi Framework");
    FrameworkFactory frameworkFactory = ServiceLoader.load(FrameworkFactory.class).iterator().next();
    Framework framework = frameworkFactory.newFramework(map);

    System.out.println("Starting OSGi Framework");
    framework.start();

    // declarative services dependency is necessary, otherwise they won't be picked up!
    loadScrBundle(framework);

    framework.getBundleContext().installBundle("file:/path/to/myBundle.jar").start();

    ServiceReference reference = framework.getBundleContext().getServiceReference("my.Interface");
    System.out.println(framework.getBundleContext().getService(reference));

    for (Bundle bundle : framework.getBundleContext().getBundles()) {
        System.out.println("Bundle: " + bundle.getSymbolicName());
        if (bundle.getRegisteredServices() != null) {
            for (ServiceReference serviceReference : bundle.getRegisteredServices())
                System.out.println("\tRegistered service: " + serviceReference);
        }
    }
}

private void loadScrBundle(Framework framework) throws URISyntaxException, BundleException {
    URL url = getClass().getClassLoader().getResource("org/apache/felix/scr/ScrService.class");
    if (url == null)
        throw new RuntimeException("Could not find the class org.apache.felix.scr.ScrService");
    String jarPath = url.toURI().getSchemeSpecificPart().replaceAll("!.*", "");
    System.out.println("Found declarative services implementation: " + jarPath);
    framework.getBundleContext().installBundle(jarPath).start();
}
Run Code Online (Sandbox Code Playgroud)