Intermittent ClassCastException from ElementNSImpl to native type during unmarshalling

We are faced with an extremely difficult task to track down a problem when we sometimes encounter ClassCastExceptions when trying to iterate over a list of unmarshalled objects. Sometimes an important bit, after a reboot, works correctly. This seems to be pointing in the direction of the concurrency / timing / race state. I can confirm that neither JAXBContext, nor marshalers and non-marshals are used at the same time. We got to serializing access to them through blocking.

However, since we run on the OSGi platform, where individual packages are initialized asynchronously via Spring DM, it may be that two different bundles create their own JAXBContext at the same time.

In any case, I would appreciate any pointers to an explanation of what these intermittent ClassCastExceptions might cause. Intermittent is important, as they indicate that the code itself works fine, but something affects the behavior of some external factor.

Here is a specific example of an exception (note that I removed the specifics of the company):

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) 

This method on line 180 is a for () construct that loops over Collection TunnelType objects inside an object without marshalling (BTW works fine with unmarshalling).

Given that the actual unmarshalling of the object went fine, is it even physically possible for JAXB to leave ElementNSImpl objects inside nested collections?

Runtime environment:

  • JAXB 2.1
  • OSGi
  • Spring dm
  • JAXBContext is initialized with a ClassLoader package containing classes to be ordered / unmarshalled
+6
java exception race-condition jaxb unmarshalling
source share
4 answers

Out of desperation, we switched to synchronization on the JAXBContext.class object, considering this as the only remaining opportunity for some race conditions, and at least we could not reproduce this problem again. Here's the critical code:

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

I get this exception ONLY when I forget to tell JAXBContext about ALL types that can be related.

 JAXBContext.newInstance(MyClass1.class,MyClass2.class, [...]); 
+4
source share

None of the approaches suggested here have done this for me. However, this solved my problem.

 @XmlAnyElement(lax = true) public List<Foo> foos; 
+1
source share

The above synchronization condition also solved the problem, but it seems that the context should not be a local variable. Instead, it should be an instance variable or static. I was not able to reorganize my code the way I like it, so instead I moved the context to a static initializer, which is not perfect, but seems to work:

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

All Articles