Igor Kromin |   Consultant. Coder. Blogger. Tinkerer. Gamer.

I've recently had a requirement to unmarshal an XML fragment that was passed into one of my services. This in itself is typically not and issue and I've written code that does that plenty a time, however in this case I was having to unmarshal a fragment for a complex type, not for an element. That's where it got a little bit more complicated.

Initially my code was throwing the following exception:
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://net.igorkromin/", local:"MyComplexType"). Expected elements are (none)

So that meant that the unmarshaller didn't recognise any valid elements in my XML string that I was trying to unmarshal. I checked the JAXB Context and it definitely had the complex type I was after so it was something else I was doing wrong.

Lets take a step back and look at the schema, my complex type, MyComplexType, was defined as:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://net.igorkromin/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://net.igorkromin/" elementFormDefault="qualified">
<xsd:complexType name="MyComplexType">

That resulted in a JAXB generated class that looked like:
 Java Class
name = "MyComplexType",
propOrder = {...}
public class MyComplexType {

So, no XmlRootElement annotation. That's because it was a complex type and not an element of that type. That should have been obvious right away, but I missed it initially. Luckily there was a simple way around it. All I had to do was tell JAXB what complex type I was expecting and wrap the XML fragment as a Source or specifically StreamSource.

So the code that would achieve that looked something like...
String xmlString =
"< MyComplexType xmlns=\"http://net.igorkromin/\">\n" +
" ..." +
"</MyComplexType >";
JAXBContext ctx = JAXBContext.newInstance(MyComplexType.class);
Unmarshaller u = ctx.createUnmarshaller();
ByteArrayInputStream bais = new ByteArrayInputStream(xmlString.getBytes());
Source source = new StreamSource(bais);
JAXBElement<MyComplexType> mct = u.unmarshal(source, MyComplexType.class);

That worked like a charm and I could then get my unmarshalled complex type instance from the JAXBElement instance.


Use of any information contained in this blog post/article is subject to this disclaimer.
comments powered by Disqus
Other posts you may like...