JAXB2 Annotations

This post explains some of the frequently used JAXB2 annotations. For the complete list of JAXB2 annotations, please visit API Page.

Let’s quickly have a look of the mapped class, and the XML it will generate, then we will go through annotations, one at a time.

Mapped Class

package com.websystique.xml.model;

import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlList;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

import org.joda.time.LocalDate;

@XmlRootElement(name = "Student")
@XmlType(propOrder = { "firstName", "lastName", "dob", "subjects", "groups" })
@XmlAccessorType(XmlAccessType.FIELD)
public class Student {

	@XmlAttribute(name = "id")
	private int id;

	private String firstName;

	@XmlElement(name="last-name")
	private String lastName;
	
	@XmlElement(name = "birthDate")
	@XmlJavaTypeAdapter(LocalDateAdapter.class)
	private LocalDate dob;
	
	@XmlTransient
	private String section;
	
	@XmlElementWrapper(name="all-subjects")
	@XmlElement(name="subject")
	private List<String> subjects;
	
	@XmlList
	private List<String> groups;
	
	public int getId() {
		return id;
	}

	public List<String> getSubjects() {
		return subjects;
	}

	public void setSubjects(List<String> subjects) {
		this.subjects = subjects;
	}

	public List<String> getGroups() {
		return groups;
	}

	public void setGroups(List<String> groups) {
		this.groups = groups;
	}

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

	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;
	}

	public String getSection() {
		return section;
	}

	public void setSection(String section) {
		this.section = section;
	}

	public LocalDate getDob() {
		return dob;
	}

	public void setDob(LocalDate dob) {
		this.dob = dob;
	}

	@Override
	public String toString() {
		return "Student [id=" + id + ", firstName=" + firstName + ", lastName="
				+ lastName + ", dob=" + dob + ", section=" + section + "]";
	}

}

Adapter class used in Mapped Class

package com.websystique.xml.model;

import javax.xml.bind.annotation.adapters.XmlAdapter;

import org.joda.time.LocalDate;

public class LocalDateAdapter extends XmlAdapter<String, LocalDate> {

	public LocalDate unmarshal(String v) throws Exception {
		return new LocalDate(v);
	}

	public String marshal(LocalDate v) throws Exception {
		return v.toString();
	}

}

Generated XML output

<!----------Generating the XML Output-------------->
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Student id="1">
    <firstName>Alan</firstName>
    <last-name>Turing</last-name>
    <birthDate>1956-10-01</birthDate>
    <all-subjects>
        <subject>Maths</subject>
        <subject>Science</subject>
        <subject>Economics</subject>
    </all-subjects>
    <groups>Techies Volunteers</groups>
</Student>

Now let’s go through annotations, one at a time:

@XmlRootElement

@XmlRootElement can be used to specify the root element of XML document generated by that particular class. By default class name is used as the root element, but you can specify a different name to be used via name attribute.

<student..>
...
</student>

@XmlType

@XmlType specify the order in which XML element will appear in generated XML. You can specify the prder using propOrder property.
In our case, the XML elements in generated XML appear in the same order as we specified in ‘propOrder’.

@XmlAccessorType

JAXB annotations can be used either on method level or on field level. You can specify the exact strategy to be used via @XmlAccessorType on class level, providing the actual strategy with XmlAccessType.

@XmlAttribute

@XmlAttribute maps a java-bean property to an XML attribute. In our example, we have specified id property to be an attribute.

<student id="1">
...
</student>

@XmlElement

@XmlElement maps a java-bean property to an XML Element. By default , once @XmlRootElement is declared on class level, all properties(or fields) will be treated as XML element with name as java-bean property name[unless they are decared otherwise, or are transient]

firstName java-bean property is mapped to firstName element in XML.

But you can specify a different name (using name attribute) if you prefer:

lastName java-bean property is mapped to last-name element in XML.

@XmlElementWrapper

@XmlElementWrapper can be used to create a wrapper around collection of elements.

In our case, we have created a wrapper all-subjects around subject collection.

    @XmlElementWrapper(name="all-subjects")
    @XmlElement(name="subject")
    private List<String> subjects;

maps to

    <all-subjects>
        <subject>Maths</subject>
        <subject>Science</subject>
        <subject>Economics</subject>
    </all-subjects>

@XmlList

@XmlList can be used to represent a collection of elements as space separated text.

    @XmlList
    private List<String> groups;

maps to

    <groups>Techies Volunteers</groups>

@XmlTransient

@XmlTransient prevents a java-bean property to be mapped in XML. By default, since the @XmlRootElement is present on class level, all the elements will be mapped to XML, but if a property is annotated with @XmlTransient, this will not be appear in generated XML.

In our case, property section is not present in generated XML.

@XmlJavaTypeAdapter

@XmlJavaTypeAdapter can be used to specify the adapter to be used for converting Java type to XML type and vice versa>.

    @XmlElement(name = "birthDate")
    @XmlJavaTypeAdapter(LocalDateAdapter.class)
    private LocalDate dob;

maps to

    <birthDate>1956-10-01</birthDate>

Below is the main class used to run this example.

package com.websystique.xml;

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

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.joda.time.LocalDate;

import com.websystique.xml.model.Student;

public class JaxbAnnotationsDemo {

	public static void main(String[] args) throws JAXBException{

		Student s = new Student();
		s.setFirstName("Alan");
		s.setLastName("Turing");
		s.setSection("Computer Science");
		s.setDob(new LocalDate(1956, 10, 1));
		s.setId(1);
	
		List<String> subjects = new ArrayList<String>();
		subjects.add("Maths");
		subjects.add("Science");
		subjects.add("Economics");

		List<String> groups = new ArrayList<String>();
		groups.add("Techies");
		groups.add("Volunteers");
		
		s.setGroups(groups);
		s.setSubjects(subjects);

		// create JAXB context
		JAXBContext context = JAXBContext.newInstance(Student.class);

		System.out.println("<!----------Generating the XML Output-------------->");
		
		// Marshalling [Generate XML from JAVA]
		// create Marshaller using JAXB context
		Marshaller m = context.createMarshaller();
		// To format the [to be]generated XML output
		m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
		// Marshall it and write output to System.out or to a file
		m.marshal(s, System.out);
	}

}

That’s it.

Download Source Code



References