ClassCastException lors de la conversion d’une vue EJB consultée dans AS7

Je déploie 2 EAR sur JBoss AS 7.1.0.Alpha1-SNAPSHOT (version post 7.0.1.Final). Les deux déploient bien.

J’ai une classe EJB Singleton intégrée dans un fichier JAR, dans l’un des fichiers EAR:

@Startup @Singleton // one of @Local(Store.class), @Remote(Store.class), @LocalBean @TransactionAtsortingbute(TransactionAtsortingbuteType.NOT_SUPPORTED) @Transactional(TransactionPropagation.SUPPORTS) public class StoreFront implements Store { ... public interface Store { ... 

Lorsqu’il se déploie, il est indiqué que l’EJB est lié à:

 "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" 

Jusqu’ici tout va bien. Lorsque j’essaie de le rechercher via JNDI à partir d’une classe non-CDI, non-EJB dans un fichier JAR au sein du fichier EAR OTHER déployé, il ne peut être trouvé que dans les noms JNDI sous “global” – à nouveau, attendu.

Cependant, lorsque j’essaie de convertir l’object résultant en classe d’interface réelle:

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

Je reçois l’exception suivante:

 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] 

Si le EJB est annoté avec l’un des éléments suivants:

 @Local(Store.class) @Remote(Store.class) @LocalBean 

ça ne fait aucune différence. Si je comprends bien, le fait qu’il renvoie une “vue” par procuration est normal. Cependant, ne devrais-je pas pouvoir convertir cette vue vers l’interface? La combinaison du nom JNDI global que j’utilise et du fait que j’effectue une conversion vers Store ou StoreFront ne semble pas faire la différence. Impossible d’effectuer une conversion quelle que soit la combinaison, même lorsque l’exception est semblable à jam.store.core.Store$$$view1 cannot be cast to jam.store.core.Store , avec les noms de classe correspondants (de base)

Quelqu’un peut-il indiquer ce que je fais mal?

Ceci est un bogue dans AS7: https://issues.jboss.org/browse/AS7-1658

Une solution de contournement possible consiste à ne pas convertir l’object renvoyé, puis à l’utiliser pour déclencher des méthodes par reflection . Bien maladroit cependant.

Une meilleure approche consiste à déployer les interfaces partagées dans un module jboss et à inclure ce module dans le chemin de classe des deux artefacts avec (lors de l’utilisation de maven).

    ${jboss.nonjee.modules}   

Aussi, je reçois de l’aide pour ce commentaire;):

David Lloyd a ajouté un commentaire – 07 / Mar / 12 16:02 C’est parce que vous utilisez des interfaces locales. Lors de l’utilisation d’interfaces locales, vous ne pouvez disposer que d’une copie de la classe d’interface (c’est ce qui la rend locale). Basculez vers des interfaces distantes (ou utilisez Class-Path pour obtenir vos interfaces locales au lieu de les dupliquer) et le problème devrait disparaître.

J’avais le même problème J’ai essayé de placer la classe Interface en tant que module sperate, de l’inclure dans une oreille et de l’inclure en tant que fournie dans l’autre oreille; Dans JBOSS, les classes de chaque fichier EAR sont chargées par un chargeur de classes distinct. Ainsi, si un EAR a la classe A et qu’un autre a la même classe A, vous obtenez une exception de transfert de classe. Ainsi, dans le second EAR, indiquez la dépendance fournie et dans jboss-deployment-structure.xml, ajoutez le premier EAR en tant que dépendance de module. Notez que la dépendance du module dynamic peut garantir que le nom du fichier EAR soit constant. Vous pouvez spécifier sous la balise de construction du fichier EAR pour résoudre ce problème.

Également changé la recherche de local à distant – voir ci-dessous, et inclus le module maven contenant l’interface dans les deux modules

 //jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); TO jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.naming.remote.client.InitialContextFactory"); 

Et vous voudriez changer la recherche de 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"); 

Et puisque l’oreille est généralement enregistrée avec la version comme celle-ci

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

et vous ne voulez pas que votre code recherche dans votre code, vous devez faire deux autres choses. Dans votre application.xml du répertoire maven de votre générateur EAR (src \ main \ resources \ application.xml), vous devez append la balise “nom-application” comme

    Task Controller EAR TaskControllerEAR TaskControllerEAR  TaskController.jar  lib  

et dans votre pom pour générer le pom, vous devez fournir une référence au fichier application.xml comme

 org.apache.maven.plugins maven-ear-plugin 2.4.2  5 lib src/main/resources ${project.basedir}/src/main/resources/application.xml 

  false               

Voici la trace de la stack pour référence

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

Même problème également si votre client EJB se trouve dans un EAR et que l’implémentation d’EJB se trouve dans un autre “service” -EAR, et que vous appelez une méthode @Remote Interface sur l’EJB renvoyant un object complexe au lieu d’un type primitif. L’object complexe renvoyé est également déclaré en tant qu’interface, correctement déclaré, connu et disponible pour le client EJB. L’implémentation Object renvoyée est elle-même contenue dans le “service” -EAR avec l’implémentation EJB cible. Malgré un tel code conforme, JBoss échoue lors d’une exception de conversion de classe.

J’ai remarqué que vous pouvez en effet conserver une interface @Remote pour déclarer toutes les méthodes EJB cibles, mais que vous ne pouvez utiliser qu’une déclaration de classe en clair pour tous les objects renvoyés par ces méthodes. Si vous déclarez les objects renvoyés en tant qu’interfaces, des exceptions de conversion de classe sont définies dans JBoss.

Ceci est une limitation (ou un bug) dans JBoss; cela fonctionne dans Glassfish et WebLogic où nous avions le même code une fois exécuté.

Le même problème s’est produit si vous avez plusieurs fichiers JAR contenant vos EJB dans votre fichier EAR.

Échantillon:

Tu as

  • un fichier myEJB.jar qui contient l’ensemble de vos EJB
  • un myWebApp.war qui contient vos classes / ressources Web
  • un myEnterprise.ear qui contient myEJB.jar et myWebApp.jar

Si votre myWebApp.war contient également le fichier myEJB.jar lui-même, vous aurez alors cette erreur (ClassCastExc). Il semble que l’object EJB soit créé dans le fichier myEJB.jar du fichier myEnterprise.ear. Et si vous allez ensuite convertir cet object dans la même classe que myEJB.jar à l’intérieur de myWebApp.war, cela ne fonctionnera pas, car cette classe est définie dans un autre fichier jar.

Si vous avez cette erreur, vous devez supprimer le fichier myEJB.jar de votre fichier war et le ClassCastExc est parti …