2009-04-01 9 views
39

Tratando de conseguir más allá de una excepción de difusión clase aquí:Class Cast Excepción al intentar deshacer un xls?

FooClass fooClass = (FooClass) unmarshaller.unmarshal(inputStream); 

lanza esta excepción:

java.lang.ClassCastException: javax.xml.bind.JAXBElement 

No entiendo esto - como la clase fue generada por la herramienta xjc.bat - y las clases que generó no las he alterado en absoluto, así que no debería haber problemas de conversión aquí; el unmarshaller realmente debería devolverme una clase que PUEDE ser lanzada a FooClass.

¿Alguna idea de lo que estoy haciendo mal?

Respuesta

93

¿Tiene FooClass la anotación XmlRootElement? Si no, intente:

Source source = new StreamSource(inputStream); 
JAXBElement<FooClass> root = unmarshaller.unmarshal(source, FooClass.class); 
FooClass foo = root.getValue(); 

Eso se basa en el Unofficial JAXB Guide.

+2

¿Por qué tiene la JAXB compilador no puso una anotación XmlRootElement en mi clase en los primeros t lugar, ya que no puedo encontrar uno. Tu código funciona, pero me gustaría saber más, es decir, ¿por qué funciona? – Vidar

+0

Pase: solo investigué lo suficiente para resolver el problema original :) Realmente no sé mucho sobre JAXB ... –

+0

Lo que se debe hacer, pero gracias por ayudarme de todos modos. – Vidar

1

¿Estás absolutamente seguro de que FooClass es el elemento raíz de la fuente de entrada xml que lo pasaste? Unmarshall devolverá un objeto del elemento raíz creado por xjc.

3

Miro el archivo XML y me aseguro de que sea más o menos lo que espera ver.

También me gustaría cambiar temporalmente el código para:

Object o = unmarshaller.unmarshal(inputStream); 
System.out.println(o.getClass()); 

si el primero failes continuación, el elenco de clase que está sucediendo dentro del método unmarshal, si tiene éxito, entonces usted puede ver la clase real que son regresando y luego averiguar por qué no es lo que espera que sea.

9

Para una explicación más completa, lea this article. Resulta que su XSD debe estar configurado correctamente, es decir, debe haber algún elemento raíz que abarque todos los demás elementos.

XJC intenta poner la anotación @XmlRootElement en una clase que generamos a partir de un tipo complejo. La condición exacta es algo desagradable, pero la idea básica es que si podemos garantizar estáticamente que un tipo complejo no será utilizado por múltiples nombres de etiqueta diferentes, ponemos @XmlRootElement.

+0

Ese enlace que señala es la mejor respuesta –

3

Pasamos demasiadas horas inquieto con la clase de fábrica JAXB para satisfacer al unmarshaller. Hemos aprendido que el uso del unmarshaller sin para llamar a la fábrica de objetos generada por JAXB funciona correctamente. Espero que el código de ejemplo rescata la frustración de alguien:

System.out.println("Processing generic-type unmarshaller: "); 
MessageClass mcObject = unmarshalXml(MessageClass.class, msgQryStreamSource, 
    NAMESPACE + "." + "MessageClass"); 

public static <T> T unmarshalXml(Class<T> clazz, StreamSource queryResults, 
    String contextNamespace) 
    { 
     T resultObject = null; 
     try { 
      //Create instance of the JAXBContext from the class-name 
      JAXBContext jc; 
      jc = JAXBContext.newInstance(Class.forName(clazz.getName())); 
      Unmarshaller u = jc.createUnmarshaller(); 
      resultObject = clazz.cast(u.unmarshal(queryResults)); 
      } 
       //Put your own error-handling here. 
     catch(JAXBException e) 
     { 
      e.printStackTrace(); 
     } 
     catch (ClassCastException e) 
     { 
      e.printStackTrace(); 
     } 
     catch (ClassNotFoundException e) 
     { 
      e.printStackTrace(); 
     } 
     return clazz.cast(resultObject); 
    } 
