Class Cast Exception when trying to unmarshall xml?

JavaJaxbJaxb2

Java Problem Overview


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 Solutions


Solution 1 - Java

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 - Java

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: https://stackoverflow.com/questions/10243679/when-does-jaxb-unmarshaller-unmarshal-returns-a-jaxbelementmyschemaobject-or-a/10253282#10253282

Solution 3 - Java

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 - Java

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.

Solution 5 - Java

We spent too many hours fidgeting with the JAXB factory class to satisfy the unmarshaller. We've learned that using the unmarshaller without calling the JAXB-generated object factory works alright. Hope the sample code redeems someone's frustration:

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

Solution 6 - Java

I'd look at the XML file and make sure it is roughly what you expect to see.

I'd also temporarily change the code to:

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

If the first one failes then the class cast is happening inside the unmarshal method, if it succeeds then you can see the actual class that you are getting back and then figure out why it isn't what you expect it to be.

Solution 7 - Java

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.

Solution 8 - Java

Are you absolutely sure FooClass is the root element of the xml input source you passed it? Unmarshall will return an object of the root element created by xjc.

Solution 9 - Java

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.

Solution 10 - Java

If you have access and you can modify the XSD. For me, this issue appends when I generate the XSD from XML with IDEA.

With this xml :

<?xml version="1.0"?>
<schema>
  <element name="foo" type="bar" />
  <complexType name="bar" />
</schema>

IDEA generate an XSD like that and JAXB won't generate an root element :

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="schema" type="schemaType"/>
  <xs:complexType name="schemaType">
    <xs:sequence>
      <xs:element type="elementType" name="element"/>
      <xs:element type="complexTypeType" name="complexType"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="elementType">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute type="xs:string" name="name"/>
        <xs:attribute type="xs:string" name="type"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
  <xs:complexType name="complexTypeType">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute type="xs:string" name="name"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
</xs:schema>

BUT, if you modify the XSD in this way (modify your root element "schema" in order to get the xs:complexType inside the tag xs:element) :

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="schema">
    <xs:complexType>
      <xs:sequence>
        <xs:element type="elementType" name="element"/>
        <xs:element type="complexTypeType" name="complexType"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:complexType name="schemaType">
    <xs:sequence>
      <xs:element type="elementType" name="element"/>
      <xs:element type="complexTypeType" name="complexType"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="elementType">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute type="xs:string" name="name"/>
        <xs:attribute type="xs:string" name="type"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
  <xs:complexType name="complexTypeType">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute type="xs:string" name="name"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
</xs:schema>

JAXB will generate the root element !

Solution 11 - Java

Specify @XmlRootElement(name="specifyName", namespace="namespace") to transforming object.

Solution 12 - Java

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

Solution 13 - Java

Try this:

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

Solution 14 - Java

In my case, I get the error when trying to send a soap petition from the SOAPUI application. I need to set the property 'strip whitespaces' to true to skip this error.

When debug the content received, is a list with the next content:

[0] = "\n"
[1] = JAXBElement
[2] = "\n"

Hope help someone.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionVidarView Question on Stackoverflow
Solution 1 - JavaJon SkeetView Answer on Stackoverflow
Solution 2 - JavaRahul ThakurView Answer on Stackoverflow
Solution 3 - JavaGaurav BView Answer on Stackoverflow
Solution 4 - JavaVidarView Answer on Stackoverflow
Solution 5 - JavaMAbraham1View Answer on Stackoverflow
Solution 6 - JavaTofuBeerView Answer on Stackoverflow
Solution 7 - JavaAlberto A. MedinaView Answer on Stackoverflow
Solution 8 - JavaGreg NoeView Answer on Stackoverflow
Solution 9 - JavaMarek BranickyView Answer on Stackoverflow
Solution 10 - JavaAnthoView Answer on Stackoverflow
Solution 11 - Javauser752749View Answer on Stackoverflow
Solution 12 - JavambrauhView Answer on Stackoverflow
Solution 13 - JavaLazyCoderView Answer on Stackoverflow
Solution 14 - JavaIván Minguet GarcíaView Answer on Stackoverflow