Praveen Singh

XStream : Make xml binding easy !

Popularity of XML is growing day by day, even birth of new portable text technology like JSON, not stopping XML to grow.

Reason behind this not XML alone but other technology which revolved around it like XSD, XSLT etc.

Almost every other language comes up with support of XML.

Java is seems ahead of any other language with different type of parsers (DOM, SAX, STAX, TRAX, etc), XML based framework (apache Cocoon, etc).

But here we are not going to talk about parsers, we are going to discuss about XML Binding in JAVA.

Q . I heard about JaxB, XMLBeans, etc which are famous Java XML Binding framework, what the hell XStream is ?.....another in the row ?

A . XStream is XML binding framework in Java with the twist, it doesn't use XML Schema to create POJO clasees.

It provide set of mechanism to bind the class with xml directly.

I prefer the annotation way and will use same.

Q . what ?...it doesn't use xsd file to create pojo stubs !....then why would any one will go for it ?

A . its true XStream doesn't use xsd, hence not fit for application in which we have lots of xml.

but if you have a few xmls in your application, lets say for configuration file, etc and we want to bind that xml file with some Java class with some not so complex way then we can use XStream.

Q . Ok, Lets start !

A . Before I start lets list down all the requirment

  • java IDE(Eclipse etc)
  • xstream-1.3.1.jar
  • xpp3-1.1.2a.jar
  • jettison-1.0.1.jar
you can download these jars from here : http://xstream.codehaus.org/
By the code we will try to bind with the xml like this, let's call it Employee.xml

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

<employee xmlns="http://www.nokia.com/beans/Employee">

<empId>1214empId>

<name>

<firstName>PraveenfirstName>

<lastName>Kumar SinghlastName>

name>

<dateOfBirth>2010-04-01+05:30dateOfBirth>

<address>

<houseNo>4GhouseNo>

<addressLine1>Tulip ApartmentaddressLine1>

<addressLine2>BangaloreaddressLine2>

<zipCode>456456zipCode>

address>

<qualification detail="BTEch in ECE" name="BTech"/>

<qualification detail="MTech in CSE" name="MTech"/>

employee>


As you can see we have basic block, which can be converted into entity are as follows

  • employee
  • name
  • address
  • qualification
so we have to create the class corresponding to above items, i am putting annotation, which will bind the xml with class, in the class itself, please use comment to understand the code

Employee.java

package beans;

import java.util.ArrayList;

import java.util.Date;

import com.thoughtworks.xstream.annotations.XStreamAlias;

import com.thoughtworks.xstream.annotations.XStreamImplicit;

// Provide the alias name as employee, be default it will be like beans.Employee

@XStreamAlias(value = "employee")

public class Employee {

private int empId;

private Name name;

private Date dateOfBirth;

private Address address;

// Bind with list of qualification

@XStreamImplicit

private ArrayList qualifications;

public int getEmpId() {

return empId;

}

public void setEmpId(int empId) {

this.empId = empId;

}

public Name getName() {

return name;

}

public void setName(Name name) {

this.name = name;

}

public Date getDateOfBirth() {

return dateOfBirth;

}

public void setDateOfBirth(Date dateOfBirth) {

this.dateOfBirth = dateOfBirth;

}

public Address getAddress() {

return address;

}

public void setAddress(Address address) {

this.address = address;

}

public ArrayList getQualifications() {

return qualifications;

}

public void setQualifications(ArrayList qualifications) {

this.qualifications = qualifications;

}

@Override

public String toString() {

return "Employee [address=" + address + ", dateOfBirth=" + dateOfBirth

+ ", empId=" + empId + ", name=" + name + ", qualifications="

+ qualifications + "]";

}

}


Name.java

package beans;

import com.thoughtworks.xstream.annotations.XStreamAlias;

@XStreamAlias(value = "name")

public class Name {

private String firstName;

private String lastName;

public String getFirstName() {

return firstName;

}

public void setFirstName(String firstName) {

this.firstName = firstName;

}

public String getLastName() {

return lastName;

}

public void setLastName(String lastName) {

this.lastName = lastName;

}

}




Address.java

package beans;

import com.thoughtworks.xstream.annotations.XStreamAlias;

@XStreamAlias(value = "address")

