2011-03-20 39 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瞭解更多信息。

管理這可能會很快成爲一個沉重的負擔,因此您應該考慮使用更高級別的抽象,如聲明性服務(如其他答案所示)。

相關問題