unmarshal parse marshal jaxbunmarshaller jaxbcontext example bean java exception jaxb race-condition unmarshalling

java - parse - Intermitente ClassCastException de ElementNSImpl a su propio tipo durante unmarshalling



jaxbcontext java example (4)

Obtengo esta excepción SÓLO cuando me olvido de contarle a JAXBContext acerca de TODOS los tipos con los que podría lidiar.

JAXBContext.newInstance(MyClass1.class,MyClass2.class, [...]);

Estamos experimentando un problema extremadamente difícil de rastrear, en el que estamos viendo ClassCastExceptions algunas veces cuando intentamos iterar sobre una lista de objetos no agrupados. El bit importante es a veces , después de un reinicio, el código en particular funciona bien. Esto parece apuntar en la dirección de concurrencia / tiempo / condición de carrera. Puedo confirmar que ni el JAXBContext, ni los Marshallers ni los Unmarshallers se están usando al mismo tiempo. Hemos ido tan lejos como serializando el acceso a ellos mediante el bloqueo.

Sin embargo, dado que ejecutamos en una plataforma OSGi donde los paquetes individuales se están inicializando de forma asincrónica a través de Spring DM, puede ser que 2 paquetes diferentes estén creando su JAXBContext al mismo tiempo.

En cualquier caso, agradecería cualquier sugerencia para una explicación de lo que podría causar estas ClassCastExceptions intermitentes . Lo intermitente es importante, ya que indican que el código en sí normalmente funciona bien, pero que algún factor externo parece influir en el comportamiento.

Aquí hay un ejemplo específico de la excepción (nota que eliminé las cosas específicas de la compañía):

Caused by: java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.ElementNSImpl cannot be cast to com.foobar.TunnelType at com.foobar.NetMonitorImpl.getVpnStatus(NetMonitorImpl.java:180)

Ese método en la línea 180 es un constructo for () que hace un bucle sobre una colección de objetos TunnelType dentro de un objeto no agrupado (dicho unmarshalling funciona correctamente BTW).

Dado que el desmaquilibrio de objetos real fue bien, ¿es físicamente posible para JAXB dejar los objetos ElementNSImpl dentro de las colecciones anidadas?

Entorno de ejecución:

  • JAXB 2.1
  • OSGi
  • Spring DM
  • El JAXBContext se inicializa con el ClassLoader del paquete que contiene las clases que se ordenarán / desmaterializarán

Por desesperación, recurrimos a la sincronización en el objeto JAXBContext.class , viendo esto como la única posibilidad restante para alguna condición de carrera y, al menos, no hemos podido reproducir este problema nuevamente. Aquí está el código crítico:

synchronized (JAXBContext.class) { context = JAXBContext.newInstance(packageList, classLoader); }


La cláusula sincronizada anterior también resolvió el problema para mí, pero parece que el contexto no debe ser una variable local. En cambio, debería ser una variable de instancia, o una estática. No pude refabricar mi código como me gustaría, así que en lugar de eso moví el contexto a un inicializador estático, que no es perfecto, pero parece funcionar:

private static Unmarshaller um; static{ try { final JAXBContext ctx = JAXBContext.newInstance(ObjectFactory.class.getPackage().getName()); um = ctx.createUnmarshaller(); } catch (final JAXBException e) { e.printStackTrace(); } }


Ninguno de los enfoques sugeridos aquí lo hizo por mí. Sin embargo, esto resolvió mi problema

@XmlAnyElement(lax = true) public List<Foo> foos;