ServiceTracker 找不到现有服务
我使用 ServiceTracker 来定位 OSGi 环境中的注册服务。 我在 Bundle Activator 启动方法中得到了这段代码:
logger.debug("looking for MyService");
tracker = new ServiceTracker(ctx, MyService.class.getName(), null);
tracker.open();
MyService = ((MyService)tracker.getService());
if (MyService != null)
{
logger.debug("found MyService");
}
问题是这样的:
- 如果我安装并启动我的捆绑包 可以找到并使用服务。
- 如果我完全重新启动 OSGi MyService 就无法 我的包找到了(即为 NULL),尽管如此 我的捆绑包处于“活动”状态。
- 如果我停止/启动我的捆绑包 MyService 可以被找到并再次使用。
我认为问题不在于托管 MyService 的捆绑包,因为它显然在那里,并且如果重新启动我的捆绑包,可以再次找到它。
看起来我的捆绑包在包含依赖服务的捆绑包之前加载,这就是为什么它在重新启动后找不到它,而在我重新启动我的捆绑包后可以找到它。
一个迹象是,如果我列出可用的服务,
ServiceReference[] ref = tracker.getServiceReferences();
它在 OSGi 重新启动后找不到任何服务,但在我停止/启动查找它的包后,它确实找到了 MyService。
我试图将 Require-Bundle 引用设置为托管 MyService 的包,希望 OSGi 框架能够识别依赖关系,但它没有帮助。
有什么想法吗...?
I am using ServiceTracker in order to located registered services in our OSGi environment.
I have got this code in the Bundle Activator start method:
logger.debug("looking for MyService");
tracker = new ServiceTracker(ctx, MyService.class.getName(), null);
tracker.open();
MyService = ((MyService)tracker.getService());
if (MyService != null)
{
logger.debug("found MyService");
}
The problem is this:
- If I install and start my bundle the
service can be found and used. - If I restart OSGi completely MyService cannot be
found by my bundle (i.e. is NULL) even though that
my bundle is on status ACTIVE. - If I stop/start my bundle MyService
can be found and used again.
I don't think the problem lies in the bundle that hosts MyService since it is clearly there and can be found again if my bundle is restarted.
It looks like my bundle loads before the one that has the dependent service in it which is why it can't find it after a restart and can find it after I restart my bundle.
An indication to that is that if I list available services using
ServiceReference[] ref = tracker.getServiceReferences();
it finds no services after the OSGi restart but it does find MyService after I stop/start my bundle that looks for it.
I was trying to set Require-Bundle reference to the bundle that hosts MyService hoping that the OSGi framework will recognize the dependency but it didn't help.
Any ideas...?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您使用
BundleActivator
中的ServiceTracker
,则可以有效地冻结整个框架(因此,无法同时启动其他捆绑包)。如果为您提供服务的捆绑包在包含跟踪器的捆绑包之后启动,您将看不到该服务。这解释了为什么稍后停止并启动捆绑包可以为您提供服务。现在,如果您想跟踪和使用该服务,我将生成一个新线程来执行此操作,并使用
waitForService
而不是getService
。If you use the
ServiceTracker
from theBundleActivator
, you effectively freeze the entire framework (so, no other bundles can be started at the same time). If the bundle that provides your service starts after the bundle with the tracker, you will not see the service. This explains why stopping and starting your bundle later on gives you your service.Now, if you want to track and use the service, I would spawn a new thread to do that, and use
waitForService
in stead ofgetService
.通过使用 ServiceTracker,您正在做正确的事情。但问题是期望跟踪器服务在激活器中可用。您不想在启动捆绑包和注册服务的捆绑包之间建立排序约束。除非您确实需要在激活器的启动方法中使用该服务(并且您可能不应该),否则只需稍后在实际需要时获取该服务即可。
另一个想法是考虑使用声明式服务来管理服务依赖项。
You are doing the right thing by using a ServiceTracker. But the problem is expecting the service being tracker to be available in the activator. You do not want to establish an ordering constraint between starting your bundle and the bundle registering the service. Unless you really need to use the service in the activator's start method (and you probably shouldn't), just get the service later when you actually need.
Another idea is to consider using Declarative Services to manage your service dependencies.
OSGi 中的服务非常不稳定,因此您永远不要指望服务会在您需要时出现或在您获得后停留在那里。这就是为什么您的包应该让自己异步收到服务通知。
ServiceTracker
类接受一个ServiceTrackerCustomizer
(并且它本身就是一个),当服务来来去去时会收到通知。大多数时候,使用服务跟踪器的正确方法如下:
请注意,我们仅跟踪
MyService
服务,不使用任何定制器(我们传递null
作为构造函数的第三个参数),但要重写两个重要的方法。另一个重要的方法是modifiedService;请阅读 Javadoc 了解更多信息。管理它很快就会成为一个严重的负担,因此您应该考虑使用更高级别的抽象,例如声明性服务(如另一个答案所建议的)。
Services are very volatile in OSGi, so you should never expect one to be there when you need it or stay there after you get it. That's why your bundle should let itself be notified of services asynchronously.
The
ServiceTracker
class accepts aServiceTrackerCustomizer
(and is one itself) that is notified when services come and go.Most of the time, the right way to use a service tracker is as follows:
Note that we only track the
MyService
services and don't use any customizer (we passnull
as third parameter to the constructor), but override the two important methods instead. Another important method ismodifiedService
; please read the Javadoc for more information.Managing this can quickly become a serious burden, so you should consider using higher level abstractions like declarative services (as suggested by another answer).