Unmarshal without jaxb annotations

Many times, you will need to unmarshal Java objects which does not have JAXB annotations such as @XmlRootElement and you are not permitted to make any changes in sourcecode. This situation may occur when you are working with legacy code or some client jar for which you do not have source code.

1. Problem when unmarshal without jaxb annotations

In such case, if you try to unmarshal Java object to XML directly then you will get error like this.

javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"employee"). Expected elements are (none)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:726)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:247)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:242)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:109)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1131)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:556)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:538)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:153)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:509)
	at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:379)
	at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:605)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3138)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:880)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
	at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:117)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
	at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:649)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:243)
	at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214)
	at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
	at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:162)
	at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:171)
	at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:189)
	at com.howtodoinjava.demo.JaxbExample.jaxbXmlFileToObject(JaxbExample.java:63)
	at com.howtodoinjava.demo.JaxbExample.main(JaxbExample.java:21)

Where Employee.java class is as below. It does not have any JAXB annotation such as @XmlRootElement.

package com.howtodoinjava.demo.model;

import java.io.Serializable;

public class Employee implements Serializable {

	private static final long serialVersionUID = 1L;

	private Integer id;
	private String firstName;
	private String lastName;
	private Department department;

	public Employee() {
		super();
	}

	public Employee(int id, String fName, String lName, Department department) {
		super();
		this.id = id;
		this.firstName = fName;
		this.lastName = lName;
		this.department = department;
	}

	//Getters and Setters

	@Override
	public String toString() {
		return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", department="
				+ department + "]";
	}
}

2. Solution to unmarshal without jaxb annotations

In absense of @XmlRootElement annotation, JAXB is not able to build JAXBElement instance for Employee object. So that’s where you have to help JAXB to construct it manually.

2.1. Syntax

/**
  * Unmarshal XML data from the specified XML Source by <tt>declaredType</tt> and return the
  * resulting content tree.
  * @param  source       source the XML Source to unmarshal XML data from (providers are
  *        				only required to support SAXSource, DOMSource, and StreamSource)
  *
  * @param  declaredType  appropriate JAXB mapped class to hold <tt>source</tt>'s xml root element
  * 
  * @return value      	 Java content rooted by JAXB Element
  */
public <T> JAXBElement<T> unmarshal( javax.xml.transform.Source source, Class<T> declaredType )
        throws JAXBException;

For example –

JAXBElement<Employee> jaxbElement = (JAXBElement<Employee>) jaxbUnmarshaller
					.unmarshal(new StreamSource(xmlFile), Employee.class);

2.2. Unmarshalling

Now let’s see how this unmarshalling code works.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<employee>
    <department>
        <id>101</id>
        <name>IT</name>
    </department>
    <firstName>Lokesh</firstName>
    <id>1</id>
    <lastName>Gupta</lastName>
</employee>
package com.howtodoinjava.demo;

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

import com.howtodoinjava.demo.model.Employee;

public class JaxbExample 
{
	public static void main(String[] args) 
	{
		String fileName = "employee.xml";

		jaxbXmlFileToObject(fileName);
	}

	private static void jaxbXmlFileToObject(String fileName) 
	{
		File xmlFile = new File(fileName);
		JAXBContext jaxbContext;
		try 
		{
			jaxbContext = JAXBContext.newInstance(Employee.class);
			Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
			
			JAXBElement<Employee> jaxbElement = (JAXBElement<Employee>) jaxbUnmarshaller
					.unmarshal(new StreamSource(xmlFile), Employee.class);
			
			Employee employee = jaxbElement.getValue();
			
			System.out.println(employee);
		}
		catch (JAXBException e) 
		{
			e.printStackTrace();
		}
	}
}

Program Output:

Employee [id=1, firstName=Lokesh, lastName=Gupta, department=Department [id=101, name=IT]]

Drop me your questions in comments section.

Happy Learning !!

Reference : XmlRootElement Java Doc

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

2 thoughts on “Unmarshal without jaxb annotations”

  1. Is there a way for this to work if the class contains fields that point to other classes, which also need to be marshalled without the XmlRootElement tag?

    Reply

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.