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