public class Address {

private String houseNo;

private String addressLine1;

private String addressLine2;

private int zipCode;

public String getHouseNo() {

return houseNo;

}

public void setHouseNo(String houseNo) {

this.houseNo = houseNo;

}

public String getAddressLine1() {

return addressLine1;

}

public void setAddressLine1(String addressLine1) {

this.addressLine1 = addressLine1;

}

public String getAddressLine2() {

return addressLine2;

}

public void setAddressLine2(String addressLine2) {

this.addressLine2 = addressLine2;

}

public int getZipCode() {

return zipCode;

}

public void setZipCode(int zipCode) {

this.zipCode = zipCode;

}

}


Qualification.java

package beans;

import com.thoughtworks.xstream.annotations.XStreamAlias;

import com.thoughtworks.xstream.annotations.XStreamAsAttribute;

/**

* @author Praveen K Singh

*

*/

@XStreamAlias(value="qualification")

public class Qualification {

// Add element as attributes.

@XStreamAsAttribute

private String name;

@XStreamAsAttribute

private String detail;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getDetail() {

return detail;

}

public void setDetail(String detail) {

this.detail = detail;

}

}


Now after creating the set of entity, time has come to create a class which will allow you to test all we have done so far


TestClass .java


package test;

import java.util.ArrayList;

import java.util.Date;

import beans.Address;

import beans.Employee;

import beans.Name;

import beans.Qualification;

import com.thoughtworks.xstream.XStream;

import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;

public class TestClass {

public static void main(String[] args) {

// Create the instance of entity employee.

Employee employee = new Employee();

employee.setEmpId(1214);

employee.setDateOfBirth(new Date());

Address address = new Address();

address.setHouseNo("4G");

address.setAddressLine1("Tulip Apartment");

address.setAddressLine2("Outer Ring Road");

address.setZipCode(12345);

Name name = new Name();

name.setFirstName("Praveen");

name.setLastName("K Singh");

employee.setName(name);

employee.setAddress(address);

ArrayList qualifications = new ArrayList();

Qualification qualification = new Qualification();

qualification.setName("BTech");

qualification.setDetail("BTech in ECE");

qualifications.add(qualification);

qualification = new Qualification();

qualification.setName("MTech");

qualification.setDetail("MTech in CSE");

qualifications.add(qualification);

employee.setQualifications(qualifications);

// Create instance of XStream.

XStream xstream = new XStream();

// Allow to detect all the annotation automatically.

xstream.autodetectAnnotations(true);

// Convert employee instance to xml

String xmlString = xstream.toXML(employee);

// Convert xml string to employee instance.

Employee emp = (Employee)xstream.fromXML(xmlString);

// Start JSON Work.

// Create XStream instance for JSON.

XStream xstreamForJSON = new XStream(new JettisonMappedXmlDriver());

xstreamForJSON.autodetectAnnotations(true);

// Convert employee instance to json

String jsonData = xstreamForJSON.toXML(employee);

// Convert json string to employee instance.

Employee empJson = (Employee)xstreamForJSON.fromXML(jsonData);

}

}


You can print json, output will be like

{"employee":{"empId":1214,"name":{"firstName":"Praveen","lastName":"K Singh"},"dateOfBirth":"2010-05-03 19:14:31.494 IST","address":{"houseNo":"4G","addressLine1":"Tulip Apartment","addressLine2":"Outer Ring Road","zipCode":12345},"qualification":[{"@name":"BTech","@detail":"BTech in ECE"},{"@name":"MTech","@detail":"MTech in CSE"}]}}

Here we done with code, you can see how easy it is to work with XStream.

Lets list down all the advantage and disadvantage of XStream

Advantage

  • Very easy to understand.
  • No cmd or ant is needed to create the POJO stub.
  • Can be merged with existing entity available in application(very common if you are using JPA/Hibernate in your application).
  • Both annotation and code support for XML binding, gives flexibility to user.
  • Great list of annotations.
  • Provide great support for JSON, integral part of WEB 2.0 project now days.
Disadvntage
  • Need to add annotation for mapping in every class (or extra code for mapping if you are not using annotation), very very hectic and difficult to maintain in big application.
  • No validation with XSD (yes their are no of 3rd party API available which do so).
  • In JSON support, no difference in child element and attribute element ie no @ symbol before attribute(now this is area of controversy, few people in web community want this in JSON, few don't )
  • You have to create class structure as per XML using your brain, no tool is their to create same for you.
Summary

Its is clear from above discussion XStream is good only for small application or limited use, as no of XML increases, difficulty increases in same fashion.


1 comment:

  1. really grt. i got a good basic idea.. thx a lot.
    wishing u to cont...

    ReplyDelete