0

Especificar @XmlRootElement (name = "specifyName", espacio de nombres = "nombre") para la transformación de objeto.

2

Basándose en las respuestas de sus colegas, por si acaso alguien todavía está buscando una respuesta.Había siendo definida la cuestión de tener el elemento raíz de mi esquema

como:

<schema> 
    <element name="foo" type="bar" /> 
    <complexType name="bar" /> 
</schema> 

Y por lo tanto, que era conseguir una excepción de difusión en:

try {    
     javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(mobilityConfigType.getClass().getPackage().getName());    
     javax.xml.bind.Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller(); 
     File f = FileUtil.toFile(this.getPrimaryFile());    
     mobilityConfigType = (MobilityModelConfigType)unmarshaller.unmarshal(FileUtil.toFile(this.getPrimaryFile())); 
    } catch (javax.xml.bind.JAXBException ex) {    
     java.util.logging.Logger.getLogger("global").log(java.util.logging.Level.SEVERE, null, ex); //NOI18N 
    } 

Lo que hice fue cambiar la primera línea del bloque try a:

javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(mobilityConfigType.getClass().getName()); 

Eso resolvió el problema para mí.

12

Uso JAXBIntrospector en el JAXBElement para obtener el schemaObject como >>

JAXBContext jaxbContext = JAXBContext.newInstance(Class.forName(className)); 
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); 
Object schemaObject = JAXBIntrospector.getValue(unmarshaller.unmarshal(new ByteArrayInputStream(xmlString.getBytes()))); 

Consulte: when does JAXB unmarshaller.unmarshal returns a JAXBElement<MySchemaObject> or a MySchemaObject?

+3

Esta solución es sencilla y funciona bien para el elenco – maoanz

+0

Gracias. También es una solución genérica. –

+1

Y entonces, ¿qué se supone que debo hacer con este schemaObject? – Line

0

también me encontré con el "Javax.xml.bind.JAXBElement no se puede convertir a un" error y se encontró esta solución muy simple:

FooClass fooClass = (FooClass) ((JAXBElement) u.unmarshal(new File("xml/foo.xml"))).getValue(); 

Dado que, al parecer, se devuelve un objeto de tipo JAXBElement, necesita encasillado su valor en su lugar.

Fuente: https://forums.oracle.com/thread/1625944

1

A veces hay una definición XSD con múltiples elementos raíz diferentes (por ejemplo XSD definidos en WSDL) y en ese caso las clases generadas faltan @XmlRootElement. Entonces, como el usuario mbrauh ya escribió, debe obtener el valor de JAXBElement. En mi caso utilicé:

FooClass request = ((JAXBElement<FooClass>) marshaller.unmarshal(new StreamSource(classPathResource.getInputStream()))).getValue(); 

Así que el uso de medicamentos genéricos puede evitar fácilmente el doble tipo de fundición.

11

Me encontré con el mismo problema hoy, vi las respuestas aquí, hice algunas investigaciones y me parece que la solución más genérica es usar JAXBIntrospector. Por lo tanto -

FooClass fooClass = (FooClass) unmarshaller.unmarshal(inputStream); 

debe escribirse como

FooClass fooClass = (FooClass) JAXBIntrospector.getValue(unmarshaller.unmarshal(inputStream)); 

O mejor aún, para que sea más genérico -

T t = (T) JAXBIntrospector.getValue(unmarshaller.unmarshal(inputStream)); 
0

Prueba esto:

JAXBContext jc = JAXBContext.newInstance(Foo.class); 
Unmarshaller unmarshaller = jc.createUnmarshaller(); 
JAXBElement element = (JAXBElement) unmarshaller.unmarshal(new StringReader(xmlString)); 
Foo foo = (Foo)element; 
Cuestiones relacionadas