在AS7中强制查找EJB视图时出现ClassCastException

时间:2011-09-01 11:33:10

标签: java ejb jndi classcastexception jboss7.x

我正在将2个EAR部署到JBoss AS 7.1.0.Alpha1-SNAPSHOT(后7.0.1.Final版本)。两者都部署得很好。

我在其中一个EAR中的JAR中打包了一个EJB Singleton类:

@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 {
...

当它部署时,它表示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"

到目前为止,这么好。当我尝试通过JNDI从OTHER部署的EAR中的JAR内的非CDI非EJB类查找它时,它只能在'global'下的JNDI名称上找到 - 再次,预期。

但是,当我尝试将结果对象强制转换为实际的接口类时:

Object lookupObject = new InitialContext().lookup(jndiName);
Store store = (StoreFront)lookupObject;

我得到以下异常:

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$1.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]

EJB是否使用

中的任何一个注释
@Local(Store.class)
@Remote(Store.class)
@LocalBean 

没有区别。据我了解,它返回代理'视图'的事实是正常的。但是,我不应该将该视图转换为界面吗?我使用的全局JNDI名称以及我是否转换为Store或StoreFront的组合似乎也没有区别 - 即使异常类似于jam.store.core.Store$$$view1 cannot be cast to jam.store.core.Store,也无法转换任何组合,具有匹配(基类)类名称

有谁可以指出我做错了什么?

6 个答案:

答案 0 :(得分:8)

这是AS7中的错误:https://issues.jboss.org/browse/AS7-1658

一种可能的解决方法是不投射返回的对象,然后使用它通过reflection触发方法。虽然很笨重。

答案 1 :(得分:4)

更好的方法是在jboss模块中部署共享接口,并在两个工件的类路径中包含该模块(使用maven时)

                <archive>
                    <manifestEntries>
                        <Dependencies>${jboss.nonjee.modules}</Dependencies>
                    </manifestEntries>
                </archive>

答案 2 :(得分:3)

我也得到了这篇评论的帮助;):

David Lloyd添加了评论 - 07 / Mar / 12 4:02 PM 这是因为您正在使用本地接口。使用本地接口时,您可能只有一个接口类副本(这就是使其成为本地接口的副本)。切换到使用远程接口(或使用Class-Path获取本地接口而不是复制它们),问题应该消失。

答案 3 :(得分:2)

我遇到了同样的问题;试图将Interface类作为sperate模块并将其包含在一个Ear中并将其包含在另一个Ear中; 在JBOSS中,每个EAR中的类由单独的类加载器加载。因此,如果一个EAR具有A类,而另一个具有相同的A类,那么您将获得一个类强制转换异常。因此,在第二个EAR中提供依赖关系,并在jboss-deployment-structure.xml中将第一个EAR添加为模块依赖关系。请注意,动态模块依赖性可能保证EAR文件名不变;您可以在EAR文件的构建标记下指定<finalName>来修复此

还将查找从本地更改为远程 - 请参阅下文,并在两个模块中包含包含接口的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");

您可能希望将查找从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");

因为Ear通常使用像这样的版本注册

java:global/ExecutorEar-<version>/Executor/AsyncFutureTest!package.AsyncFutureItf

并且您不希望在代码中进行版本驱动的查找,您还需要做两件事。在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>

并在你的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>

这是用于参考的堆栈跟踪

java.lang.ClassCastException: com.package.TaskSplitterItf$$$view210 cannot be cast to com.package.TaskSplitterItf

答案 4 :(得分:1)

如果您的EJB客户端位于EAR中并且EJB实现位于另一个&#34; service&#34; -EAR中,并且您在EJB上调用@Remote接口方法返回复杂的Object而不是原始类型。返回的复杂对象也被声明为接口,正确声明,已知并可供EJB客户端使用。返回的Object实现包含在&#34; service&#34; -EAR中以及目标EJB实现中。 尽管有这样一致的代码,但JBoss在类强制转换异常上失败了。

我注意到您确实可以保留@Remote接口来声明所有目标EJB方法,但只能对这些方法返回的所有对象使用普通类声明。如果将返回的对象声明为接口,则JBoss中会出现类强制转换异常。

这是JBoss的限制(或bug);它在Glassfish和WebLogic中工作,我们在运行时使用相同的代码。

答案 5 :(得分:1)

如果您的EJB中的EJB文件更多次在您的EAR中,则会出现相同的问题。

样品:

你有

  • 包含所有EJB
  • 的myEJB.jar文件
  • 包含您的网络类/资源的myWebApp.war
  • 包含myEJB.jar和myWebApp.jar的myEnterprise.ear

如果你的myWebApp.war还包含myEJB.jar,则会出现此错误(ClassCastExc)。似乎EJB对象是在myEnterprise.ear的myEJB.jar中创建的。如果你随后将这个对象转换为myWebApp.war中myEJB.jar的同一个类,那么这将无效,因为这是在另一个jar中定义的类。

如果您有此错误,则必须从war文件中删除myEJB.jar并且ClassCastExc已消失...