ClassCastException cuando se lanza a la misma clase

Tengo 2 proyectos diferentes de Java, uno tiene 2 clases: dynamicbeans.DynamicBean2 y dynamicbeans.DynamicBean2 .

En el otro proyecto, cargo ambas clases dinámicamente y las almaceno en un Object

 class Form { Class beanClass; Class validatorClass; Validator validator; } 

Luego, sigo adelante y creo un objeto Validator utilizando validatorClass.newInstance() y lo validator en el validator luego creo un objeto Bean también usando beanClass.newInstance() y lo agrego a la sesión.

 portletRequest.setAttribute("DynamicBean2", bean); 

Durante el ciclo de vida del proyecto Form , llamo a validator.validate() que carga el objeto bean creado previamente desde la sesión (estoy ejecutando Websphere Portal Server). Cuando bash devolver este objeto a DynamicBean2 , falla con una ClassCastException.

Cuando retiro el objeto de la sesión usando

 faces.getApplication().createValueBinding("#{DynamicBean2}").getValue(faces); 

y verifique la clase usando .getClass() obtengo dynamicbeans.DynamicBean2 . Esta es la clase en la que quiero lanzarla; sin embargo, cuando bash, obtengo ClassCastException.

¿Alguna razón por la que estoy obteniendo esto?

No estoy siguiendo la descripción del flujo del progtwig, pero generalmente cuando obtiene ClassCastExceptions no puede explicar que ha cargado la clase con un cargador de clases y luego intenta convertirlo a la misma clase cargada por otro cargador de clases. Esto no funcionará; están representados por dos objetos de Clase diferentes dentro de la JVM y el lanzamiento fallará.

Hay un artículo sobre la carga de clases en WebSphere . No puedo decir cómo se aplica a su aplicación, pero hay varias soluciones posibles. Puedo pensar al menos:

  1. Cambie el cargador de clase de contexto manualmente. Requiere que realmente pueda obtener una referencia a un cargador de clases apropiado, lo que puede no ser posible en su caso.

     Thread.currentThread().setContextClassloader(...); 
  2. Asegúrese de que la clase sea cargada por un cargador de clases superior en la jerarquía.

  3. Serializar y deserializar el objeto. (¡Yuck!)

Sin embargo, es probable que haya una forma más apropiada para su situación particular.

Los objetos de clase se cargaron en diferentes cargadores de clases, por lo tanto, las instancias creadas desde en cada una de las clases se consideran ‘incompatibles’. Este es un problema común en un entorno donde se usan muchos cargadores de clases diferentes y se están pasando objetos. Estos problemas pueden surgir fácilmente en Java EE y entornos de portal.

La emisión de una instancia de una clase requiere que la clase vinculada al objeto que se está fundiendo sea la misma que la cargada por el cargador de clases de contexto de hilo actual.

Obtuve el problema A2AClassCastException al tratar de crear una Lista de objetos desde XML usando Apache Commons Digester.

 List templates = new ArrayList(); Digester digester = new Digester(); digester.addObjectCreate("/path/to/template", MyTemplate.class); digester.addSetNext("/path/to/template", "add"); // Set more rules... digester.parse(f); // f is a pre-defined File for(MyTemplate t : templates) { // ClassCastException: Cannot cast mypackage.MyTemplate to mypackage.MyTemplate // Do stuff } 

Como se indicó anteriormente, la causa es que el digestor no usa el mismo ClassLoader como el rest del progtwig. Ejecuté esto en JBoss, y resultó que commons-digester.jar no estaba en el directorio lib de JBoss, sino en el directorio lib de una aplicación web. Copiar el jar en mywebapp / WEB-INF / lib también resolvió el problema. Otra solución fue casll digester.setClassLoader (MyTemplate.class.getClassLoader ()), pero se siente como una solución bastante fea en este contexto.

Tuve el mismo problema con una búsqueda EJB de otro EJB. Resolví agregar @Remote (MyInterface.class) a la configuración de la clase EJB

