Thursday, 9 May 2013

How to convert POJO to XML and XML to POJO with JAXB?


Conversion of POJO to XML and XML to POJO


While working with web-services or SOA applications, it is mandatory that we should know to convert java object to XML, XML to Java, Java to JSON and JSON to java object.


We will first consider about the Java object to XML conversion. Now days, JAXB is the common tool which is used for JAVA object to XML conversion. JAXB stands for Java Architecture for XML Binding. It provides a convenient and fast way to bind XML schemas and java representational objects. It is an annotation based framework which provides a bridge to map java classes to XML schema and XML to java classes. As part of conversion process from java to XML, JAXB provides methods for marshalling (writing) of java objects into XML instance documents and conversion for XML instance to java objects, JAXB provides methods for unmarshalling (reading) XML instance documents into Java objects.



Steps to perform marshalling of JAVA objects to XML instance documents using JAXB:

  • Create a java POJO (Plain Old Java Object) and annotate the class with @XmlRootElement, @XmlAccessorType and annotate all fields with @XmlElement. If required we can annotate attributes with @XmlAttribute. These annotations will help to bind java Object properties to XML instance elements.

  • Create a JAXBContext object. This abstract class is available in javax.xml.bind.JAXBContext package.

  • Create a Marshaller object which is available in javax.xml.bind.Marshaller package and invoke marshal() method on Marshaller object. While marshaling we can pass java.io.Writer, java.io.File or java.io.OutputStream for redirecting the generated XML documents.


Specific Use of JAXB Annotations :-



@XmlRootElement - Maps a class or an enum type to an XML element.

The @XmlRootElement annotation can be used with the following program elements:

  • a top level class
  • an enum type


@XmlAccessorType - This annotation provides control over the default serialization of properties and fields in a class.

@XmlAccessorType annotation can be used with the following program elements:

  • package
  • a top level class

By default, if @XmlAccessorType on a package is absent, then the following package level annotation is assumed.

   @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)


By default, if @XmlAccessorType on a class is absent, and none of its super classes is annotated with @XmlAccessorType, then the following default on the class is assumed:

   @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)




@XmlElement- Maps a JavaBean property to a XML element derived from property name.

@XmlElement annotation can be used with the following program elements:

  • a JavaBean property
  • non static, non transient field
  • within XmlElements


@XmlAttribute - Maps a JavaBean property to a XML attribute.

The @XmlAttribute annotation can be used with the following program elements:

  • JavaBean property
  • field

reference taken from oracle.com

Steps to perform unmarshalling of XML instance documents to JAVA objects using JAXB:

  • Create a JAXBContext object. This abstract class is available in javax.xml.bind.JAXBContext package.

  • Create a Unmarshaller object and invoke unmarshal() method on Unmarshaller class object. While unmarshaling we can pass java.io.Reader, class object which will read the XMLdata which we can provide in the form of string.

  • Then we can pass the Reader class object in unmarshal method and by typecasting the specific pojo class we will get the Java object back from XML instance documents.


Advantages of using JAXB:-


  • In comparison with SAX and DOM, JAXB is providing easiest and convenient way for conversion.

  • JAXB is available with JDK so no need to add or depends on any additional jars in Classpath.

  • JAXB is more memory efficient then DOM as we are working with java instances instead of XML elements.

  • With DOM, we have to go/navigate through the tree structure but JAXB allows performing non-sequential processing of XML documents.


Example:- POJO to XML and XML to POJO conversion



In this example, I am retrieving the data from a DB table and generating the retrieved table as XML document and then reading the XML document and converting back it to java object.


System Requirement:-


JDK 1.6 or above.

Eclipse Helios or above

Hibernate API jars

MySQL database and corresponding jar.



Table structure and Insert Scripts


Create script;


CREATE TABLE employee (

    id DOUBLE ,

    NAME VARCHAR (50),

    email VARCHAR (100)

); 


Insert script;


INSERT INTO employee (id, NAME, email) VALUES('1','GAURAV','gaurav@yahoo.co.in');

INSERT INTO employee (id, NAME, email) VALUES('2','Aryan','Aryan@gmail.com');

INSERT INTO employee (id, NAME, email) VALUES('7','Madhu','madhu@sify.com');


Data Status in employee Table

Required Jars:-


antlr-2.7.6.jar
asm-2.2.2.jar
asm-commons-2.2.2.jar
cglib-nodep-2.1_3.jar
commons-collections.jar
commons-logging.jar
dom4j-1.6.1.jar
ehcache-1.1.jar
hibernate3.jar
jta.jar
log4j-1.2.14.jar
mysql-connector-java-5.0.4-bin.jar


Steps to create this demo example:-

  • Create a java project using eclipse;

  • Add the hibernate and mysql jars in the project classpath.

  • Create a package named com.gaurav.jaxbimplementation and create a java class with the name Employee.java

  • Create a java class and name it with Employees.java and place the corresponding source code in both the pojo's.

  • Create a EmpDS.java file and place the below available code in the file.

  • Create a hibernate configuration file and hibernate mapping file in the project src folder and place the corresponding code in their files which is available below.

  • At last create a JAXBConverter.java file and place the below available code in that file then execute this file as Run as Java application and check the result on Eclipse console.




Employee.java


package com.gaurav.jaxbimplementation;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;


@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Employee {

    @XmlElement
    private long id;
    @XmlElement
    private String name;
    @XmlElement
    private String email;
   
    public Employee() {
    }

    public Employee(long id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
   
    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + ", " +
                "email=" + email + "]";
   
    }

}




Employees.java


