Java 通过@products-ClassCastException进行远程EJB注入
我将继续在EJB中表达我似乎永无止境的误解: 我使用JBoss8(Wildfly 8.1)作为我的应用服务器 我目前正在为这个问题构建一个解决方案,即Inpustreams不能通过RMI传递到远程EJB(我一想到这个问题就绝对有意义) 我不能替换现有的资源接口(将Inpustream写入文件),我构建了以下3个项目作为解决方案: 接口(双耳均包含库):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{
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中被加载了两次。我这里没有足够的信息告诉你原因。