OSGi声明性服务处于活动状态,但不调用bind()

时间:2017-07-31 08:37:37

标签: java linux osgi equinox declarative-services

我在OSGi上下文中遇到了一个我不理解的声明性服务的问题。我试着解释一下:

我有FooService需要FooManagerService (1..1 static)FooManagerService引用了FooService,但它是可选的(0..n dynamic)。 目标是,如果FooService可用,则会在bind()注册(FooManagerService方法),以便FooManagerService始终包含所有可用的列表{ {1}}系统中的实现。

它在Windows上运行良好,但在Linux上遇到问题,FooService变为活动状态(FooService方法被调用),但activate()无法识别(不调用FooManagerService方法)。如果我在OSGi控制台上手动禁用并启用bind(),则FooService会识别它。

我不明白,为什么会这样。可以通过增加捆绑包的起始级别来避免FooManagerService所在的位置。但这感觉就像一个丑陋的解决方法,这就是为什么我想了解那里发生了什么。

我附上一张描述服务之间参考的图片。任何提示都表示赞赏。提前谢谢!

祝你好运

斯特芬

Service Manager Diagram

1 个答案:

答案 0 :(得分:1)

根据理论,这里有一个循环应该没问题。但是,实践中存在许多问题。

首先,您的实施应该是immediate=true。这解决了一些问题,因为它可以防止DS无法获得服务的令人讨厌的问题,因为它正在初始化。即如果FooManager和FooService impls必须是立即的。这在OSGi enRoute Cycles

中有所描述

然而,还有一个问题:-( Apache Felix DS有一个错误会导致你描述的效果。这个错误与包排序有关。这在Apache Felix JIRA 5618报告。

如果这个DS错误是问题,那么遗憾的是只有一个可靠的解决方案。不幸的是,因为它需要你下降到OSGi的肠子。解决方案是手动注册经理服务并确保DS未注册:

@Component(service={}, immediate=true )
public class FooManagerImpl implements FooManager {

   private ServiceRegistration<FooManager> registration;

   @Reference
   volatile List<FooService> foos;

   @Activate
   void activate( BundleContext context, Map<String,Object> properties ) {
     registration = context.registerService(FooManager.class, this, new Hashtable<String,Object>(properties));
   }

   @Deactivate
   void deactivate() {
      registration.unregister();
   }

   ...
}

这里的技巧是FooManager在激活之前不会注册其服务,而通常在激活之前注册

我知道Apache Felix正在研究它,但不知道它们有多远。

无论如何,周期总是糟透了。可悲的是,它们并不总是可以预防,但我当然会尝试。

  

注意:手动注册服务不会创建功能。如果使用要求/功能,则应在清单中添加服务功能以使解析器工作。如果这条线对你来说是胡言乱语,请忽略它。