OSGi 声明式服务处于活动状态,但未调用 bind()
OSGi declarative service is active, but bind() is not called
我在 OSGi 上下文中遇到了一个我不理解的声明性服务问题。我试着解释一下:
我有一个 FooService
需要 FooManagerService (1..1 static)
。 FooManagerService
引用 FooService
,但它是可选的 (0..n dynamic)
。
目标是,如果 FooService
可用,它会在 FooManagerService
处注册(调用 bind()
方法),以便 FooManagerService
始终具有所有可用 FooService
系统实现。
它在 Windows 上运行良好,但在 Linux 上我遇到了问题,即 FooService
变为活动状态(调用了 activate()
方法),但那不是' 未被 FooManagerService
识别(未调用 bind()
方法)。如果我在 OSGi 控制台上手动禁用和启用 FooService
,它会被 FooManagerService
.
识别
我不明白,为什么会这样。可以通过增加 FooServiceImpl
所在的包的起始级别来避免这种情况。但这感觉像是一个丑陋的解决方法,这就是为什么我想了解那里发生了什么。
我附上一张描述服务之间参考的图片。任何提示表示赞赏。提前致谢!
此致
史蒂芬
Service Manager Diagram
这里有个循环,按理论应该没问题。但是在实践中遇到了很多问题
首先,您的实现应该是 immediate=true
。这解决了一些问题,因为它防止了 DS 因为正在初始化而无法获得服务的讨厌问题。 IE。如果 FooManager 和 FooService impls 必须是立即的。 OSGi enRoute Cycles
中对此进行了描述
但是,还有一个问题 :-( Apache Felix DS 有一个错误,会导致您描述的效果。此错误与捆绑包排序有关。Apache Felix JIRA 5618 中报告了这一点。
如果这个 DS 错误是问题所在,那么不幸的是只有一个可靠的解决方案。不幸的是,因为它需要你深入到 OSGi 的内部。解决方法是手工注册manager service,并保证没有被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 正在处理它,但不知道他们的进展情况。
无论如何,循环 总是 糟透了。可悲的是,它们并不总是可以预防的,但我一定会尝试。
Note: registering a service manually will not create a capability. If you use Requirements/Capabilities you should add a service capability in the manifest to make the resolver work. If this line is gibberish to you, ignore it.
我在 OSGi 上下文中遇到了一个我不理解的声明性服务问题。我试着解释一下:
我有一个 FooService
需要 FooManagerService (1..1 static)
。 FooManagerService
引用 FooService
,但它是可选的 (0..n dynamic)
。
目标是,如果 FooService
可用,它会在 FooManagerService
处注册(调用 bind()
方法),以便 FooManagerService
始终具有所有可用 FooService
系统实现。
它在 Windows 上运行良好,但在 Linux 上我遇到了问题,即 FooService
变为活动状态(调用了 activate()
方法),但那不是' 未被 FooManagerService
识别(未调用 bind()
方法)。如果我在 OSGi 控制台上手动禁用和启用 FooService
,它会被 FooManagerService
.
我不明白,为什么会这样。可以通过增加 FooServiceImpl
所在的包的起始级别来避免这种情况。但这感觉像是一个丑陋的解决方法,这就是为什么我想了解那里发生了什么。
我附上一张描述服务之间参考的图片。任何提示表示赞赏。提前致谢!
此致
史蒂芬
Service Manager Diagram
这里有个循环,按理论应该没问题。但是在实践中遇到了很多问题
首先,您的实现应该是 immediate=true
。这解决了一些问题,因为它防止了 DS 因为正在初始化而无法获得服务的讨厌问题。 IE。如果 FooManager 和 FooService impls 必须是立即的。 OSGi enRoute Cycles
但是,还有一个问题 :-( Apache Felix DS 有一个错误,会导致您描述的效果。此错误与捆绑包排序有关。Apache Felix JIRA 5618 中报告了这一点。
如果这个 DS 错误是问题所在,那么不幸的是只有一个可靠的解决方案。不幸的是,因为它需要你深入到 OSGi 的内部。解决方法是手工注册manager service,并保证没有被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 正在处理它,但不知道他们的进展情况。
无论如何,循环 总是 糟透了。可悲的是,它们并不总是可以预防的,但我一定会尝试。
Note: registering a service manually will not create a capability. If you use Requirements/Capabilities you should add a service capability in the manifest to make the resolver work. If this line is gibberish to you, ignore it.