XML Unmarshalling – Convert XML to Java Objects using JAXB Version 3

In the world of software development, XML (eXtensible Markup Language) remains a widely used format for data exchange due to its human-readable structure and flexibility. However, working directly with XML data in Java can be cumbersome. This is where JAXB (Java Architecture for XML Binding) comes into play, allowing Java developers to easily convert XML data into Java objects and vice versa.

In this blog post, we'll explore how to perform XML unmarshalling using JAXB Version 3. Unmarshalling refers to the process of converting XML data into corresponding Java objects. We'll walk through the process, including required annotations and common pitfalls.

What is JAXB?

JAXB is a framework that helps bind Java objects to XML representations. It provides a convenient way to work with XML documents by automatically converting between XML and Java objects. JAXB enables you to:

  • Marshall Java objects into XML.
  • Unmarshall XML back into Java objects.

Starting from JAXB Version 3, the API has undergone some changes, including the removal of the JAXB reference implementation from Java SE (introduced in Java 11). You now need to include JAXB as a separate dependency if you're using Java 11 or later.

Setting up JAXB Version 3

To get started with JAXB in your project, you need to add the appropriate dependencies. If you're using Maven, include the following in your pom.xml:

<dependencies>

    <dependency>

        <groupId>jakarta.xml.bind</groupId>

        <artifactId>jakarta.xml.bind-api</artifactId>

        <version>3.0.0</version>

    </dependency>

    <dependency>

        <groupId>org.glassfish.jaxb</groupId>

        <artifactId>jaxb-runtime</artifactId>

        <version>3.0.0</version>

    </dependency>

</dependencies>

Unmarshalling with JAXB

Unmarshalling with JAXB involves converting an XML document into a corresponding Java object. This process requires a JAXB Unmarshaller and a valid XML structure. Let's look at the steps involved:

1. Create a Java Class to Represent the XML Structure

To unmarshal XML into Java objects, you need a Java class that corresponds to the XML structure. This class should have JAXB annotations to specify how the XML elements map to Java fields.

Here is an example:

XML file (person.xml):

<person>

    <name>John Doe</name>

    <age>30</age>

</person>

Java Class (Person.java):

import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Person {

    private String name;
    private int age;

    @XmlElement
    public String getName() {
        return name;
    }

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

    @XmlElement
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

In the Person class:

  • The @XmlRootElement annotation marks this class as the root element of the XML.
  • The @XmlElement annotation is used to bind the fields to XML elements.

2. Unmarshal the XML Document

Once the Java class is set up, you can use JAXB to unmarshal the XML into a Java object.

Here’s how you can do it:

import jakarta.xml.bind.JAXBContext;

import jakarta.xml.bind.JAXBException;

import jakarta.xml.bind.Unmarshaller;


import java.io.File;


public class Main {

    public static void main(String[] args) {

        try {

            // Create a JAXB context for the Person class

            JAXBContext context = JAXBContext.newInstance(Person.class);


            // Create an unmarshaller

            Unmarshaller unmarshaller = context.createUnmarshaller();


            // Unmarshal the XML file into a Person object

            File file = new File("person.xml");

            Person person = (Person) unmarshaller.unmarshal(file);


            // Print the result

            System.out.println("Name: " + person.getName());

            System.out.println("Age: " + person.getAge());

        } catch (JAXBException e) {

            e.printStackTrace();

        }

    }

}

In this example:

  • A JAXBContext is created for the Person class.
  • An Unmarshaller is then created from the context.
  • The unmarshal method is used to convert the XML document (person.xml) into a Person object.

3. Handle JAXBException

It's important to handle any potential JAXBException that may occur during unmarshalling. This could happen if the XML structure doesn't match the expected format or if the class is not properly annotated.

Handling Nested Elements

If the XML structure is more complex, such as having nested elements, JAXB allows you to annotate the corresponding Java fields to map these nested structures.

Example of a more complex XML:

XML (company.xml):

<company>

    <name>Tech Solutions</name>

    <employee>

        <name>John Doe</name>

        <age>30</age>

    </employee>

</company>

Java Classes (Company.java and Employee.java):

import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Company {

    private String name;
    private Employee employee;

    @XmlElement
    public String getName() {
        return name;
    }

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

    @XmlElement
    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }
}

class Employee {
    private String name;
    private int age;

    @XmlElement
    public String getName() {
        return name;
    }

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

    @XmlElement
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

Now, the Company class contains an Employee object, and JAXB will automatically handle the nested structure during unmarshalling.

4. Handle XML Attributes

If your XML uses attributes instead of elements, JAXB can handle this as well with the @XmlAttribute annotation.

XML with attributes (person.xml):

<person id="1">

    <name>John Doe</name>

    <age>30</age>

</person>

Java Class (Person.java):

import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Person {

    private int id;
    private String name;
    private int age;

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

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

    @XmlElement
    public String getName() {
        return name;
    }

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

    @XmlElement
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

In this case, the id attribute of the XML element is mapped to the id field in the Java class using the @XmlAttribute annotation.

Followers