在嵌入式 Felix 框架中使用声明式服务

Using declarative services with embedded Felix framework

我正在使用 Netbeans 和 Maven 在 Mac OS X 上开发带有声明式服务的桌面 OSGi 应用程序。我从 Java 应用程序中启动 Felix 框架并使用 AutoProcessor.process().

加载我的 OSGi 包

但是,我无法激活其他服务中引用的服务。例如,我有一个服务 AImpl,它引用服务 B,如下所示:

interface A {}

interface B {}

@Component
@Service(A.class)
class AImpl implements A {
    @Reference(strategy = EVENT)
    B b;
    ...
}

@Component
@Service(B.class)
class BImpl implements B { ... }

在我创建类型为 A 的包后,AImpl.b 的值总是 null

我启动 Felix 框架的代码如下所示:

Map felixConfiguration = ...;

try {
    framework = new Felix(felixConfiguration);
    framework.init();

    final BundleContext frameworkBundleContext = framework.
                getBundleContext();

    AutoProcessor.process(felixConfiguration, frameworkBundleContext);

    framework.start();

    framework.waitForStop(0);
    System.exit(0);

} catch (Exception ex) {
    log.error("Could not start framework", ex);
    System.exit(-1);
}

felixConfiguration 包含 - 除其他外 - 目录的定义,包含 DS 服务的包将从中加载。

但是,我收到如下错误消息:

 DEBUG: BundleA (12): [AImpl(6)] Updating target filters
 DEBUG: BundleA (12): [AImpl(6)] No change in target property for dependency b: currently registered: false
 DEBUG: BundleA (12): [AImpl(6)] No existing service listener to unregister for dependency b
 DEBUG: BundleA (12): [AImpl(6)] Setting target property for dependency b to null
 DEBUG: BundleA (12): [AImpl(6)] New service tracker for b, initial active: false, previous references: {}
 DEBUG: BundleA (12): [AImpl(6)] dm b tracker reset (closed)
 DEBUG: BundleA (12): [AImpl(6)] dm b tracker opened
 DEBUG: BundleA (12): [AImpl(6)] registering service listener for dependency b
 DEBUG: BundleA (12): [AImpl(6)] Component enabled
 DEBUG: BundleA (12): [AImpl(6)] ActivateInternal
 DEBUG: BundleA (12): [AImpl(6)] Activating component from state 4
 DEBUG: BundleA (12): [AImpl(6)] Dependency not satisfied: b
 DEBUG: BundleA (12): [AImpl(6)] Not all dependencies satisfied, cannot activate

在我看来,缺少一些使 Felix 框架处理 DS 服务的 SCR 代码。我在依赖项中包含了 org.apache.felix.scr-1.8.2.jar(或者 org.apache.felix.scr-2.0.2.jarorg.apache.felix.scr.compat-1.0.2.jar),但这似乎还不够。

另一个症状,我认为它与同一问题有关:gogo 启动但无法识别 helplb 等命令,尽管所有三个包(命令、运行时、shell)可用。

我简化了示例并更改了相关方的名称以保护无辜者:-)我希望结构足够清晰以显示我正在尝试做什么以及什么不起作用。

我用谷歌搜索了 felix ds embedded 之类的术语,并找到了 this 之类的文章,这听起来像我希望的那样简单。显然我在某个地方犯了错误:我将不胜感激。

你做的第一眼看起来不错。没有所有细节很难说清楚。

您似乎在使用 scr 注释。由于现在有标准的 DS 注释,我建议您尝试一下。我得到了 full example here.

我通常使用 karaf 作为我的例子,但它也应该在普通的 felix 中工作。

您可以尝试的一件事是将您的包安装到 karaf 中并使用 karaf shell 分析是否有任何异常。只需安装 scr 功能并将您的包放入部署目录。

如果可行,那么您的包是正确的,您的 felix 部署可能有问题。

在任何情况下,您都应该检查是否可以解析所有捆绑包。当然这个有点难,只要shell不行就可以了。

在将应用程序剥离到最基本的部分后,我已经解决了这个问题,在本例中是启动 Felix 框架的代码。

问题的关键是认识到嵌入在普通 Java 程序中的 OSGi 框架是两个世界的交汇点:bundle 和 POJO。如今,许多 POJO 都与 OSGi 兼容的清单一起分发,但它们仍然是 POJO 而不是捆绑包。但是我将带有 OSGi 清单的所有内容都粘贴到捆绑目录中并使用 AutoProcessor.process() 加载它们。这包括 org.apache.felix.frameworkorg.apache.felix.main 之类的东西,还有各种处理日志记录的 POJO。这似乎导致了上述行为。

我通过以经典方式链接 org.apache.felix.frameworkorg.apache.felix.main 和日志记录 POJO 并将它们从 AutoProcessor.process() 中排除来解决这个问题。

不幸的是,slf4j-api 似乎过着双重生活,那里有很多捆绑包,我正在使用其中一些,它们需要捆绑包。我没有尝试加载它两次(经典链接和 AutoProcessor.process()),而是简单地将 pax-logging-apipax-logging-service 添加到我的 bundles 目录,然后让 AutoProcessor.process() 加载它们。

事后看来,这一切都说得通;-)