9

我正在将 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 类中查找它时,只能在“全局”下的 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,具有匹配的(基)类名

谁能指出我做错了什么?

4

6 回答 6

8

This is a bug in 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.

于 2011-09-02T07:19:20.487 回答
4

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

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

于 2013-09-13T21:43:20.100 回答
4

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

                <archive>
                    <manifestEntries>
                        <Dependencies>${jboss.nonjee.modules}</Dependencies>
                    </manifestEntries>
                </archive>
于 2011-09-30T14:42:02.803 回答
2

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

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

而且由于耳朵通常是用这样的版本注册的

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

并且您不想在代码中进行版本驱动的查找,您还需要做两件事。在 EAR builder maven dir (src\main\resources\application.xml) 中的 application.xml 中,您需要添加“应用程序名称”标签,例如

    <?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
于 2014-11-13T15:58:49.110 回答
1

如果您的 EAR 中多次包含带有 EJB 的 jar 文件,则会出现同样的问题。

样本:

你有

  • 一个包含所有 EJB 的 myEJB.jar 文件
  • 一个 myWebApp.war,其中包含您的 Web 类/资源
  • 包含 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 已消失...

于 2016-10-24T11:23:20.523 回答
1

如果您的 EJB 客户端位于 EAR 中,而 EJB 实现位于另一个“服务”-EAR 中,并且您在 EJB 上调用 @Remote 接口方法返回复杂对象而不是原始类型,则同样的问题。被返回的复杂对象也被声明为一个接口,正确地声明、已知并且对 EJB 客户端可用。返回的对象实现与目标 EJB 实现一起包含在“服务”-EAR 中。尽管有这样一致的代码,JBoss 在 Class cast 异常上还是失败了。

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

这是 JBoss 中的一个限制(或错误);它确实在 Glassfish 和 WebLogic 中工作,我们曾经运行过相同的代码。

于 2016-07-24T18:08:34.633 回答