Tuve el mismo problema al usar varias instancias de JBoss en diferentes máquinas. Para mal, no me encontré con esta publicación antes.
Había artefactos desplegados en diferentes máquinas, dos de ellos cargadores de clases declarados con un nombre idéntico. Cambié uno de los nombres de los cargadores de clases y todo funcionó bien => ¡Cuidado con copiar y pegar!

¿Por qué la ClassCastException no menciona los cargadores de clase involucrados? – Creo que sería una información muy útil.
¿Alguien sabe si habrá algo como esto disponible en el futuro? Necesitar comprobar los cargadores de la clase de 20-30 artefactos no es tan agradable. ¿O hay algo que extrañé en el texto de excepción?

EDITAR : edité el archivo META-INF / jboss-app.xml y cambié el nombre del cargador, la idea es tener un nombre único. En el trabajo, utilizamos el identificador de artefactos (único) combinado con la versión insertada por maven ({$ version}) durante la comstackción.
Usar campos dynamics es solo opcional, pero ayuda si desea implementar diferentes versiones de la misma aplicación.

   com.example:archive=unique-archive-name-{$version}   

Puede encontrar información aquí: https://community.jboss.org/wiki/ClassLoadingConfiguration

Tuve el mismo problema, y ​​finalmente encontré una solución en java.net:

Copie todos los archivos org.eclipse.persistence jar de glassfish4/glassfish/modules a WEB-INF/lib . Luego ingrese su glassfish-web.xml y establezca class-delegate en false .

Trabajó para mi !

Tuve un problema similar con JAXB y JBoss AS 7.1. El problema y la solución se describen aquí: javax.xml.bind.JAXBException: Class *** ni ninguna de sus superclase se conoce en este contexto . La excepción que se dio fue org.foo.bar.ValueSet no se puede convertir a org.foo.bar.ValueSet

Tuve el mismo problema en un EJB de wildfly. El EJB devolvía una lista de Objetos y tenía una interfaz remota y local. Utilicé la interfaz local por error, lo que funcionaba bien hasta el momento en que intentas lanzar los objetos en la lista.

Interfaz local / remota:

 public interface DocumentStoreService { @javax.ejb.Remote interface Remote extends DocumentStoreService { } @javax.ejb.Local interface Local extends DocumentStoreService { } 

El bean EJB:

 @Stateless public class DocumentStoreServiceImpl implements DocumentStoreService.Local, DocumentStoreService.Remote { 

La envoltura correcta de spring alrededor del EJB:

      

Tenga en cuenta $ Remote, puede cambiar esto a $ Local y encontrará que la interfaz local está bien, y también ejecutar los métodos sin ningún problema (desde una aplicación separada en el mismo contenedor), pero los objetos del modelo no se calculan y son desde un cargador de clases diferente si usa la interfaz local por error.

Otra opción:

Me sucedió en weblogic, pero creo que también puede suceder en otros servidores, si lo haces (simplemente) “Publicar” y, por lo tanto, algunas de tus clases se vuelven a cargar. En cambio, haz “Limpiar” para que todas las clases se vuelvan a cargar juntas.

Tenía el mismo my.package.MyClass cannot be cast to my.package.MyClass en WildFly 10.1 y, según tengo entendido, hice lo contrario a lo que describió @Emil Lundberg en su respuesta.

He agregado el módulo (que contiene my.package.MyClass ) a my.war/WEB-INF/jboss-deployment-structure.xml como una dependencia

  ...   

y eliminó el jar correspondiente de my.war/WEB-INF/lib , volvió a desplegar WAR y luego el código funcionó como se esperaba.

Por lo tanto, nos aseguramos de que resuelva el problema. Ahora, debemos asegurarnos de que el problema no vuelva, por ejemplo, cuando se ensamble e implemente la versión actualizada de WAR .

Para esto, en las fonts de esos WAR , se requiere agregar provided para esos jar en pom.xml , de modo que cuando my.war se my.war próxima vez con el código fix / enhancement inyectado , no empaquetará este jar en my.war/WEB-INF/lib .