This JAXB2 Helloworld example post explains the basics of JAXB along with core concepts like Mapping
, Marshalling
& Unmarshalling
XML to Java objects and vice versa, commonly used JAXB annotations
, JAXBContext
setup and API usage, XmlAdapter
usage etc.
Let’s go through them one by one:
1) Mapping
Mapping refers to binding Java objects to XML structures and vice versa. With JAXB, we specify this mapping using set of JAXB annotations on java classes and properties/methods.
Below is an example of how a POJO is mapped to XML using set of JAXB annotations.
package com.websystique.xml.model; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; 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", "section" }) public class Student { private int id; private String firstName; private String lastName; private LocalDate dob; private String section; @XmlAttribute(name = "id") public int getId() { return id; } 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; } @XmlElement(name = "birthDate") @XmlJavaTypeAdapter(LocalDateAdapter.class) 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 + "]"; } }
Here Student class and methods are mapped to XML Elements/attributes which will eventually generate following XML structure [HOW part is explained further in post]:
<Student id="1"> <firstName>Alan</firstName> <lastName>Turing</lastName> <birthDate>1956-10-01</birthDate> <section>Computer Science</section> </Student>
Commonly used Annotations:
@XmlRootElement
can be used to map a java class to the root of XML document produced by that class. Once applied on a class, all properties of that class maps to XML elements. You can however , use @XmlElement
on individual property/methods to override default behavior( for example specify an Element with different name in XML than in java, specify required/optional/nillable attributes). For example Student.dob will be mapped to birthDate in XML.
@XmlElementWrapper
can be used to create a wrapper around a collection of elements.
@XmlType
can be used to specify the order in which the properties of a java object will appear in XML document.
@XmlAttribute
can be used to map a property to an XML attribute.
Note that @XmlAttribute and @XmlElement can be applied on field level or on method level. In our case we are using them on methods.
2) Marshalling
Marshalling refers to actually converting mapped Java objects to XML [generating XML from mapped java objects]. This step involves JAXB core API’s.
In order to do it, first create a JAXBContext, specifying the root for the XML document
// create JAXB context JAXBContext context = JAXBContext.newInstance(Student.class);
Next, create Marshaller to Generate XML from mapped and populated Java objects using JAXBContext created above.
// Populate business objects[mapped class] Student s1 = new Student(); s1.setFirstName("Alan"); s1.setLastName("Turing"); s1.setSection("Computer Science"); s1.setDob(new LocalDate(1956, 10, 1)); s1.setId(1); // 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(s1, System.out); m.marshal(s1, new File(SOME_FILE));
Output of this step is the generated XML shown in Step 1 [repeated here].
<Student id="1"> <firstName>Alan</firstName> <lastName>Turing</lastName> <birthDate>1956-10-01</birthDate> <section>Computer Science</section> </Student>
3) UnMarshalling
UnMarshalling refers to populating the Mapped Java objects from input XML using JAXBContext API.
In order to do it, first create a JAXBContext, specifying the root for the XML document
// create JAXB context JAXBContext context = JAXBContext.newInstance(Student.class);
Next, create UnMarshaller to populate the Mapped objects with input XML using JAXBContext created above.We will use the same generated XML from above step for input in this step.
// UnMarshalling [Generate JAVA from XML] // Instantiate Unmarshaller via context Unmarshaller um = context.createUnmarshaller(); // Unmarshall the provided input XML into an object Student s = (Student) um.unmarshal(new FileReader(XML_FILE)); System.out.println("Student : " + s);
Output of UnMarshalling step is a populated java object:
Student : Student [id=1, firstName=Alan, lastName=Turing, dob=1956-10-01, section=Computer Science]
4) Using Adapters [Optional]
Adapters are used to convert java data types into XML types and vice versa. You may have noticed that we are using Joda-time LocalDate
class to specify dob property in Student class. But JAXB knows nothing about LocalDate. So we need to provide a way to help JAXB map this property into xml format. That’s where XmlAdapter
comes into play. Using XmlAdapter you can convert Java Type into XML type. In our case we are converting LocalDate to String format. We can specify the adapter to be used using @XmlJavaTypeAdapter
on respective property in java.
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(); } }
Above class provides a way to convert a LocalDate type into String and viceversa.
That’s all with basic usages. Below is the complete example for this post.
Complete Code Example
Following technologies being used:
- Maven 3
- JDK 1.6.0_45
- Joda Time 2.7
- Eclipse JUNO Service Release 2
Let’s begin.
Step 1: Create Project Directory Structure
Following will be the final project directory structure for this example:
Now let’s add the content mentioned in above structure explaining each in detail.
Step 2: Provide Dependencies in Maven pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.websystique.xml</groupId> <artifactId>JaxbBasicDemo</artifactId> <version>1.0.0</version> <packaging>jar</packaging> <name>JaxbBasicDemo</name> <properties> <joda-time.version>2.7</joda-time.version> </properties> <dependencies> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>${joda-time.version}</version> </dependency> </dependencies> </project>
There is no special dependencies to be declared. Since i am using Joda Time for any date time related processing (and also to show an important feature of JAXB), i’ll declare that here. You can skip it if you prefer to use Java Date api for the same.
Step 3: Create Model Classes for Marsahlling/UnMarshalling
Create Sample Java classes [POJOs], and annotate them with appropriate JAXB annotations, in order to provide mapping between Java and plain XML.
com.websystique.xml.model.Student
package com.websystique.xml.model; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; 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", "section" }) public class Student { private int id; private String firstName; private String lastName; private LocalDate dob; private String section; @XmlAttribute(name = "id") public int getId() { return id; } 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; } @XmlElement(name = "birthDate") @XmlJavaTypeAdapter(LocalDateAdapter.class) 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 + "]"; } }
com.websystique.xml.model.University
package com.websystique.xml.model; import java.util.List; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlRootElement(name = "University") @XmlType(propOrder = { "name", "address", "students" }) public class University { List<Student> students; private String name; private String address; @XmlElementWrapper(name = "Students") @XmlElement(name = "Student") public List<Student> getStudents() { return students; } public void setStudents(List<Student> students) { this.students = students; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
This post depicts an example of Student and University relation. Each student can have several properties. A University can have several properties and additionally multiple students.
Student and University classes[both are pojo’s] and there properties, are annotated with JAXB annotations. These annotations tells JAXB which property of a Java object will be mapped to which element or attribute in XML.
Step 4: Create Adapters [Optional]
com.websystique.xml.model.LocalDateAdapter
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(); } }
Above class provides a way to convert a LocalDate type into String and viceversa.
Step 5: Run it
Below is the complete Main class:
com.websystique.xml.JaxbBasicDemo
package com.websystique.xml; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.util.ArrayList; import java.util.List; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import org.joda.time.LocalDate; import com.websystique.xml.model.Student; import com.websystique.xml.model.University; public class JaxbBasicDemo { private static final String XML_FILE = "education_centers.xml"; public static void main(String[] args) throws JAXBException, FileNotFoundException { List<Student> students = new ArrayList<Student>(); Student s1 = new Student(); s1.setFirstName("Alan"); s1.setLastName("Turing"); s1.setSection("Computer Science"); s1.setDob(new LocalDate(1956, 10, 1)); s1.setId(1); students.add(s1); Student s2 = new Student(); s2.setFirstName("Thomas"); s2.setLastName("Edison"); s2.setSection("Physics"); s2.setDob(new LocalDate(1916, 3, 3)); s2.setId(2); students.add(s2); Student s3 = new Student(); s3.setFirstName("Linus"); s3.setLastName("Torvald"); s3.setSection("Computer Science"); s3.setDob(new LocalDate(1958, 11, 4)); s3.setId(3); students.add(s3); University university = new University(); university.setName("Cambridge"); university.setAddress("England"); university.setStudents(students); // create JAXB context JAXBContext context = JAXBContext.newInstance(University.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(university, System.out); m.marshal(university, new File(XML_FILE)); System.out.println("<!---------------Generating the Java objects from XML Input-------------->"); // UnMarshalling [Generate JAVA from XML] // Instantiate Unmarshaller via context Unmarshaller um = context.createUnmarshaller(); // Unmarshall the provided XML into an object University unif = (University) um.unmarshal(new FileReader(XML_FILE)); List<Student> studentsList = unif.getStudents(); for (Student s : studentsList) { System.out.println("Student : " + s); } } }
Below is the generated output:
<!----------Generating the XML Output--------------> <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <University> <name>Cambridge</name> <address>England</address> <Students> <Student id="1"> <firstName>Alan</firstName> <lastName>Turing</lastName> <birthDate>1956-10-01</birthDate> <section>Computer Science</section> </Student> <Student id="2"> <firstName>Thomas</firstName> <lastName>Edison</lastName> <birthDate>1916-03-03</birthDate> <section>Physics</section> </Student> <Student id="3"> <firstName>Linus</firstName> <lastName>Torvald</lastName> <birthDate>1958-11-04</birthDate> <section>Computer Science</section> </Student> </Students> </University> <!---------------Generating the Java objects from XML Input--------------> Student : Student [id=1, firstName=Alan, lastName=Turing, dob=1956-10-01, section=Computer Science] Student : Student [id=2, firstName=Thomas, lastName=Edison, dob=1916-03-03, section=Physics] Student : Student [id=3, firstName=Linus, lastName=Torvald, dob=1958-11-04, section=Computer Science]
That’s it. In the next post , we will discuss about the schema validation using JAXB.
Download Source Code
References
If you like tutorials on this site, why not take a step further and connect me on Facebook , Google Plus & Twitter as well? I would love to hear your thoughts on these articles, it will help improve further our learning process.