Intermittent ClassCastException from ElementNSImpl to own type during unmarshalling

青春壹個敷衍的年華 提交于 2019-12-07 01:02:37

问题


We are experiencing an exceedingly hard to track down issue where we are seeing ClassCastExceptions sometimes when trying to iterate over a list of unmarshalled objects. The important bit is sometimes, after a reboot the particular code works fine. This seems to point in the direction of concurrency/timing/race condition. I can confirm that neither the JAXBContext, nor the marshallers and unmarshallers are being used concurrently. We've gone as far as serializing access to them through locking.

However, since we run on an OSGi platform where individual bundles are getting initialized asynchronously through Spring DM it can be that 2 different bundles are creating their JAXBContext at the same time.

In any case I would appreciate any pointers towards an explanation for what could cause these intermittent ClassCastExceptions. The intermittent is important since they indicate that the code itself is normally working fine but that some external factor seems to influence the behaviour.

Here's a specific example of the exception (note I removed the company specific stuff):

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)

That method at line 180 is a for() construct looping over a Collection of TunnelType objects inside of an unmarshalled object (said unmarshalling works fine BTW).

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

Runtime environment:

  • JAXB 2.1
  • OSGi
  • Spring DM
  • The JAXBContext is initialised with the ClassLoader of the bundle containing the classes to be marshalled/unmarshalled

回答1:


I get this exception ONLY when I forget to tell JAXBContext about ALL to-be-marshalled types it could be dealing with.

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



回答2:


Neither of the approaches suggested here did it for me. However this resolved my problem

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



回答3:


Out of despair we turned to synchronizing on the JAXBContext.class object, seeing this as the only remaining possibility for some race condition and at least we have not been able to reproduce this issue again. Here's the critical code:

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



回答4:


The synchronized clause above resolved the issue for me as well, but it seems like the context should not be a local variable. Instead it should be an instance variable, or a static. I wasn't able to refactor my code how I'd like it, so instead I moved the context into a static initializer, which isn't 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();
    }
  }


来源:https://stackoverflow.com/questions/377865/intermittent-classcastexception-from-elementnsimpl-to-own-type-during-unmarshall

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!