Handling Complex Types with JAXB Adapters

While binding our java object to xml, we might come across a situation where our java class representation may not be quite similar to that in the xml. JAXB provides XMLAdapters which becomes handy in these situations.


The XML Document

Let's take an example of the xml document shown below:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Employee id="1">
    <name>Ashutosh</name>
    <email>[email protected]</email>
    <mobile>9899885672</mobile>
    <joiningDate>January 26, 2010</joiningDate>
</Employee>

We can see that there is a joiningDate node present in the xml, which we would like to map to a date field in java object. To convert the date string in the xml to a Date object we need to use a JAXB XMLAdapter.


The Adapter Class

To create an Adapter class we need to extend the abstract class XMLAdapter. It defines two abstract methods marshal and unmarshal, which we need to override in our custom Adapter. Below is our Adapter to do the date-string conversions. Let's call it as DateAdapter.

public class DateAdapter extends XmlAdapter<String, Date> {

    @Override
    public String marshal(Date date) throws Exception {
	DateFormat df = new SimpleDateFormat("MMMM dd, yyyy");
	String dateString = df.format(date);
	return dateString;
    }

    @Override
    public Date unmarshal(String dateString) throws Exception {
	DateFormat df = new SimpleDateFormat("MMMM dd, yyyy");
	Date date = df.parse(dateString);
	return date;
    }	
}

We can notice in the code above that the XMLAdapter class is a generic class, it takes two generic types. The first being the type which is to be bound (i.e. the type in the xml document) and the other the type to be bound to.


The XML Class Representation

JAXB provides the @XMLJavaAdapter annotation that can be used to tell JAXB to marshal/unmarshal a particular field in a class using the adapter. Below is the Employee class that used the annotation.

@XmlType(propOrder={"name","email","mobileNo","joiningDate"})
@XmlRootElement(name="Employee")
public class Employee {

    private int id;
    private String name;
    private String email;
    private String mobileNo;
    private Date joiningDate;

    @XmlAttribute(name="id")
    public int getId() {
	return id;
    }

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

    @XmlElement(name="name", required=true)
    public String getName() {
	return name;
    }

    public void setName(String name) {
this.name = name; } @XmlElement(name="email", required=true) public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @XmlElement(name="mobile") public String getMobileNo() { return mobileNo; } public void setMobileNo(String mobileNo) { this.mobileNo = mobileNo; } @XmlJavaTypeAdapter(value=DateAdapter.class) @XmlElement(name="joiningDate") public Date getJoiningDate() { return joiningDate; } public void setJoiningDate(Date joiningDate) { this.joiningDate = joiningDate; } }

Notice that the getJoiningDate() method is annotated with @XMLJavaAdapter and the value parameter passed is DateAdapter.class to indicate that the joiningDate should be marshalled/unmarshalled using the DateAdapter class.

RELATED ARTICLES

Generate Namespace & Schema Information using JAXB

Most xml documents used in enterprise applications makes use of namespace to avoid element name conflicts. This article talks about generating these namespace and schema information when marshaling...

View Article

Object-XML Binding using JAXB

JAXB is a Java API that simplifies the access of XML documents within a Java Application. This articles demonstrates xml to object conversion and vice-versa using JAXB.

View Article

XML Schema Validation with JAXB

XML documents are often required to be validated against a schema, which contains some rules that the xml elements must respect. JAXB can be used to simplify this process of xml schema validation.

View Article