2014-02-22 101 views
0

我使用JBOSS OSGI 7.1作爲我的項目。 我有2包:ClassCastException在JBOSS OSGI 7.1上

usermanagement (service provider) 
jerseyBundle (service consumer) 

當我部署並啓動usermanagement捆綁, 然後部署並啓動球衣束。

jerseyBundle getServiceReference() successful. 

然後。 我嘗試重新部署並重新啓動usermanagement。然後刷新所有包。

JerseyBundle getServiceReference() with Exception: "ClassCastException" 

這是代碼,我用它來獲得服務:

public <T> T getService(Class<T> type,List<ServiceReference> _sref) { 
try { 
    ServiceReference sref = bundleContext.getServiceReference(type.getName()); 
    if(sref != null) 
    { 
     _sref.add(sref); 
    } 

    return type.cast(bundleContext.getService(sref)); 
} catch (Exception ex) { 
    ex.printStackTrace(); 
    return null; 
} 

} 

我用的藍圖註冊服務。

我試圖ungetservice,但它沒有解決這個問題。

public void unGetService(List<ServiceReference> _sref) { 
try{  
while(_sref != null && _sref.size() >0) 
{ 
    System.err.println("==============" + bundleContext.ungetService(_sref.remove(0))); 

} 
}catch(Exception ex){ 
    ex.printStackTrace(); 
} 
} 

是否有任何方法重新部署服務提供程序包,不需要重新部署服務消費者包?

+0

當然,這是首先使用OSGi的原因之一。你需要給我們更多的信息(附帶代碼)來幫助你。 –

+0

感謝Arie van Wijngaarden,我只是更新了我的問題。請教我什麼我想念。 –

回答

1

觀察到的行爲的原因可能是OSGi通過捆綁包緩存服務對象。因此,如果你使用bundleContext.getService(sref),那麼OSGI將在內部存儲這個對象,並始終返回相同的結果,直到執行ungetService。

因此,當您更新也包含接口並刷新客戶端的服務包時,您將擁有一個接口的新類。如果您現在將舊服務對象轉換爲新接口,則會發生ClassCastException。

解決此問題的一種方法是僅在短時間內使用服務對象,然後取消它。像這樣:

ServiceReference sref = bundleContext.getServiceReference(type.getName()); 
myO = type.cast(bundleContext.getService(sref)); 
doStuff(myO); 
bundleContext.ungetService(sref) 

當然,這隻適用於不頻繁通話,因爲您有一些開銷。

另一種方式是使用ServiceTracker並對服務添加和刪除做出反應。因此,例如,您可以在您的班級中注入一項服務,該服務執行「doStuff」並在發生變化時刪除/替換服務。儘管如此,這很難做到。

事實上,這就是爲什麼有聲明式服務(DS)或藍圖等框架的原因。這些確保在服務來來去去時重新注入服務並重新啓動您的組件。 由於您已經在提供者端使用藍圖,因此您可能會嘗試在客戶端使用藍圖。藍圖客戶端不應該有你觀察到的問題。

Btw。藍圖和DS非常不同地處理服務動態。 Blueprint只注入一次代理,然後僅替換代理內的服務對象,而DS將真正重新啓動用戶組件。

+0

我使用藍圖爲普通包注入服務(使用標籤屬性和標籤引用)。但是如果球衣包是寧靜包。我使用getServicereference()和ungetService()。但它不能解決問題。也許我需要更改我的源代碼以使用Service Tracker。謝謝你的回答它幫助我更多地瞭解osgi服務。 –