ClassCastException при приведении искомого представления EJB в AS7 - PullRequest
9 голосов
/ 01 сентября 2011

У меня развернуто 2 EAR на JBoss AS 7.1.0.Alpha1-SNAPSHOT (пост 7.0.1. Окончательная версия). Оба развернуты нормально.

У меня есть класс 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 {
...

При развертывании говорится, что 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 из не-CDI, не-EJB-класса в JAR-файле в другом развернутом EAR, его можно найти только в именах JNDI в разделе «global» - опять же, как и ожидалось.

Однако, когда я пытаюсь привести полученный объект к классу интерфейса:

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 ]

8 голосов
/ 02 сентября 2011

Это ошибка в AS7: https://issues.jboss.org/browse/AS7-1658

Один из возможных обходных путей - не приводить возвращаемый объект, а затем использовать его для запуска методов с помощью reflections . Впрочем, неуклюжий.

4 голосов
/ 30 сентября 2011

Лучшим подходом является развертывание общих интерфейсов в модуле jboss и включение этого модуля в classpath обоих артефактов с помощью (при использовании maven)

                <archive>
                    <manifestEntries>
                        <Dependencies>${jboss.nonjee.modules}</Dependencies>
                    </manifestEntries>
                </archive>
3 голосов
/ 14 сентября 2013

Также я получаю помощь с этим комментарием;):

Дэвид Ллойд добавил комментарий - 07 / Mar / 12 16:02 Это потому, что вы используете локальные интерфейсы.При использовании локальных интерфейсов у вас может быть только одна копия класса интерфейса (именно это делает его локальным).Переключитесь на использование удаленных интерфейсов (или используйте Class-Path для получения локальных интерфейсов вместо их дублирования), и проблема должна исчезнуть.

2 голосов
/ 13 ноября 2014

У меня была такая же проблема;Попытался поместить класс Interface в качестве отдельного модуля и включить его в одно ухо, а также включить его как предоставленный в другое ухо;В JBOSS классы в каждом EAR загружаются отдельным загрузчиком классов.Таким образом, если один EAR имеет класс A, а другой - тот же класс A, вы получите исключение приведения класса.Таким образом, во втором EAR дайте зависимость, как предусмотрено, и в jboss-deploy-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");

И поскольку Ear обычно регистрируется с такой версией, как эта

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

и вы не хотите, чтобы в вашем коде осуществлялся поиск по версии, вам нужно сделать еще две вещи.В вашем application.xml в maven dir вашего EAR builder (src \ main \ resources \ 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 для созданияПом, вам нужно предоставить ссылку на 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
1 голос
/ 24 октября 2016

Та же проблема возникла, если у вас есть файл jar с вашими EJB больше, чем один раз в вашем EAR.

Пример:

У вас есть

  • файл myEJB.jar, который содержит все ваши EJB
  • myWebApp.war, который содержит ваши веб-классы / ресурсы
  • myEnterprise.ear, который содержит myEJB.jar и myWebApp.jar

Если ваш myWebApp.war также содержит myEJB.jar самостоятельно, у вас будет эта ошибка (ClassCastExc). Кажется, что объект EJB создан внутри myEJB.jar myEnterprise.ear. И если затем вы приведете этот объект к тому же классу myEJB.jar внутри myWebApp.war, это не сработает, поскольку этот класс определен в другом jar.

Если у вас есть эта ошибка, вы должны удалить myEJB.jar из вашего файла войны, и ClassCastExc пропал ...

1 голос
/ 24 июля 2016

Та же проблема, если ваш EJB-клиент находится в EAR, а реализация EJB - в другом «service» -EAR, и вы вызываете метод интерфейса @Remote для EJB, возвращающий сложный объект вместо примитивного типа.Возвращаемый сложный объект также объявляется как интерфейс, должным образом объявляется, известен и доступен для EJB-клиента.Возвращенная реализация Object также содержится в «service» -EAR вместе с целевой реализацией EJB.Несмотря на такой совместимый код, JBoss терпит неудачу при исключении приведения класса.

Я заметил, что вы действительно можете сохранить интерфейс @Remote для объявления всех целевых методов EJB, но можете использовать только объявление простого класса для всех объектов, возвращаемыхэти методы.Если вы объявляете возвращенные Объекты как Интерфейсы, исключения приведения к классу возникают в JBoss.

Это ограничение (или ошибка) в JBoss;он действительно работает в Glassfish и WebLogic, где у нас был один и тот же код.

...