osgi - osgi 服务:不满足活动服务的参考
问题描述
我有一个不满意的 osgi 服务:
ls 142
Components in bundle A:
ID State Component Name Located in bundle
90 Unsatisfied ServiceA A(bid=142)
对 ServiceB 的引用不满足:
comp 90
Component[
name = ServiceA
activate = activate
deactivate = deactivate
modified =
configuration-policy = optional
factory = null
autoenable = true
immediate = false
implementation = ServiceA
state = Unsatisfied
properties =
serviceFactory = false
serviceInterface = [ServiceA]
references = {
Reference[name = ServiceB, interface = ServiceB, policy = static, cardinality = 1..1, target = null, bind = setServiceB, unbind = unsetServiceB]
}
located in bundle = B_2.12.0.qualifier [142]
]
Dynamic information :
*The component is NOT satisfied
The following references are not satisfied:
Reference[name = ServiceB, interface = ServiceB, policy = static, cardinality = 1..1, target = null, bind = setServiceB, unbind = unsetServiceB]
Component configurations :
Configuration properties:
component.name = ServiceA
component.id = 136
objectClass = String[ServiceA]
Instances:
尽管如此,ServiceB 仍处于活动状态:
ls 52
Components in bundle B:
ID State Component Name Located in bundle
14 Active ServiceB B(bid=52)
那么为什么不满足从 ServiceA 到 ServiceB 的引用呢?重新启动捆绑包 A(停止和启动)没有帮助。在捆绑包 C 中配置工作 ServiceC 上的引用会使 ServiceC 不满意。
更新:ServiceB 已注册
osgi 控制台中“服务”命令的结果包含以下内容:
{ServiceB}={service.id=180}
Registered by bundle: Z_2.12.0.qualifier [123]
No bundles using service.
附加信息:ServiceA 和 ServiceB 的配置、初始化和注册
ServiceB 基本上是一个 apache cxf Web 服务,它实现了一个接口。该接口是从 wsdl 生成的。ServiceB 以编程方式注册。ServiceA 具有对生成接口的引用。此模式与另一个 Web 服务(比如说 ServiceC 和 ServiceD)完美配合。
如果它有帮助:在我们升级 apache cxf 之前,这种模式甚至可以在 ServiceA 和 ServiceB 之间工作。我之前没有提供这些信息,因为我担心这会使这个问题变得过于复杂。
更新:组件ServiceB的配置
考虑配置有两个部分:xml 文件和注册。xml 文件包含实现类“WebServiceConfigImpl”、提供的接口“WebServiceConfig”和一些属性。属性之一是 web 服务“ServiceB”——该服务的名称是稍后在启动过程中以编程方式注册的。
xml文件:
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="activate" deactivate="deactivate" name="ServiceB">
<implementation class="WebServiceConfigImpl"/>
<service>
<provide interface="WebServiceConfig"/>
</service>
<property name="webservice" type="String" value="ServiceB"/>
<property name="address" type="String" value="${adresse}"/>
<property name="username" type="String" value="${benutzer}"/>
<property name="password" type="String" value="${passwort}"/>
(...)
two references to other osgi services for resolving the web service configuration
</scr:component>
注册: 我们为此使用自己的 org.osgi.util.tracker.ServiceTracker。这个ServiceTracker是在bundle Z的Activator中打开的,它以“WebServiceConfig”为参数调用ServiceTracker的构造函数,所以如果提供了“WebServiceConfig”接口的Service已经注册了,这个ServiceTracker就会得到通知。我们的 SeriveTracker 实现现在读取属性“webservice”并以此名称发布 osgi 服务:
context.registerService(serviceName, service, null);
之后,该服务可用并在 osgi 控制台中激活。
更新:访问 ServiceB
通过我们的 ServiceTracker 注册后,可以通过 osgi 控制台和源代码访问 ServiceB:
ServiceTracker st = new ServiceTracker(bundleContext, "ServiceB", null);
st.open();
st.getService();
更新:访问 ServiceB 2
ServiceB 可以通过包 Z 中的源代码访问。但不能通过包 A 中的源代码访问。那么服务对象为空。
解决方案
我找到了一种以编程方式访问 ServiceB 的解决方法:
ServiceTracker st = new ServiceTracker(context, ServiceB.class.getName(), null);
st.open(true);
st.getService()
open 方法中的布尔参数会有所不同。
不幸的是,我无法回答为什么有些捆绑包可以“直接”访问 ServiceB(open 方法中不需要参数)而有些捆绑包需要“true”参数的问题。