package com.gaurav.jaxbimplementation;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Employees {

    private int recCount;

    private List<Employee> employee = new ArrayList<Employee>();

    /**
     * @return the employeesList
     */
    public List<Employee> getEmployee() {
        return employee;
    }

    /**
     * @param employeesList
     *            the employeesList to set
     */
    public void setEmployee(List<Employee> employeesList) {
        this.employee = employeesList;
    }

    /**
     * @return the recCount
     */
    public int getRecCount() {
        return recCount;
    }

    /**
     * @param recCount
     *            the recCount to set
     */
    public void setRecCount(int recCount) {
        this.recCount = recCount;
    }

    public String toString() {
        StringBuffer buffer = new StringBuffer();
        buffer.append("RecordCount: " + recCount + "\n");
        buffer.append("employees: \n");
        buffer.append(employee);
        return buffer.toString();
    }

}
 


EmpDS.java


package com.gaurav.jaxbimplementation;

import java.util.ArrayList;

import java.util.List;

import org.hibernate.HibernateException;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.Transaction;

import org.hibernate.cfg.Configuration;



public class EmpDS {



    /* This Method will be used to retrieve the employee Details from the DB table employee*/

    @SuppressWarnings("rawtypes")

    public List retrieveEmployee() {



        SessionFactory sf = new Configuration().configure()

                .buildSessionFactory();

        List emps = new ArrayList();

        Session session = sf.openSession();

        Transaction tx = session.beginTransaction();

        try {



            emps = session.createQuery("from Employee").list();



            tx.commit();

        } catch (HibernateException e) {

            tx.rollback();

            e.printStackTrace();

        } finally {

            session.close();

        }

        return emps;

    }



}


EmpBean.hbm.xml


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"

        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">



<hibernate-mapping>

    <class name="com.gaurav.jaxbimplementation.Employee" table="Employee">

        <id name="id" column="id" type="long">

            <generator class="assigned" />

        </id>



        <property name="name" column="name" />

        <property name="email" column="email" />



    </class>

</hibernate-mapping>



hibernate.cfg.xml


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-configuration PUBLIC

        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory>

        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property>

        <property name="hibernate.connection.username">root</property>

        <property name="connection.password">root</property>

        <property name="connection.pool_size">1</property>

        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

        <property name="show_sql">true</property>

        <property name="hbm2ddl.auto">update</property>

        <mapping resource="EmpBean.hbm.xml" />

    </session-factory>

</hibernate-configuration>




JAXBConverter.java


package com.gaurav.jaxbimplementation;

import java.io.StringReader;

import java.io.StringWriter;

import java.util.List;

import javax.xml.bind.JAXBContext;

import javax.xml.bind.JAXBException;

import javax.xml.bind.Marshaller;

import javax.xml.bind.Unmarshaller;



public class JAXBConverter {



    private static EmpDS employeeDS = new EmpDS();



    private String pojo2Xml(Object object, JAXBContext context)

            throws JAXBException {

        Marshaller marshaller = context.createMarshaller();

        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        StringWriter writer = new StringWriter();

        marshaller.marshal(object, writer);

        String xmlStringData = writer.toString();

        return xmlStringData;

    }



    private Employees xml2Pojo(String xmlStringData, JAXBContext context)

            throws JAXBException {

        StringReader reader = new StringReader(xmlStringData);

        Unmarshaller unmarshaller = context.createUnmarshaller();

        Employees employee = (Employees) unmarshaller.unmarshal(reader);

        return employee;

    }



    @SuppressWarnings("unchecked")

    public static void main(String args[]) {



        JAXBContext context = null;



        JAXBConverter jaxbConverter = new JAXBConverter();



        List<Employee> employeesList = employeeDS.retrieveEmployee();



        Employee empBean = null;



        Employees employees = new Employees();



        try {

            int counter = 0;

            for (Employee bean : employeesList) {

                empBean = new Employee();

                empBean.setId(bean.getId());

                empBean.setName(bean.getName());

                empBean.setEmail(bean.getEmail());

                counter++;



                employees.setRecCount(counter);

                employees.getEmployee().add(empBean);



            }



        } catch (Exception e) {

            e.printStackTrace();

        }



        try {



            context = JAXBContext.newInstance(Employees.class);

            String xmlStringData = jaxbConverter.pojo2Xml(employees, context);

            System.out

                    .println("\nPOJO to XML conversion(Marshal) demonstration in Java");

            System.out.println(xmlStringData);



            employees = jaxbConverter.xml2Pojo(xmlStringData, context);

            System.out

                    .println("\nXML to POJO conversion(UnMarshal) demonstration in Java");

            System.out.println(employees);



        } catch (JAXBException e1) {

            e1.printStackTrace();

        }



    }

}




Result:-


log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).

log4j:WARN Please initialize the log4j system properly.

Hibernate: select employee0_.id as id0_, employee0_.name as name0_, employee0_.email as email0_ from Employee employee0_


POJO to XML conversion(Marshal) demonstration in Java


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<employees>

    <employee>

        <id>1</id>

        <name>GAURAV</name>

        <email>gaurav@yahoo.co.in</email>

    </employee>

    <employee>

        <id>2</id>

        <name>Aryan</name>

        <email>Aryan@gmail.com</email>

    </employee>

    <employee>

        <id>7</id>

        <name>Madhu</name>

        <email>madhu@sify.com</email>

    </employee>

    <recCount>3</recCount>

</employees>



XML to POJO conversion(UnMarshal) demonstration in Java


RecordCount: 3

employees:

[Employee [id=1, name=GAURAV, email=gaurav@yahoo.co.in], Employee [id=2, name=Aryan, email=Aryan@gmail.com], Employee [id=7, name=Madhu, email=madhu@sify.com]]


1 comment:

  1. My XML looks like this:

    Heritage

    How can I convert issue to a POJO? Could you tell me the name that should be given to the variable that stores the value of the issue tag? Thanks!

    ReplyDelete