java 在 AS7 中投射查找的 EJB 视图时出现 ClassCastException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7269680/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ClassCastException when casting looked-up EJB view in AS7
提问by Ben Kirby
I have am deploying 2 EARs onto JBoss AS 7.1.0.Alpha1-SNAPSHOT (post 7.0.1.Final version). Both deploy fine.
我正在将 2 个 EAR 部署到 JBoss AS 7.1.0.Alpha1-SNAPSHOT(7.0.1.Final 版本之后)。两者都部署得很好。
I have an EJB Singleton class packaged within a JAR, within one of the EARs:
我有一个 EJB Singleton 类打包在 JAR 中,在其中一个 EAR 中:
@Startup
@Singleton
// one of @Local(Store.class), @Remote(Store.class), @LocalBean
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@Transactional(TransactionPropagation.SUPPORTS)
public class StoreFront implements Store {
...
public interface Store {
...
When it deploys, it says the EJB is bound to:
当它部署时,它说 EJB 绑定到:
"java:app/store-core-2011.1.2-SNAPSHOT/StoreFront"
"java:app/store-core-2011.1.2-SNAPSHOT/StoreFront!uk.co.magus.jam.store.core.Store"
"java:module/StoreFront"
"java:module/StoreFront!uk.co.magus.jam.store.core.Store"
"java:global/store-ear-2011.1.2-SNAPSHOT/store-core-2011.1.2-SNAPSHOT/StoreFront!uk.co.magus.jam.store.core.Store"
"java:global/store-ear-2011.1.2-SNAPSHOT/store-core-2011.1.2-SNAPSHOT/StoreFront"
So far, so good. When I try to look it up via JNDI from a non-CDI, non-EJB class within a JAR within the OTHER deployed EAR, it can only be found on the JNDI names under 'global' - again, expected.
到现在为止还挺好。当我尝试通过 JNDI 从其他部署的 EAR 内的 JAR 中的非 CDI、非 EJB 类中查找它时,它只能在“全局”下的 JNDI 名称上找到 - 同样,预期。
However, when I try to cast the resulting object to the actual interface class:
但是,当我尝试将生成的对象转换为实际的接口类时:
Object lookupObject = new InitialContext().lookup(jndiName);
Store store = (StoreFront)lookupObject;
I get the following exception:
我收到以下异常:
11:17:52,402 ERROR [jam.core.link.LinkListener] (Thread-45) Exception when casting to Store after lookup with [java:global/store-ear-2011.1.2-SNAPSHOT/store-core-2011.1.2-SNAPSHOT/StoreFront]: java.lang.ClassCastException: jam.store.core.Store$$$view1 cannot be cast to jam.store.core.Store
at jam.core.link.LinkListener.getStore(LinkListener.java:108) [core-jar-2011.1.2-SNAPSHOT.jar:]
at jam.core.link.LinkListener.postLoad(LinkListener.java:27) [core-jar-2011.1.2-SNAPSHOT.jar:]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [:1.6.0_07]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [:1.6.0_07]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [:1.6.0_07]
at java.lang.reflect.Method.invoke(Method.java:597) [:1.6.0_07]
at org.hibernate.ejb.event.ListenerCallback.invoke(ListenerCallback.java:48)
at org.hibernate.ejb.event.EntityCallbackHandler.callback(EntityCallbackHandler.java:96)
at org.hibernate.ejb.event.EntityCallbackHandler.postLoad(EntityCallbackHandler.java:89)
at org.hibernate.ejb.event.EJB3PostLoadEventListener.onPostLoad(EJB3PostLoadEventListener.java:49)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:264)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1012)
at org.hibernate.loader.Loader.doQuery(Loader.java:889)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:289)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
at org.hibernate.loader.Loader.loadEntity(Loader.java:2058)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:81)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:71)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3686)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:446)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:427)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:204)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:251)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:148)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:947)
at org.hibernate.internal.SessionImpl.get(SessionImpl.java:863)
at org.hibernate.internal.SessionImpl.get(SessionImpl.java:856)
at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:787)
at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:762)
at org.jboss.as.jpa.container.AbstractEntityManager.find(AbstractEntityManager.java:220) [jboss-as-jpa-7.1.0.Alpha1-SNAPSHOT.jar:7.1.0.Alpha1-SNAPSHOT]
at jam.core.dao.GenericDAO.findById(GenericDAO.java:87) [core-jar-2011.1.2-SNAPSHOT.jar:]
at harvest.service.HarvesterDAOUtil.loadLink(HarvesterDAOUtil.java:251) [harvest-sar-2011.1.2-SNAPSHOT.jar:]
at harvest.service.1779224926$Proxy$_$$_WeldSubclass.loadLink(1779224926$Proxy$_$$_WeldSubclass.java) [harvest-sar-2011.1.2-SNAPSHOT.jar:]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [:1.6.0_07]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [:1.6.0_07]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [:1.6.0_07]
at java.lang.reflect.Method.invoke(Method.java:597) [:1.6.0_07]
at org.jboss.interceptor.proxy.SimpleInterceptionChain.invokeNextInterceptor(SimpleInterceptionChain.java:112) [jboss-interceptor-core-2.0.0.Alpha3.jar:2.0.0.Alpha3]
at org.jboss.interceptor.proxy.InterceptorInvocationContext.proceed(InterceptorInvocationContext.java:119) [jboss-interceptor-core-2.0.0.Alpha3.jar:2.0.0.Alpha3]
at org.jboss.seam.transaction.TransactionInterceptor.work(TransactionInterceptor.java:194) [seam-persistence-3.0.0.Final.jar:]
at org.jboss.seam.transaction.Work.workInTransaction(Work.java:54) [seam-persistence-3.0.0.Final.jar:]
at org.jboss.seam.transaction.TransactionInterceptor.aroundInvoke(TransactionInterceptor.java:188) [seam-persistence-3.0.0.Final.jar:]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [:1.6.0_07]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [:1.6.0_07]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [:1.6.0_07]
at java.lang.reflect.Method.invoke(Method.java:597) [:1.6.0_07]
at org.jboss.interceptor.proxy.InterceptorInvocation$InterceptorMethodInvocation.invoke(InterceptorInvocation.java:72) [jboss-interceptor-core-2.0.0.Alpha3.jar:2.0.0.Alpha3]
at org.jboss.interceptor.proxy.SimpleInterceptionChain.invokeNextInterceptor(SimpleInterceptionChain.java:82) [jboss-interceptor-core-2.0.0.Alpha3.jar:2.0.0.Alpha3]
at org.jboss.interceptor.proxy.InterceptorMethodHandler.executeInterception(InterceptorMethodHandler.java:133) [jboss-interceptor-core-2.0.0.Alpha3.jar:2.0.0.Alpha3]
at org.jboss.interceptor.proxy.InterceptorMethodHandler.invoke(InterceptorMethodHandler.java:112) [jboss-interceptor-core-2.0.0.Alpha3.jar:2.0.0.Alpha3]
at org.jboss.weld.bean.proxy.CombinedInterceptorAndDecoratorStackMethodHandler.invoke(CombinedInterceptorAndDecoratorStackMethodHandler.java:65) [weld-core-1.1.2.Final.jar:2011-07-26 15:02]
at harvest.service.1779224926$Proxy$_$$_WeldSubclass.loadLink(1779224926$Proxy$_$$_WeldSubclass.java) [harvest-sar-2011.1.2-SNAPSHOT.jar:]
at harvest.service.CombineHarvester.workOnLinkId(CombineHarvester.java:259) [harvest-sar-2011.1.2-SNAPSHOT.jar:]
at harvest.service.CombineHarvester.harvestCache(CombineHarvester.java:223) [harvest-sar-2011.1.2-SNAPSHOT.jar:]
at harvest.service.CombineHarvester.performHarvest(CombineHarvester.java:136) [harvest-sar-2011.1.2-SNAPSHOT.jar:]
at harvest.service.CombineHarvester.run(CombineHarvester.java:107) [harvest-sar-2011.1.2-SNAPSHOT.jar:]
at java.lang.Thread.run(Thread.java:619) [:1.6.0_07]
Whether the EJB is annotated with one from any of
EJB 是否使用以下任何一个注解
@Local(Store.class)
@Remote(Store.class)
@LocalBean
makes no difference. As I understand it, the fact it's returning a proxy 'view' is normal. However, shouldn't I be able to cast that view to the interface? The combination of which global JNDI name I use and whether I cast to Store or StoreFront also appears to make no difference - unable to cast whatever the combination, even when the exception is like jam.store.core.Store$$$view1 cannot be cast to jam.store.core.Store
, with matching (base) class names
没什么区别。据我了解,它返回代理“视图”的事实是正常的。但是,我不应该能够将该视图投射到界面上吗?我使用的全局 JNDI 名称的组合以及我是否转换为 Store 或 StoreFront 似乎也没有区别 - 无法转换任何组合,即使异常类似于jam.store.core.Store$$$view1 cannot be cast to jam.store.core.Store
,具有匹配的(基)类名称
Can anyone point out what I'm doing wrong?
谁能指出我做错了什么?
采纳答案by Ben Kirby
This is a bug in AS7: https://issues.jboss.org/browse/AS7-1658
这是 AS7 中的一个错误:https://issues.jboss.org/browse/AS7-1658
One possible workaround is not to cast the returned object, and then use it to fire methods via reflection. Well clunky though.
一种可能的解决方法是不强制转换返回的对象,然后使用它通过反射来触发方法。不过好笨重。
回答by Riccardo Pasquini
A better approach is to deploy the shared interfaces in a jboss module and include that module in both artifacts' classpath with (when using maven)
更好的方法是在 jboss 模块中部署共享接口,并将该模块包含在两个工件的类路径中(使用 maven 时)
<archive>
<manifestEntries>
<Dependencies>${jboss.nonjee.modules}</Dependencies>
</manifestEntries>
</archive>
回答by Pavel
Also i get help with this commentary ;):
我也得到了有关此评论的帮助;):
David Lloyd added a comment - 07/Mar/12 4:02 PM It's because you're using local interfaces. When using local interfaces, you may only have one copy of the interface class (that's what makes it local). Switch to using remote interfaces (or, use Class-Path to get your local interfaces instead of duplicating them) and the problem should disappear.
David Lloyd 添加了评论 - 07/Mar/12 4:02 PM 这是因为您使用的是本地接口。使用本地接口时,您可能只有接口类的一个副本(这就是使其成为本地的原因)。切换到使用远程接口(或者,使用 Class-Path 来获取本地接口而不是复制它们),问题应该会消失。
回答by Alex Punnen
I was getting the same problem; Tried to put the Interface class as a sperate module and include it in one Ear and include it as a provided in the other Ear;
In JBOSS the classes in each EAR are loaded by a separate class loader. So if one EAR has Class A , and another has the same Class A , then you get a class cast exception. So in the second EAR give the dependency as provided and in jboss-deployment-structure.xml add the first EAR as a module dependency. Note that the dynamic module dependency might warrant the EAR file name to be constant; You can specify <finalName>
under the build tag for the EAR file to fix this
我遇到了同样的问题;试图将 Interface 类作为一个单独的模块,并将其包含在一个 Ear 中,并将其作为一个提供在另一个 Ear 中;在 JBOSS 中,每个 EAR 中的类由单独的类加载器加载。因此,如果一个 EAR 具有 Class A ,而另一个 EAR 具有相同的 Class A ,那么您会得到一个类转换异常。因此,在第二个 EAR 中提供所提供的依赖项,并在 jboss-deployment-structure.xml 中添加第一个 EAR 作为模块依赖项。请注意,动态模块依赖性可能会保证 EAR 文件名是恒定的;您可以<finalName>
在 EAR 文件的构建标记下指定以解决此问题
Also changed the lookup from local to remote - see below, and included the maven module containing the interface in both the modules
还将查找从本地更改为远程 - 见下文,并在两个模块中包含了包含接口的 maven 模块
//jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
TO
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.naming.remote.client.InitialContextFactory");
And you would want to change the lookup from java:app to java:global
并且您希望将查找从 java:app 更改为 java:global
final javax.naming.Context context = new InitialContext(jndiProperties);
AsyncFutureItf test =(AsyncFutureItf)context.lookup
//("java:app/Executor/AsyncFutureTest!pacakge.AsyncFutureItf");
("java:global/ExecutorEar/Executor/AsyncFutureTest!package.AsyncFutureItf");
And since the Ear is usually registered with the version like this
而且由于耳朵通常使用这样的版本注册
java:global/ExecutorEar-<version>/Executor/AsyncFutureTest!package.AsyncFutureItf
and you do not want version driven lookup in your code, you need to do two more things. In your application.xml in your EAR builder maven dir (src\main\resources\application.xml) you need to add the "application-name" tag like
并且您不想在代码中进行版本驱动的查找,您还需要做两件事。在 EAR 构建器 maven 目录 (src\main\resources\application.xml) 中的 application.xml 中,您需要添加“application-name”标签,如
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_5.xsd" version="5">
<description>Task Controller EAR</description>
<display-name>TaskControllerEAR</display-name>
<application-name>TaskControllerEAR</application-name>
<module>
<ejb>TaskController.jar</ejb>
</module>
<library-directory>lib</library-directory>
</application>
and in your pom to generate the pom you need to provide a reference to the application.xml like
并在您的 pom 中生成 pom,您需要提供对 application.xml 的引用,例如
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.4.2</version>
<configuration>
<version>5</version>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<earSourceDirectory>src/main/resources</earSourceDirectory>
<applicationXml>${project.basedir}/src/main/resources/application.xml</applicationXml>
...
...
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<ear-subdeployments-isolated>false</ear-subdeployments-isolated>
<sub-deployment name="MROControllerRest.war">
<exclusions>
<module name="org.apache.commons.logging" />
<module name="org.slf4j" />
<module name="org.slf4j.ext" />
<module name="org.slf4j.jcl-over-slf4j" />
<module name="org.slf4j.impl" />
<module name="org.apache.log4j" />
</exclusions>
<dependencies>
<module name="org.slf4j" slot="1.7.5" />
<module name="logger" />
<module name="deployment.TaskControllerEAR.ear.TaskController.jar" export="TRUE"/>
</dependencies>
Here is the stack trace for reference
这是供参考的堆栈跟踪
java.lang.ClassCastException: com.package.TaskSplitterItf$$$view210 cannot be cast to com.package.TaskSplitterItf
回答by berhauz
Same issue too if your EJB-client is in an EAR and the EJB implementation in another "service"-EAR, and you invoke a @Remote Interface method on the EJB returning a complex Object instead of a primitive type. The complex Object being returned is also declared as an Interface, properly declared, known, and available to the EJB-client. The returned Object implementation is, it, contained in the "service"-EAR along with the target EJB implementation too. Despite such conformant code, JBoss fails on Class cast exception.
如果您的 EJB 客户端在一个 EAR 中,而 EJB 实现在另一个“服务”-EAR 中,并且您在 EJB 上调用 @Remote 接口方法返回一个复杂的对象而不是原始类型,那么同样的问题。被返回的复杂对象也被声明为一个接口,正确声明、已知并且可供 EJB 客户端使用。返回的对象实现也包含在“服务”-EAR 和目标 EJB 实现中。尽管有这样一致的代码,JBoss 还是在 Class cast 异常上失败了。
I noted that you can indeed keep a @Remote Interface for declaring all target EJB methods, but can only use a plain class declaration for all the Objects returned by those methods. If you declare the returned Objects as Interfaces, Class cast exceptions ensue in JBoss.
我注意到您确实可以保留一个@Remote 接口来声明所有目标 EJB 方法,但只能对这些方法返回的所有对象使用普通类声明。如果将返回的对象声明为接口,则 JBoss 中会发生类转换异常。
This is a limitation (or bug) in JBoss; it does work in Glassfish and WebLogic where we had the same code once running.
这是 JBoss 中的一个限制(或错误);它在 Glassfish 和 WebLogic 中确实有效,我们曾经运行过相同的代码。
回答by Steffen
Same Problem occurred if you have the jar file with your EJBs more as one time in your EAR.
如果您在 EAR 中多次使用带有 EJB 的 jar 文件,则会出现相同的问题。
Sample:
样本:
You have
你有
- a myEJB.jar file which contains all of your EJB
- a myWebApp.war which contains your web classes / resources
- a myEnterprise.ear which contains myEJB.jar and myWebApp.jar
- 包含所有 EJB 的 myEJB.jar 文件
- 包含您的网络类/资源的 myWebApp.war
- 包含 myEJB.jar 和 myWebApp.jar 的 myEnterprise.ear
If your myWebApp.war also contains the myEJB.jar by self then you will have this error (ClassCastExc). Seems that the EJB object is created inside the myEJB.jar of the myEnterprise.ear. And if you then will be cast this object into the same class of the myEJB.jar inside of the myWebApp.war this will not worked because this is class is defined in another jar.
如果您的 myWebApp.war 也包含自己的 myEJB.jar,那么您将遇到此错误 (ClassCastExc)。似乎 EJB 对象是在 myEnterprise.ear 的 myEJB.jar 中创建的。如果您随后将这个对象强制转换为 myWebApp.war 中 myEJB.jar 的同一个类,这将不起作用,因为这是在另一个 jar 中定义的类。
If you have this error you must remove the myEJB.jar from your war file and the ClassCastExc is gone ...
如果出现此错误,则必须从 war 文件中删除 myEJB.jar 并且 ClassCastExc 消失了......