Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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?

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

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.

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.

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

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.

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.

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.

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

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

Try this:

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

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.

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 !

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top