Pergunta

Estamos experimentando um extremamente difícil de rastrear problema onde estamos vendo ClassCastExceptions às vezes ao tentar iterar sobre uma lista de objetos unmarshalled. O bit importante é às vezes , após uma reinicialização do código particular funciona bem. Isto parece apontar na direção da condição de concorrência / tempo / raça. Posso confirmar que nem o JAXBContext, nem os marshallers e unmarshallers estão sendo usados ??simultaneamente. Nós temos ido tão longe como a serialização de acesso a eles por meio de bloqueio.

No entanto, desde que executado em uma plataforma OSGi, onde pacotes individuais estão sendo inicializado de forma assíncrona através da Primavera DM pode ser que 2 pacotes diferentes estão criando seu JAXBContext ao mesmo tempo.

Em qualquer caso, eu gostaria de receber qualquer ponteiros para uma explicação para o que poderia causar esses intermitente ClassCastExceptions. O intermitente é importante, uma vez que indicam que o próprio código é normalmente funcionando bem, mas que algum fator externo parece influenciar o comportamento.

Aqui está um exemplo específico de exceção (nota eu removi o material empresa específica):

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)

Esse método na linha 180 é um de () construção de loop sobre uma coleção de TunnelType objetos dentro de um objeto unmarshalled (disse trabalhos unmarshalling bem BTW).

Dado que o unmarshalling objeto real correu bem, é mesmo fisicamente possível para JAXB para deixar ElementNSImpl objetos dentro de coleções aninhadas?

ambiente de tempo de execução:

  • JAXB 2.1
  • OSGi
  • Spring DM
  • O JAXBContext é inicializado com o ClassLoader do pacote que contém as classes para ser marshalled / unmarshalled
Foi útil?

Solução 3

Fora de desespero que se virou para sincronização no objeto JAXBContext.class, vendo esta como a possibilidade único remanescente por alguma condição de corrida e, pelo menos, não temos sido capazes de reproduzir este problema novamente. Aqui está o código crítico:

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

Outras dicas

Eu recebo esta exceção só quando eu esqueça de dizer JAXBContext sobre todos os tipos a-ser-marshalled poderia ser lidando.

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

Nenhuma das abordagens sugeridas aqui fez isso por mim. No entanto, esta resolvido o meu problema

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

A cláusula sincronizado acima resolveu o problema para mim também, mas parece que o contexto não deve ser uma variável local. Em vez disso, deve ser uma variável de instância, ou um estático. Eu não era capaz de refatorar meu código como eu gostaria que ele, então ao invés Mudei o contexto em um inicializador estático, que não é perfeito, mas 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();
    }
  }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top