Class Cast Exception when trying to unmarshall xml?

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?


Solution 1:

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.

Solution 2:

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?

Solution 3:

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));

Solution 4:

For a fuller explanation read this article. It turns out that your XSD must be properly set up, i.e. there must be some root element encompassing all the other elements.

XJC does try to put @XmlRootElement annotation on a class that we generate from a complex type. The exact condition is somewhat ugly, but the basic idea is that if we can statically guarantee that a complex type won't be used by multiple different tag names, we put @XmlRootElement.