Class Cast Exception when trying to unmarshall xml

2019-01-30 04:55发布

Trying to get past a class cast exception here:

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

throws this exception:

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

I don't understand this - as the class was generated by the xjc.bat tool - and the classes it generated I have not altered at all - so there should be no casting problems here - the unmarshaller should really be giving me back a class that CAN be cast to FooClass.

Any ideas as to what I am doing wrong?

标签: java jaxb jaxb2
14条回答
Ridiculous、
2楼-- · 2019-01-30 05:18

Building on the previews answers from colleagues, just in case anybody is still looking for an answer.

I had the issue of having the root element of my scheme being defined as:

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

And therefore I was getting a Cast Exception at:

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
    }

What I did was to change the first line of the try block to:

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

That resolved the problem for me.

查看更多
3楼-- · 2019-01-30 05:18

I also encountered the "Javax.xml.bind.JAXBElement cannot be cast to" error and found this very simple solution:

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

Since, apparently, an object of type JAXBElement is returned, you need to typecast its value instead.

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

查看更多
SAY GOODBYE
4楼-- · 2019-01-30 05:19

Does FooClass have the XmlRootElement annotation? If not, try:

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

That's based on the Unofficial JAXB Guide.

查看更多
爷、活的狠高调
5楼-- · 2019-01-30 05:19

Use JAXBIntrospector on the JAXBElement to get the schemaObject like >>

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

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

查看更多
来,给爷笑一个
6楼-- · 2019-01-30 05:23

Sometimes you have a XSD definition with multiple different root elements (for instance XSD defined in WSDL) and in that case the generated classes are missing @XmlRootElement. So as user mbrauh already wrote you have to get the value of JAXBElement. In my case I used:

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

So using generics you can easily avoid double type casting.

查看更多
Evening l夕情丶
7楼-- · 2019-01-30 05:26

I ran into the same problem today, saw the answers here, did some research and looks to me that the most generic solution is to use JAXBIntrospector. Hence -

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

should be written as

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

Or even better, to make it more generic -

T t = (T) JAXBIntrospector.getValue(unmarshaller.unmarshal(inputStream));
查看更多
登录 后发表回答