Pregunta

Estamos experimentando un problema muy difícil de localizar a donde estamos viendo ClassCastExceptions a veces cuando se trata de iterar sobre una lista de objetos unmarshalled. La cosa importante es a veces , después de un reinicio del código particular funciona bien. Esto parece apuntar en la dirección de la condición de concurrencia / tiempo / carrera. Puedo confirmar que ni el JAXBContext, ni los señaleros y unmarshallers están siendo utilizados simultáneamente. Hemos llegado tan lejos como la serialización de acceso a las mismas a través de bloqueo.

Sin embargo, ya que se corre sobre una plataforma OSGi en paquetes individuales se están inicializadas de forma asíncrona a través de la primavera DM puede ser que 2 diversos paquetes están creando su JAXBContext al mismo tiempo.

En cualquier caso, le agradecería cualquier puntero hacia una explicación de lo que podría causar estos intermitentes ClassCastExceptions. El intermitente es importante ya que indican que el código en sí está trabajando normalmente bien, pero que algún factor externo parece influir en el comportamiento.

Aquí hay un ejemplo específico de la excepción (Nota Quité la compañía cosas específicas):

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 una de () construir un bucle sobre una colección de objetos TunnelType interior de un objeto unmarshalled (dijo unmarshalling funciona bien BTW).

Dado que el objeto real unmarshalling fue bien, ¿es posible que incluso físicamente JAXB para dejar objetos ElementNSImpl interior de colecciones anidadas?

El entorno de tiempo de ejecución:

  • JAXB 2.1
  • OSGi
  • Spring DM
  • El JAXBContext se inicializa con el cargador de clases del paquete que contiene las clases que se marshalled / unmarshalled
¿Fue útil?

Solución 3

Fuera de la desesperación que se dirigió a la sincronización en el objeto JAXBContext.class, viendo esto como la única posibilidad restante por alguna condición de carrera y por lo menos no hemos sido capaces de reproducir de nuevo esta cuestión. Aquí está el código crítico:

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

Otros consejos

consigo esta excepción sólo cuando me olvido de decir JAXBContext sobre la ALL-a-ser movilizados tipos podría ser tratando.

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

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

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

La cláusula sincronizado anteriormente resuelve el problema para mí también, pero parece que el contexto no debe ser una variable local. En su lugar, debe ser una variable de instancia, o una estática. Yo no era capaz de refactorizar mi código cómo me gusta, así que en vez me movía el contexto en un inicializador estático, que no es perfecto, pero parece que funciona:

 private static Unmarshaller um;

  static{
    try {
      final JAXBContext ctx = JAXBContext.newInstance(ObjectFactory.class.getPackage().getName());
      um = ctx.createUnmarshaller();
    } catch (final JAXBException e) {
      e.printStackTrace();
    }
  }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top