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 the idea is that we are not able to modify the model class with JAXB annotations. This can be an example to convert Java objects to XML without JAXB.
1. Problem while Marshalling without @XmlRootElement
In such case, if we try to marshal the Java object to XML directly then we will get an error like “unable to marshal type T as an element because it is missing an @XmlRootElement annotation“.
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 an POJO class and does not have the JAXB annotations such as @XmlRootElement
.
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String firstName;
private String lastName;
private Department department;
//constructors, setters, getters
}
2. Solution to marshal an object without @XmlRootElement
In absence 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. Then we can convert this JAXBElement to XML.
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, employeeInstance);
jaxbMarshaller.marshal(jaxbElement, System.out);
2.2. Demo
Now let’s see how this marshalling code works. We are creating an instance of the above Employee class and converting in to XML.
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 had 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
Comments