java - poner - ClassCastException cuando se lanza a la misma clase
setbounds java (9)
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 intento 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 intento, obtengo ClassCastException.
¿Alguna razón por la que estoy obteniendo esto?
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.
No estoy siguiendo la descripción del flujo del programa, 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:
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(...);
Asegúrese de que la clase sea cargada por un cargador de clases superior en la jerarquía.
Serializar y deserializar el objeto. (¡Yuck!)
Sin embargo, es probable que haya una forma más apropiada para su situación particular.
Obtuve el problema A2AClassCastException al tratar de crear una Lista de objetos desde XML usando Apache Commons Digester.
List<MyTemplate> templates = new ArrayList<MyTemplate>();
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 resto del programa. 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.
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.
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 compilación.
Usar campos dinámicos es solo opcional, pero ayuda si desea implementar diferentes versiones de la misma aplicación.
<jboss-app>
<loader-repository>
com.example:archive=unique-archive-name-{$version}
</loader-repository>
</jboss-app>
Puede encontrar información aquí: https://community.jboss.org/wiki/ClassLoadingConfiguration
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 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 primavera alrededor del EJB:
<bean id="documentStoreService" class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">
<property name="jndiName" value="java:global/dpc/dpc-ejb/DocumentStoreServiceImpl!santam.apps.dpc.service.DocumentStoreService$Remote"/>
<property name="businessInterface" value="santam.apps.dpc.service.DocumentStoreService$Remote"/>
<property name="resourceRef" value="true" />
</bean>
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.
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