JBOSS OSGI 7.1上的ClassCastException

JBOSS OSGI 7.1上的ClassCastException,jboss,osgi,Jboss,Osgi,我在我的项目中使用了JBossOSGi7.1。 我有两包: usermanagement (service provider) jerseyBundle (service consumer) 当我部署并启动usermanagementbundle时, 然后部署并启动jersey捆绑包 jerseyBundle getServiceReference() successful. 那么。 我尝试重新部署并重新启动usermanagement。然后刷新所有包 JerseyBundle getSe

我在我的项目中使用了JBossOSGi7.1。 我有两包:

usermanagement (service provider)
jerseyBundle (service consumer)
当我部署并启动
usermanagement
bundle时, 然后部署并启动jersey捆绑包

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;
}

}
public T getService(类类型,列表){
试一试{
ServiceReference sref=bundleContext.getServiceReference(type.getName());
如果(sref!=null)
{
_补充(sref);
}
返回类型.cast(bundleContext.getService(sref));
}捕获(例外情况除外){
例如printStackTrace();
返回null;
}
}
我使用blueprint注册服务

我试图取消此服务,但它没有解决此问题

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();
}
}
public void unGetService(列表_sref){
试试{
while(_sref!=null&&u sref.size()>0)
{
System.err.println(“===================”+bundleContext.ungetService(_sref.remove(0));
}
}捕获(例外情况除外){
例如printStackTrace();
}
}

是否有任何方法可以重新部署服务提供者捆绑包,而不需要重新部署服务使用者捆绑包?

观察到这种行为的原因可能是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)或blueprint这样的框架。这些可以确保在服务出现和消失时重新注入服务并重新启动组件。 由于您已经在提供者端使用blueprint,您也可以尝试在客户端使用它。blueprint客户端不应该有您观察到的问题


顺便说一句,blueprint和DS处理服务动态的方式非常不同。Blueprint注入一次代理,然后只替换代理中的服务对象,而DS将真正重新启动用户组件。

当然,这是首先使用OSGi的原因之一。你需要给我们更多的信息(代码)来帮助你。谢谢Arie van Wijngaarden,我只是更新了我的问题。请告诉我我错过了什么。我使用blueprint为普通捆绑包注入服务(使用标记属性和标记引用)。但万一jersey捆绑包是restful捆绑包。我使用了getServicereference()和ungetService()。但这并不能解决问题。也许我需要更改我的源代码以使用服务跟踪器。谢谢你的回答,它帮助我更多地了解osgi服务。