Прерывистое ClassCastException от ElementNSImpl для собственного типа во время демаршаллинга - PullRequest
6 голосов
/ 18 декабря 2008

Мы сталкиваемся с чрезвычайно трудной для отслеживания проблемой, когда мы видим ClassCastExceptions иногда при попытке перебрать список неупорядоченных объектов. Важный бит - , иногда , после перезагрузки конкретный код работает нормально. Это, кажется, указывает на направление параллелизма / времени / состояния гонки. Я могу подтвердить, что ни JAXBContext, ни маршаллеры, ни маршаллеры не используются одновременно. Мы прошли сериализацию доступа к ним через блокировку.

Однако, поскольку мы работаем на платформе OSGi, где отдельные пакеты инициализируются асинхронно через Spring DM, возможно, что 2 разных пакета создают свой JAXBContext одновременно.

В любом случае я был бы признателен за любые указания на объяснение того, что может вызвать эти прерывистые ClassCastExceptions. Прерывистый режим важен, поскольку он указывает на то, что сам код обычно работает нормально, но что на его поведение влияет какой-то внешний фактор.

Вот конкретный пример исключения (обратите внимание, я удалил материал, специфичный для компании):

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)

Этот метод в строке 180 представляет собой конструкцию for (), зацикливающуюся на объектах Collection of TunnelType внутри немаршализованного объекта (указанный демонтирование работает нормально, кстати).

Учитывая, что фактическое демаршалирование объекта прошло нормально, возможно ли даже для JAXB физически оставлять объекты ElementNSImpl внутри вложенных коллекций?

Среда выполнения:

  • JAXB 2.1
  • OSGi
  • пружина DM
  • JAXBContext инициализируется загрузчиком ClassLoader пакета, содержащего классы, которые нужно маршалировать / демаршалировать

Ответы [ 4 ]

4 голосов
/ 22 марта 2009

Я получаю это исключение ТОЛЬКО тогда, когда забываю сообщить JAXBContext обо ВСЕХ подлежащих маршаллингу типах, с которыми он может иметь дело.

JAXBContext.newInstance(MyClass1.class,MyClass2.class, [...]);
1 голос
/ 10 января 2012

Ни один из предложенных здесь подходов не сделал это для меня. Однако это решило мою проблему

@XmlAnyElement(lax = true)
public List<Foo> foos;
0 голосов
/ 22 февраля 2011

Синхронизированное предложение выше решило проблему и для меня, но похоже, что контекст не должен быть локальной переменной. Вместо этого это должна быть переменная экземпляра или статическая переменная. Я не смог реорганизовать свой код так, как мне бы хотелось, поэтому вместо этого я переместил контекст в статический инициализатор, который не идеален, но, кажется, работает:

 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 голосов
/ 21 июля 2009

В отчаянии мы обратились к синхронизации на объекте JAXBContext.class, рассматривая это как единственную оставшуюся возможность для некоторого состояния гонки, и, по крайней мере, мы не смогли воспроизвести эту проблему снова. Вот критический код:

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