2014-02-22 42 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服务。 –