Solving the JAXB “unexpected element” problem

-1If you are using JAXB in a maven/java project to unmarshal an XML document and you get:

javax.xml.bind.UnmarshalException: unexpected element (uri:”urn:iso:std:somestuff:xsd:somestuff”, local:”Document”). Expected elements are (none)

Or if you are using JAXB to marshal an XML document and you get:

com.sun.istack.internal.SAXException2: unable to marshal type “generated.somestuff.Document” as an element because it is missing an @XmlRootElement annotation

You have probably fallen victim of the fact that JAXB does not do “Simple Binding” by default. If your project is a maven project and you generated classes based on an xsd file, this is how you fix it (without changing the xsd file):

Tell JAXB to do “simple binding”. To do so, create a binding file called src/main/resources/jaxb/simple-binding.xml with the following contents:

<jaxb:bindings jaxb:extensionBindingPrefixes="xjc" version="2.1"
	xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
	xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">
  <jaxb:globalBindings>
	  <xjc:simple/>
  </jaxb:globalBindings>
</jaxb:bindings>

Then, add the following options to the execution of your jaxb2-maven-plugin (highlighted):

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>jaxb2-maven-plugin</artifactId>
  <version>1.5</version>
  <executions>
	<execution>
	  <id>somestuff</id>
	  <goals>
		<goal>xjc</goal>
	  </goals>
	  <configuration>
		<clearOutputDir>false</clearOutputDir>
		<extension>true</extension>
		<bindingDirectory>${basedir}/src/main/resources/jaxb</bindingDirectory>
		<bindingFiles>simple-binding.xjb</bindingFiles>
		<staleFile>${project.build.directory}/jaxb2/.somestuff.StaleFlag</staleFile>
		<packageName>generated.somestuff</packageName>
		<schemaDirectory>${basedir}/src/main/resources/schemas</schemaDirectory>
		<schemaFiles>somestuff.xsd</schemaFiles>
	  </configuration>
	</execution>
  </executions>
</plugin>

You should be able to re-generate the jaxb code now, and parsing should work. In order to test if you have this problem, and to ensure that it does not come back after somebody changes your build file, create a unittest which marshals a java object into xml, and then unmarshalls the generated xml back into an object:

// Create document objects (JAXB Generated classes)
Document sourceDocument = new Document();
sourcedocument.setSomeElement(new SomeElement());

JAXBContext jaxbContext = JAXBContext.newInstance(Document.class);

// Write Document
File file = File.createTempFile("sometempstuff", ".xml");
FileWriter fileWr = new FileWriter(file);
XMLOutputFactory xml = XMLOutputFactory.newFactory();
XMLStreamWriter xmlStrWr = xml.createXMLStreamWriter(fileWr);
xmlStrWr.writeStartDocument("UTF-8", "1.0");
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
marshaller.marshal(sourceDocument, xmlStrWr);
xmlStrWr.writeEndDocument();
fileWr.close();

// Read Document
FileInputStream fileInpStr = new FileInputStream(file);
Unmarshaller unm = jaxbContext.createUnmarshaller();
Document result = (Document) unm.unmarshal(fileInpStr);

// Test the parsedDocument here if you like.
...

// Cleanup
file.delete();

The reason for this blog is of course the fact that I expected this “Simple Binding” to be the default, as 80% of the people will want to do exactly this. I’ve found a lot of people suffering from this problem, and I found the documentation to be not very helpful.

I hope this blog post helps you get on with more important stuff.

Have fun!
Rolf

2 Responses to Solving the JAXB “unexpected element” problem

  1. Rolf Schumacher says:

    As I am new to JAXB (substituting xmlbeans for me), trying to use it together with Eclipse, m2e, and jaxb-maven-plugin, I have been run into this problem. Many thanks for pointing to it, saving me time to search the failure in my programmings. I simply went back to xmlbeans as my knowledge seems not to be sufficient to make your solution working for me.

    I would love to get pointed to a working example using JAXB in an m2e/Eclipse environment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s