2011-03-20 33 views
2

我使用ServiceTracker的在我们的OSGi环境位于注册的服务。 我有在包激活此代码入手方法:ServiceTracker的不为了找到一个现有服务

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,我的包(即NULL)即使 我的包处于状态ACTIVE状态,MyService也不能为 。
  • 如果我停止/启动我的包的MyService 可以找到并重新使用。

我不认为问题在于托管MyService的包,因为它明显存在,如果我的包已重新启动,可以再次找到它。

它看起来像我有依赖服务在它这就是为什么它不能在重新启动后找到它,我重新启动我的包后,可以找到它的一个前束负载。

的指示,那就是如果我使用

ServiceReference[] ref = tracker.getServiceReferences(); 

列出可用的服务是OSGi的重新启动后发现没有服务,但它确实为MyService找到我后,启动/停止我的包,看起来它。

我试图要求束基准设置为驻留的MyService希望OSGi框架会识别依赖关系,但它并没有帮助的捆绑。

任何想法......?

回答

4

如果使用BundleActivator中的ServiceTracker,则可以有效地冻结整个框架(因此,不能同时启动其他捆绑包)。如果提供服务的捆绑开始捆绑与跟踪器,你将不会看到该服务。这就解释了为什么在稍后停止并启动您的软件包会为您提供服务。

现在,如果你想跟踪和使用服务,我会产生一个新的线程来做到这一点,并使用waitForService而不是getService

+1

谢谢,这可能解释了原因。 ServiceTracket建议不要在start方法中使用waitForService()(“强烈建议在调用BundleActivator方法期间不使用waitForService,BundleActivator方法应该在短时间内完成”)。在那种情况下,获得对该服务的引用的更好方法是什么?也许在Activator类中保存对bundlecontext的引用,然后从bundle代码本身调用ServiceTracker.getService()? – Joly 2011-03-20 21:27:20

+1

如果你需要从你的bundle中访问BundleContext,你应该确实将它从'Activator'保存下来,然后用它来获得你的服务。我也鼓励你看一下你使用它的一些系统,比如OSGi规范中的Declarative Services,iPojo或者Apache Felix Dependency Manager。 – 2011-03-20 21:33:27

+0

我尝试了waitForService,现在这个包挂在了STARTING上,它挂起了整个bootstrap,所以我不认为waitForService是个好主意...... – Joly 2011-03-20 21:37:59

2

您通过使用ServiceTracker的做正确的事。但问题是期望在激活器中可以使用该服务。你不想建立开始你的包和包注册服务之间的排序约束。除非你真的需要在激活的启动方法使用的服务(你可能不应该),刚刚得到的服务后,当你真正需要的。

另一个想法是考虑使用声明式服务来管理您的服务依赖性。

+0

谢谢,这是有道理的... – Joly 2011-03-21 14:07:50

+0

我想在OSGI中部署两个捆绑包,但只有一个变得活跃,无论哪个先部署。我无法从第二个包中访问这些服务。任何解决方案? – Kiran 2016-02-02 02:44:11

1

服务是OSGi的非常不稳定,所以你千万不要指望当你需要它还是呆在那里你得到后,一个在那里。这就是为什么你的包应该让自己异步通知服务。

ServiceTracker类接受ServiceTrackerCustomizer(并且它本身),当服务来来去去时通知它。

大部分的时间,使用服务跟踪器的正确方法如下:

// In BundleActivator.start: 
this.serviceTracker = new ServiceTracker(bundleContext, MyService.class.getName(), null) { 
    public Object addingService(ServiceReference reference) { 
     // Get the service 
     final MyService service = (MyService)this.context.getService(reference); 

     // Do something with the service (e.g. inject it somewhere) 
     // ... 

     // Return the service to track it 
     return service; 
    } 

    public void removedService(ServiceReference reference, Object service) { 
     // Stop using the service (e.g. notify the objects that use it) 
     // ... 

     // Unget the service (very important!) 
     this.context.unget(reference); 
    } 
} 

注意,我们只跟踪MyService服务,不使用任何定制(我们通过null作为第三个参数到构造函数),而是覆盖两个重要的方法。另一个重要的方法是modifiedService;请阅读Javadoc了解更多信息。

管理这可能会很快成为一个沉重的负担,因此您应该考虑使用更高级别的抽象,如声明性服务(如其他答案所示)。

相关问题