我遇到了equinox服务注册表实现的服务解析问题,我不确定这是不是一个bug .
这是我的包和运行时的简短描述:
Bundle com.foo.api
-
使用接口IFooService导出com.foo.base
-
IFooService不是从ManagedService或与其相关的任何形式继承的
Bundle com.foo.impl
-
进口com.foo.base
-
进口org.osgi.service.cm
-
注册实现IFooService的FooServiceImpl以及org.osgi.service.cm中的ManagedService
-
这是FooServiceImpl的component.xml:
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"
immediate="true" name="com.foo.impl.FooServiceImpl">
<implementation class="com.foo.impl.FooServiceImpl"/>
<service>
<provide interface="com.foo.api.IFooService"/>
<provide interface="org.osgi.service.cm.ManagedService"/>
</service>
<property name="service.pid" value="fooservice"/>
</scr:component>
Bundle com.foo.user
-
进口com.foo.base
-
进口org.osgi.service.cm
-
实现了一个需要IFooService的组件(它只请求此接口而不是ManagedService接口)
-
component.xml
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"
name="com.foo.user.BarComponentImpl"
enabled="true" immediate="true">
<implementation class="com.foo.user.BarComponentImpl" />
<reference interface="com.foo.api.IFooService"
name="fooService" policy="static" cardinality="1..1"
bind="bindFooService" unbind="unbindFooService"/>
</scr:component>
运行时
我正在使用equinox,在config.ini中加载了上面描述的包,org.eclipse.osgi.service和org.apache.felix.configadmin . (当然,除了其他人,但他们现在不感兴趣)
org.eclipse.osgi.service和org.apache.felix.configadmin都提供了包org.osgi.service.cm
-
org.eclipse.osgi.servce提供1.4版
-
org.apache.felix.configadmin提供程序版本1.5
问题
根据config.ini中bundle的顺序,com.foo.user可能无法获得对FooServiceImpl的依赖 .
调试到equinox运行时我发现这发生了:
-
com.foo.impl使用org.osgi.service.com 1.4版(来自org.eclipse.osgi.service包)
-
com.foo.user使用org.osgi.service.com 1.5版(来自org.apache.felix.configadmin包)
-
equinox注册表检测到com.foo.user已知接口IFooService,但是由IFooServiceImpl实现的接口ManagedService在com.foo.impl和com.foo.user之间不兼容 . 注册表不会返回服务引用 . 虽然声明性服务实现将依赖关系列为使用osgi控制台上的
comp
命令解析的 .
在这种情况下,这是理想的行为吗?在请求IFooService时框架是否应该返回对FooServiceImpl的引用,即使该服务实现了另一个与using bundle不兼容的接口?
我没有在OSGi规范中找到任何声明,但在eclipse打开bug之前我想听听专家的想法 .
更新
感谢BJ Hargrave解决了主要问题(见下文),但我仍然想知道为什么框架以不同方式处理这两种情况
-
Bundle A 请求IFooService,它只导入com.foo.api
-
Bundle B 请求IFooService,它导入com.foo.api和org.osgi.service.cm(但在"wrong version"中)
Bundle A 获取对服务的引用, Bundle B 没有 .
什么区别
-
"an interface is not known by a bundle"和
-
"an interface is imported in an incompatbile version"
什么时候这个接口在请求服务时没有被实际使用?
2 回答
它仅被指定为返回与请求者兼容的类型的服务 . 您没有提供有关如何注册和查找相关服务的详细信息,以提供更明确的答案 .
这里的解决方案是不安装
org.eclipse.osgi.service
包 . 诸如此类的捆绑(不相关的导出包的集合)会导致这些问题 .org.eclipse.osgi.service
在编译时非常有用,因为您可以访问大量服务 . 但是在运行时,它会产生你看到的那类问题 . 在运行时,最好让服务实现导出包,就像Felix CM那样,或者让bundle只导出服务包来支持实现及其客户端 .OSGi提供
osgi.cmpn.jar
,类似于org.eclipse.osgi.service
,用于编译时 . 这个jar的最新版本包含一个无法解决的要求,以防止人们在运行时将jar用作bundle .我同意BJ的观点,这可能是OSGi中的正常行为 . 您可以尝试解决问题的方法是为每个接口单独注册服务 . 如果这仍然没有帮助你可以创建一个实现ManagedService的spearate类,它将配置更新转发给主服务 .