JAXB marshal without @XmlRootElement – Missing @XmlRootElement Error

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

There can be many other such situations but idea is that we are not able to modify model class with JAXB annotations. This can be an example to convert java object to xml without jaxb.

1. Problem while marshalling without @XmlRootElement

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

javax.xml.bind.MarshalException
 - with linked exception:
[com.sun.istack.internal.SAXException2: unable to marshal type "com.howtodoinjava.demo.model.Employee" 
as an element because it is missing an @XmlRootElement annotation]
  at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:311)
  at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:236)
  at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:95)
  at com.howtodoinjava.demo.JaxbExample.jaxbObjectToXML(JaxbExample.java:45)
  at com.howtodoinjava.demo.JaxbExample.main(JaxbExample.java:17)
Caused by: com.sun.istack.internal.SAXException2: unable to marshal type "com.howtodoinjava.demo.model.Employee" 
as an element because it is missing an @XmlRootElement annotation
  at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:234)
  at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:323)
  at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:479)
  at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:308)
  ... 4 more

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 marshal a object without @XmlRootElement annotation

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

2.1. Syntax

/**
  * @param name          Java binding of xml element tag name
  * @param declaredType  Java binding of xml element declaration's type
  * @param value         Java instance representing xml element's value
  */
JAXBElement<T> elem = new JAXBElement(QName name, Class<T> declaredType, T value );

For example –

JAXBElement<Employee> jaxbElement 
        = new JAXBElement<Employee>( new QName("", "employee"), Employee.class, employeeObj );

2.2. JAXB marshal without @XmlRootElement example

Now let’s see how this marshalling code works.

package com.howtodoinjava.demo;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.namespace.QName;

import com.howtodoinjava.demo.model.Department;
import com.howtodoinjava.demo.model.Employee;

public class JaxbExample 
{
  public static void main(String[] args) 
  {
    Employee employee = new Employee(1, "Lokesh", "Gupta", new Department(101, "IT"));
    
    jaxbObjectToXML( employee );
  }
  
  private static void jaxbObjectToXML(Employee employeeObj) 
  {
      try {
          JAXBContext jaxbContext = JAXBContext.newInstance(Employee.class);
          Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

          // To format XML
          jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); 

          //If we DO NOT have JAXB annotated class
          JAXBElement<Employee> jaxbElement = 
            new JAXBElement<Employee>( new QName("", "employee"), 
                      Employee.class, 
                      employeeObj);
            
          jaxbMarshaller.marshal(jaxbElement, System.out);
          
          //If we have JAXB annotated class
          //jaxbMarshaller.marshal(employeeObj, System.out);  
          
      } catch (JAXBException e) {
          e.printStackTrace();
      }
  }
}

Program Output:

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

Drop me your questions related to JAXB marshal without @XmlRootElement example.

Happy Learning !!

Reference : XmlRootElement Java Doc

2 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments

Comments are closed for this article!

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.