Java 通过@products-ClassCastException进行远程EJB注入

Java 通过@products-ClassCastException进行远程EJB注入,java,jakarta-ee,jboss,Java,Jakarta Ee,Jboss,我将继续在EJB中表达我似乎永无止境的误解: 我使用JBoss8(Wildfly 8.1)作为我的应用服务器 我目前正在为这个问题构建一个解决方案,即Inpustreams不能通过RMI传递到远程EJB(我一想到这个问题就绝对有意义) 我不能替换现有的资源接口(将Inpustream写入文件),我构建了以下3个项目作为解决方案: 接口(双耳均包含库): com.package.ejb public interface StorageAdapter extends Serializable{

我将继续在EJB中表达我似乎永无止境的误解:

我使用JBoss8(Wildfly 8.1)作为我的应用服务器

我目前正在为这个问题构建一个解决方案,即Inpustreams不能通过RMI传递到远程EJB(我一想到这个问题就绝对有意义)

我不能替换现有的资源接口(将Inpustream写入文件),我构建了以下3个项目作为解决方案:

接口(双耳均包含库):

com.package.ejb
public interface StorageAdapter extends Serializable{
    String store(Inpustream is); (//returns an id
    Inputstream load(String id);
}

public interface StorageAdapterProvider{
    StorageAdapter provide();
}
持久性EAR

com.package.impl
public class FileSystemStorageAdapter implements com.package.ejb.Storageadapter {
//implementation, writing to locally mounted path in filesystem...
}

com.package.impl
@Singleton
@Remote(com.package.ejb.StorageAdapterProvider.class)
public class StorageAdapterProviderBean implements  com.package.ejb.StorageadapterProvider {

    public StorageAdapter provide() {
        return new FileSystemStorageAdapter(); 
    }
}
com.package.business

public class StorageProvider {
    @EJB(looklup = "java:global/Persistence-EAR/StorageAdapterProviderBean!com.package.ejb.StorageAdapterProvider"
    private StorageAdapterProvider provider;

    @Produces
    public StorageAdapter getStorageAdapter() {
    return provider.provide();
    }

}
商务耳朵

com.package.impl
public class FileSystemStorageAdapter implements com.package.ejb.Storageadapter {
//implementation, writing to locally mounted path in filesystem...
}

com.package.impl
@Singleton
@Remote(com.package.ejb.StorageAdapterProvider.class)
public class StorageAdapterProviderBean implements  com.package.ejb.StorageadapterProvider {

    public StorageAdapter provide() {
        return new FileSystemStorageAdapter(); 
    }
}
com.package.business

public class StorageProvider {
    @EJB(looklup = "java:global/Persistence-EAR/StorageAdapterProviderBean!com.package.ejb.StorageAdapterProvider"
    private StorageAdapterProvider provider;

    @Produces
    public StorageAdapter getStorageAdapter() {
    return provider.provide();
    }

}
然后我使用
@Inject-StorageAdapter-StorageAdapter
获取Storageadapter实现的实例

Business EAR/Storageprovider然后抛出一个
ClassCastException
,告诉我
com.package.impl.FileSystemStorageAdapter不能强制转换为com.package.ejb.StorageAdapter

我向EJB添加了一些日志记录

com.package.impl
@Singleton
@Remote(com.package.ejb.StorageAdapterProvider.class)
public class StorageAdapterProviderBean implements  com.package.ejb.StorageadapterProvider {

    public StorageAdapter provide() {
    StroageAdapter ret = new FileSystemStorageAdapter();
          logger.info("EJB: RETURNING Stortage adapter");
    logger.info("    is of type:"+ret.getClass().getName());
    logger.info("        is Storageadapter: "+ (ret instanceof StorageAdapter));
    logger.info("        is FileSystemStorageAdapter: "+ (ret instanceof FileSystemStorageAdapter));
    return ret;
    }
}
它正确地打印:

EJB: RETURNING Stortage adapter
is of type:com.package.impl.FileSystemStorageAdapter
is Storageadapter: true
is FileSystemStorageAdapter: true
进一步的调查显示,当容器包装“ret”对象时抛出异常,因为如果我将@Provides实现更改为:

    Object o = provider.provide();
从EJB返回接口类型是不可能的吗? 我错过了什么? 业务EJB需要知道实现类吗在这种情况下,ClassNotFound异常不是更有意义吗

提前谢谢

编辑:

我的包装如下:

果穗

 -lib/Interfaces.jar
  -StorageAdapter
  -Storageprovider
 -persistence_ejb.jar
  -FileSystemStorageAdapter
  -StorageAdapterProviderBean
商务英语

 -lib/Interfaces.jar
  -StorageAdapter
  -Storageprovider
 -business_ejb.jar
  -StorageProvider 
 -web.war
  -Jaxrsres
 -lib
  -Interfaces.jar
   -StorageAdapter
   -Storageprovider
  -persistence_ejb.jar
   -FileSystemStorageAdapter
   -StorageAdapterProviderBean
 -business_ejb.jar
  -StorageProvider 
 -web.war
  -Jaxrsres
Jaxrsres
是通过
@Inject
我正在将这两个WAR部署到JBoss Wildlfly 8.1服务器上

我没有对配置进行任何相关更改-因此,据我所知,您请求的所有其他点都是默认值

编辑2: 这有点违背了目的,但如果我将
Persistence.ear/Persistence\u ejb.jar添加到
Business.ear
的库中,它就会起作用

商务英语

 -lib/Interfaces.jar
  -StorageAdapter
  -Storageprovider
 -business_ejb.jar
  -StorageProvider 
 -web.war
  -Jaxrsres
 -lib
  -Interfaces.jar
   -StorageAdapter
   -Storageprovider
  -persistence_ejb.jar
   -FileSystemStorageAdapter
   -StorageAdapterProviderBean
 -business_ejb.jar
  -StorageProvider 
 -web.war
  -Jaxrsres
但这显然不是我想要的:/

主要的一点是,我希望能够重新部署Persistence.ear,比如说“DatabaseStorageAdapter”,而不必触及business.ear


“梦想”是直接将Storageadapter作为EJB提供—但由于接口是固定的,需要InputStream,这是无法实现的。

我需要了解有关如何打包以及使用何种容器/类加载方案的更多详细信息。只需说,如果要将类强制转换为自身,则可以获得ClassCastException,但它是由两个不同的类加载器加载的。检查一下是否包含了不止一次的界面类,并考虑把它移到耳朵的LIB文件夹中。谢谢你的回答!因此,您建议容器不将该类识别为该接口的实现,因为一个ear的接口是由另一个类加载器加载的?是的,我认为这是一个类加载器问题。然而,这两个耳朵有独立的类装入器。您的问题在客户机ear的某个地方。正如我所指出的,我可以将EJB实现作为lib提供给客户机ear,以使其工作—但我希望能够在不涉及business.ear部署的情况下交换Persistence.ear。您有其他想法来实现这一点吗?您不需要提供实现类。我想告诉你,我相信接口类在同一个ear中被加载了两次。我这里没有足够的信息告诉你原因。