How to run Rest API Tests in GitLab CI/CD

HOME

This tutorial explains the process to run the Rest API Tests in GitLab pipeline. This is a significant step towards achieving CI/CD. Ideally, the tests need to run after any change (minor/major) before merging the change to master branch. Suppose there are 100 changes in a day, and any QA won’t want to start the tests manually 100 times in a day. So, now adding tests to GitLab pipeline comes to the picture. We can add a test stage to the pipeline and the tests will run automatically when the pipeline run, or we can schedule the tests to run automatically every hour or day using GitLab pipeline.

Pre-Requisite:

  1. Rest Assured – 4.3.3
  2. Java 11
  3. Maven / Gradle
  4. TestNG /JUnit
  5. GitLab account

To use GitLab CI/CD, we need to keep 2 things in mind:-

a) Make sure a runner is available in GitLab to run the jobs. If there is no runner, install GitLab Runner and register a runner for your instance, project, or group.

b) Create a .gitlab-ci.yml file at the root of the repository. This file is where you define your CI/CD jobs.

Step 1 – Create a new Maven Project

Step 2 – Add the below mentioned pom.xml that shows all the dependencies need to add to the project

<dependencies>
      <!-- https://mvnrepository.com/artifact/org.testng/testng -->
      <dependency>
         <groupId>org.testng</groupId>
         <artifactId>testng</artifactId>
         <version>7.4.0</version>
         <scope>test</scope>
      </dependency>
      <!-- https://mvnrepository.com/artifact/io.rest-assured/rest-assured -->
      <dependency>
         <groupId>io.rest-assured</groupId>
         <artifactId>rest-assured</artifactId>
         <version>4.3.3</version>
         <scope>test</scope>
      </dependency>
      <!-- https://mvnrepository.com/artifact/org.json/json -->
      <dependency>
         <groupId>org.json</groupId>
         <artifactId>json</artifactId>
         <version>20210307</version>
      </dependency>
   </dependencies>
   <build>
      <plugins>
         <!-- Compiler plug-in -->
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <configuration>
               <source>11</source>
               <!--For JAVA 8 use 1.8-->
               <target>11</target>
               <!--For JAVA 8 use 1.8-->
            </configuration>
         </plugin>
         <!-- Added Surefire Plugin configuration to execute tests -->
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.0.0-M5</version>
            <configuration>
               <suiteXmlFiles>
                  <suiteXmlFile>testng.xml</suiteXmlFile>
               </suiteXmlFiles>
            </configuration>
         </plugin>
      </plugins>
   </build>
</project>

It is needed to add maven-surefire plugin to run the TestNG tests through command line. To know more about this, please refer to this tutorial.

Step 3 – Create the Test Code to test the Rest API

Here, 2 tests are created. One of the tests get all the employee data (GET) whereas another test creates an employee (POST).

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.equalTo;

import org.json.JSONObject;
import org.testng.annotations.Test;

import io.restassured.http.ContentType;

public class RestAPIDemo {

	@Test(description = "To get the details of employee with id 2", priority = 0)
	public void verifyUser() {

		// Given
		given()
				// When
				.when().get("http://dummy.restapiexample.com/api/v1/employee/2")
				// Then
				.then().statusCode(200).statusLine("HTTP/1.1 200 OK")
				// To verify booking id at index 3
				.body("data.employee_name", equalTo("Garrett Winters"))
				.body("message", equalTo("Successfully! Record has been fetched."));
	}

	@Test(description = "To create a new employee", priority = 1)
	public void createUser() {

		JSONObject data = new JSONObject();

		// Map<String, String> map = new HashMap<String, String>();

		data.put("employee_name", "APITest");
		data.put("employee_salary", "99999");
		data.put("employee_age", "30");

		// GIVEN
		given().baseUri("http://dummy.restapiexample.com/api").contentType(ContentType.JSON).body(data.toString())

				// WHEN
				.when().post("/v1/create")

				// THEN
				.then().statusCode(200).body("data.employee_name", equalTo("APITest"))
				.body("message", equalTo("Successfully! Record has been added."));

	}
}

Step 4 – Create testng.xml to run the tests through TestNG

Now, let’s create a testng.xml to run the TestNG tests. If JUnit is used instead of TestNG, then this step is not needed.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Suite">
  <test name="Test">
    <classes>
      <class name="com.example.RestAssured_TestNG_Demo.RestAPIDemo"/>
    </classes>
  </test> <!-- Test -->
</suite> <!-- Suite -->

Step 5 – Run the tests through command line

Now, let us execute the tests through command line. Go to the place where pom.xml of the project is placed and use the below command to run the tests. This step makes sure that all the test are running as expected.

GitLab Section

Step 6 – Create a blank project in GitLab

Refer to this tutorial to create a new blank project – How to create a new project in GitLab

Step 7 – Push the project from the local repository to GitLab Repository

Refer to this tutorial to push the changes – How to push new local GIT Repository to GitLab

Step 8 – Create .gitlab-ci.yml file in the project in GitLab

It is a YAML file where you configure specific instructions for GitLab CI/CD. In the .gitlab-ci.yml, we can define:

  • The scripts you want to run.
  • Other configuration files and templates you want to include.
  • Dependencies and caches.
  • The commands you want to run in sequence and those you want to run in parallel.
  • The location to deploy your application.
  • Whether you want to run the scripts automatically or trigger any of them manually.
image: adoptopenjdk/maven-openjdk11

stages:
  - test

variables:
  MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"

test:
  stage: test
  allow_failure: true

# Run the tests
  script:
    - mvn $MAVEN_OPTS clean package
    - mvn compile test

# Store artifacts
  artifacts:
    when: always
    name: "report"
    paths:
    - target/surefire-reports/*
    expire_in: 1 h

Step 9 – Run the tests in the GitLab pipeline

Now, when a new change is committed, a pipeline kicks off and it runs all the tests.

Step 10 – Check the status of the pipeline

Once the Status of the pipeline changes to either failed or passed.. that means the tests are already executed. Here, the pipeline is passed with brown color means that the execution of the test is completed with some failures.

I have added an artifact in the gitalb-ci.yml with the name “report”. This artifact creates a folder with the name “report” and the reports in this folder come from the path /target/surefire-reports. This artifact gives us an option to download the reports or browse the report. This report will be available for 1 hour only as mentioned in the gitlab-ci.yml.

Step 11 – Download the report

Click on the Download button and the report zip file is downloaded. Unzip the folder, and it contains all different types of surefire-reports.

Example of Emailable-Report.html

Example of Index.html

Congratulations. This tutorial has explain the steps to run Selenium tests in GitLab CI/CD. Happy Learning!!

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

HOME

The previous tutorial explain the Marshalling of Java Object to XML using JAXB Version 3.

There are tutorials about marshalling and unmarshalling XML using JAXB Version 2.

Marshalling – How to convert Java Objects to XML using JAXB

UnMarshalling- How to convert XML to Java Objects using JAXB

As of Java 11, JAXB is not part of the JRE anymore, and you need to configure the relevant libraries via your dependency management system, for example, either Maven or Gradle.

Configure the Java compiler level to be at least 11 and add the JAXB Version 3 dependencies to your pom file.

<!-- JAXB API v3.0.1 -->
<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <version>3.0.1</version>
</dependency>

<!-- JAXB v3.0.2 reference implementation (curiously with com.sun coordinates) -->
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>3.0.2</version>
    <scope>runtime</scope>
</dependency>

To know about the difference between JAXB Version 2 and JAXB Version3, refer this tutorial.

Sample XML Structure

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<EmployeeDetail>
    <firstName>Terry</firstName>
    <lastName>Mathew</lastName>
    <age>30</age>
    <salary>75000.0</salary>
    <designation>Manager</designation>
    <contactNumber>+919999988822</contactNumber>
    <emailId>abc@test.com</emailId>
    <gender>female</gender>
    <maritalStatus>married</maritalStatus>
</EmployeeDetail>

Now, let us create the Java Objects (POJO) of above XML.

import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "EmployeeDetail")
@XmlAccessorType(XmlAccessType.FIELD)
public class Employee {

	private String firstName;
	private String lastName;
	private int age;
	private double salary;
	private String designation;
	private String contactNumber;
	private String emailId;
	private String gender;
	private String maritalStatus;

	public Employee() {
		super();

	}

	// Getter and setter methods
	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 int getAge() {
		return age;
	}

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

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public String getDesignation() {
		return designation;
	}

	public void setDesignation(String designation) {
		this.designation = designation;
	}

	public String getContactNumber() {
		return contactNumber;
	}

	public void setContactNumber(String contactNumber) {
		this.contactNumber = contactNumber;
	}

	public String getEmailId() {
		return emailId;
	}

	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public String getMaritalStatus() {
		return maritalStatus;
	}

	public void setMaritalStatus(String maritalStatus) {
		this.maritalStatus = maritalStatus;
	}

    @Override
	public String toString() {
		return "Employee [FirstName=" + firstName + ", LastName=" + lastName + ", Age=" + age + ", Salary=" + salary
				+ ", Designation=" + designation + ", ContactNumber=" + contactNumber + ", EmailId=" + emailId
				+ ", Gender=" + gender + ", MaritalStatus=" + maritalStatus + "]";
	}
}

Let’s create a simple program using the JAXBContext which provides an abstraction for managing the XML/Java binding information necessary to implement the JAXB binding framework operations and unmarshal.

import java.io.File;

import org.junit.Test;

import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Unmarshaller;

public class JAXBDeserialization {

	@Test
	public void JAXBUnmarshalTest() {

		try {

			String userDir = System.getProperty("user.dir");
			File file = new File(userDir + "\\src\\test\\resources\\JAXB_XML.xml");

			JAXBContext jaxbContext = JAXBContext.newInstance(Employee.class);

			Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
			Employee employee = (Employee) jaxbUnmarshaller.unmarshal(file);
			System.out.println(employee);

		} catch (JAXBException e) {
			e.printStackTrace();
		}

	}

When we run the code above, we may check the console output to verify that we have successfully converted XML data into a Java object:

This response is the result of the toString() method in POJO Class.

There is another way to get the values of each node of XML.

   @Test
	public void JAXBUnmarshalTest1() {

		try {

			String userDir = System.getProperty("user.dir");
			File file = new File(userDir + "\\src\\test\\resources\\JAXB_XML.xml");

			JAXBContext jaxbContext = JAXBContext.newInstance(Employee.class);

			Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
			Employee employee = (Employee) jaxbUnmarshaller.unmarshal(file);

			System.out.println("FirstName: " + employee.getFirstName());
			System.out.println("LastName: " + employee.getLastName());
			System.out.println("Age: " + employee.getAge());
			System.out.println("Salary: " + employee.getSalary());
			System.out.println("Contact Number: " + employee.getContactNumber());
			System.out.println("Designation: " + employee.getDesignation());
			System.out.println("Gender: " + employee.getGender());
			System.out.println("EmailId: " + employee.getEmailId());
			System.out.println("MaritalStatus: " + employee.getMaritalStatus());

		} catch (JAXBException e) {
			e.printStackTrace();
		}

	}

When we run the code above, we may check the console output to verify that we have successfully converted XML data into a Java object:

The Unmarshaller class governs the process of deserializing XML data into newly created Java content trees, optionally validating the XML data as it is unmarshalled. It provides overloading of unmarshal methods for many input kinds.

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

XML Marshalling – Convert Java objects to XML using JAXB Version 3

HOME

The previous tutorials have explained marshalling and unmarshalling of XML using JAXB Version 2.

As of Java 11, JAXB is not part of the JRE anymore, and you need to configure the relevant libraries via your dependency management system, for example, either Maven or Gradle.

Configure the Java compiler level to be at least 11 and add the JAXB Version 3 dependencies to your pom file.

<!-- JAXB API v3.0.1 -->
<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <version>3.0.1</version>
</dependency>

<!-- JAXB v3.0.2 reference implementation (curiously with com.sun coordinates) -->
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>3.0.2</version>
    <scope>runtime</scope>
</dependency>

Difference between javax.xml.* and jakarta.xml.*

Eclipse foundation rebrand the Java EE javax.xml.* to Jakarta EE jakarta.xml.*.

Below are some JAXB APIs in versions 2 and 3.

//@Since 3.0.0, rebrand to Jakarta.xml

import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlTransient;
import jakarta.xml.bind.annotation.XmlType;

import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.PropertyException;
import jakarta.xml.bind.Unmarshaller;

//JAXB Version 2.0

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;

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

Sample XML Structure

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<EmployeeDetail>
    <firstName>Terry</firstName>
    <lastName>Mathew</lastName>
    <age>30</age>
    <salary>75000.0</salary>
    <designation>Manager</designation>
    <contactNumber>+919999988822</contactNumber>
    <emailId>abc@test.com</emailId>
    <gender>female</gender>
    <maritalStatus>married</maritalStatus>
</EmployeeDetail>

Now, let us create the Java Objects (POJO) of the above XML.

import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "EmployeeDetail")
@XmlAccessorType(XmlAccessType.FIELD)
public class Employee {

	private String firstName;
	private String lastName;
	private int age;
	private double salary;
	private String designation;
	private String contactNumber;
	private String emailId;
	private String gender;
	private String maritalStatus;

	public Employee() {
		super();

	}

	// Getter and setter methods
	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 int getAge() {
		return age;
	}

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

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public String getDesignation() {
		return designation;
	}

	public void setDesignation(String designation) {
		this.designation = designation;
	}

	public String getContactNumber() {
		return contactNumber;
	}

	public void setContactNumber(String contactNumber) {
		this.contactNumber = contactNumber;
	}

	public String getEmailId() {
		return emailId;
	}

	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public String getMaritalStatus() {
		return maritalStatus;
	}

	public void setMaritalStatus(String maritalStatus) {
		this.maritalStatus = maritalStatus;
	}

    @Override
	public String toString() {
		return "Employee [FirstName=" + firstName + ", LastName=" + lastName + ", Age=" + age + ", Salary=" + salary
				+ ", Designation=" + designation + ", ContactNumber=" + contactNumber + ", EmailId=" + emailId
				+ ", Gender=" + gender + ", MaritalStatus=" + maritalStatus + "]";
	}
}

Let’s create a simple program using the JAXBContext which provides an abstraction for managing the XML/Java binding information necessary to implement the JAXB binding framework operations.

import java.io.StringWriter;

import org.junit.Test;

import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.PropertyException;

public class JAXBSerialization {

	@Test
	public void serializationTest1() {

		try {

			Employee employee = new Employee();

			employee.setFirstName("Terry");
			employee.setLastName("Mathew");
			employee.setAge(30);
			employee.setSalary(75000);
			employee.setDesignation("Manager");
			employee.setContactNumber("+919999988822");
			employee.setEmailId("abc@test.com");
			employee.setMaritalStatus("married");
			employee.setGender("female");

			// Create JAXB Context
			JAXBContext context = JAXBContext.newInstance(Employee.class);

			// Create Marshaller
			Marshaller jaxbMarshaller = context.createMarshaller();

			// Required formatting
			jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

			// Print XML String to Console
			StringWriter sw = new StringWriter();

			// Write XML to StringWriter
			jaxbMarshaller.marshal(employee, sw);

			// Verify XML Content
			String xmlContent = sw.toString();
			System.out.println(xmlContent);

		} catch (PropertyException e) {
			e.printStackTrace();

		} catch (JAXBException e) {

		}
	}

}

When we run the code above, we may check the console output to verify that we have successfully converted the Java object into XML:

The Marshaller class is responsible for governing the process of serializing Java content trees back into XML data.

I hope this has helped you to understand the use of JAXB Version 3.

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

How to test JSON Request using GSON API

HOME

In this tutorial, I will explain the testing of a JSON Payload using GSON API.

Refer to the below tutorials to understand how GSON works:-

Serialization – How to convert Java Object To JSON Object Using Gson API

Deserialization – How to create JSON Object to JAVA Object Using Gson API

Add below dependency to POM.xml to use Gson API.

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.9</version>
</dependency>

As we know, we can use toJson() to convert the JAVA objects to JSON Payload.

In the below example, I have created a POJO class with the name of EmployeeDetails. This class contains the data members corresponding to the JSON nodes and their corresponding getter and setter methods.

public class EmployeeDetails {

	// private variables or data members of pojo class
	private String name;
	private double salary;
	private int age;

	public String getName() {
		return name;
	}

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

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public int getAge() {
		return age;
	}

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

}

Below, will create a JSON payload and pass it as a request body to the Rest API.

	@Test
	public void createEmployee() throws IOException {

		// Just create an object of Pojo class
		EmployeeDetails emp = new EmployeeDetails();
		emp.setName("GsonTest");
		emp.setSalary(50000);
		emp.setAge(25);

		// Converting a Java class object to a JSON payload as string using Gson
		Gson builder = new GsonBuilder().setPrettyPrinting().create();
		String employeePrettyJsonPayload = builder.toJson(emp);
		System.out.println("Request");
		System.out.println(employeePrettyJsonPayload);
		System.out.println("=========================================");
		System.out.println("Response");

		// GIVEN
		given()
              .baseUri("http://dummy.restapiexample.com/api")
              .contentType(ContentType.JSON).body(emp)

		// WHEN
		.when()
               .post("/v1/create")

		// THEN
		.then()
              .assertThat().statusCode(200)
              .body("status", equalTo("success"))
			  .body("data.name", equalTo("GsonTest"))
              .body("data.salary", equalTo(50000))
			  .body("data.age", equalTo(25))
              .body("message", equalTo("Successfully! Record has been added."))
              .log().body();

	}
}

Output

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

@XmlElementWrapper Annotation for XML – JAXB

HOME

The previous tutorials explain how to use JAXB(Java Architecture for XML Binding) to parse XML documents to Java objects and vice versa. This is also called Marshalling and Unmarshalling.

This tutorial explains @XmlElementWrapper Annotation.

Configure the Java compiler level to be at least 11 and add the JAXB dependencies to the pom file.

<?xml version="1.0" encoding="UTF-8"?>

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>JAXBDemo</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <name>JAXBDemo</name>
  <url>http://www.example.com</url>

  <properties>  

    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
  </dependency>
    
 <dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.3.3</version>
   </dependency>
 </dependencies>
   
</project>

@XmlElementWrapper generates a wrapper element around XML representation. This is primarily intended to be used to produce a wrapper XML element around collections.

This annotation can be used with the following annotations –  XmlElementXmlElementsXmlElementRefXmlElementRefsXmlJavaTypeAdapter.

@XmlElementWrapper and @XmlElement (Wrapped collection)

Let us understand this with the help of an example shown below.

@XmlRootElement(name = "CustomerDetails")
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {

	private int id;

	private String name;
	private int yearOfBirth;
	private String emailId;
	private String streetAddress;

	private String postcode;

	@XmlElementWrapper(name = "emergencyContacts")
	@XmlElement(name = "Contact")
	private List<String> emergencyContacts;

	public Customer() {
		super();
	}

	public Customer(int id, String name, int yearOfBirth, String emailId, String streetAddress, String postcode,
			List<String> emergencyContacts) {
		super();
		this.id = id;
		this.name = name;
		this.yearOfBirth = yearOfBirth;
		this.emailId = emailId;
		this.streetAddress = streetAddress;
		this.postcode = postcode;
		this.emergencyContacts = emergencyContacts;
	}

	public int getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

	public int getYearOfBirth() {
		return yearOfBirth;
	}

	public void setYearOfBirth(int yearOfBirth) {
		this.yearOfBirth = yearOfBirth;
	}

	public String getEmailId() {
		return emailId;
	}

	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}

	public String getStreetAddress() {
		return streetAddress;
	}

	public void setStreetAddress(String streetAddress) {
		this.streetAddress = streetAddress;
	}

	public String getPostcode() {
		return postcode;
	}

	public void setPostcode(String postcode) {
		this.postcode = postcode;
	}

	public List<String> getEmergencyContacts() {
		return emergencyContacts;
	}

	public void setEmergencyContacts(List<String> emergencyContacts) {
		this.emergencyContacts = emergencyContacts;
	}
}

Now, let us create a Test to convert these Java Objects to XML.

   @Test
	public void Test() {

		try {

			Customer cust = new Customer();
			cust.setId(1111);
			cust.setName("Tim");
			cust.setYearOfBirth(1988);
			cust.setEmailId("Test@test.com");
			cust.setStreetAddress("6, JaySmith, Dublin");
			cust.setPostcode("A12 YP22");

			cust.setEmergencyContacts(Arrays.asList("98675 12312", "88881 23415", "44123 67453"));

			// Create JAXB Context
			JAXBContext context = JAXBContext.newInstance(Customer.class);

			// Create Marshaller
			Marshaller jaxbMarshaller = context.createMarshaller();

			// Required formatting
			jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

			// Write XML to StringWriter
			StringWriter sw = new StringWriter();
			jaxbMarshaller.marshal(cust, sw);

			// Print XML Content
			String xmlContent = sw.toString();
			System.out.println(xmlContent);

		} catch (PropertyException e) {
			e.printStackTrace();

		} catch (JAXBException e) {

		}
	}

Here, contact is within emergencyContacts, because contact is @XmlElement.

Use Only @XmlElementWrapper

@XmlRootElement(name = "CustomerDetails")
@XmlAccessorType(XmlAccessType.FIELD)

public class Customer {

	private int id;

	private String name;
	private int yearOfBirth;
	private String emailId;
	private String streetAddress;

	private String postcode;

	@XmlElementWrapper(name = "emergencyContacts")
 //	@XmlElement(name = "Contact") //Commented this
	private List<String> emergencyContacts;

	public Customer() {
		super();
	}

	public Customer(int id, String name, int yearOfBirth, String emailId, String streetAddress, String postcode,
			List<String> emergencyContacts) {
		super();
		this.id = id;
		this.name = name;
		this.yearOfBirth = yearOfBirth;
		this.emailId = emailId;
		this.streetAddress = streetAddress;
		this.postcode = postcode;
		this.emergencyContacts = emergencyContacts;
	}

Here, there is no contact within emergencyContacts, it is because there is no @XmlElement for contact.

Do not use @XmlElementWrapper (Unwrapped collection)

@XmlRootElement(name = "CustomerDetails")
@XmlAccessorType(XmlAccessType.FIELD)

public class Customer {

	private int id;

	private String name;
	private int yearOfBirth;
	private String emailId;
	private String streetAddress;

	private String postcode;

 //@XmlElementWrapper(name = "emergencyContacts") Commented this
	@XmlElement(name = "Contact")
	private List<String> emergencyContacts;

	public Customer() {
		super();
	}

	public Customer(int id, String name, int yearOfBirth, String emailId, String streetAddress, String postcode,
			List<String> emergencyContacts) {
		super();
		this.id = id;
		this.name = name;
		this.yearOfBirth = yearOfBirth;
		this.emailId = emailId;
		this.streetAddress = streetAddress;
		this.postcode = postcode;
		this.emergencyContacts = emergencyContacts;
	}

Here, there is no @XmlElementWrapper. So, all the contact appear as attributes of XML.

I hope this has helped to understand the usage of @XmlElementWrapper.

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

UnMarshalling- How to convert XML to Java Objects using JAXB

HOME

This tutorial explains how to use JAXB (Java Architecture for XML Binding) to convert an XML document to Java Objects.

The previous tutorial has explained the conversion of Java Objects to XML.

As of Java 11, JAXB is not part of the JRE anymore, and you need to configure the relevant libraries via your dependency management system, for example, either Maven or Gradle.

Configure the Java compiler level to be at least 11 and add the JAXB dependencies to your pom file.

<?xml version="1.0" encoding="UTF-8"?>
 
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>org.example</groupId>
  <artifactId>JAXBDemo</artifactId>
  <version>0.0.1-SNAPSHOT</version>
 
  <name>JAXBDemo</name>
  <url>http://www.example.com</url>
 
  <properties>  
 
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>
 
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
  </dependency>
     
 <dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.3.3</version>
   </dependency>
 </dependencies>
    
</project>

Sample XML Structure

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<EmployeeDetails>
    <firstName>Terry</firstName>
    <lastName>Mathew</lastName>
    <gender>female</gender>
    <age>30</age>
    <maritalStatus>married</maritalStatus>
    <designation>Manager</designation>
    <contactNumber>+919999988822</contactNumber>
    <emailId>abc@test.com</emailId>
    <GrossSalary>75000.0</GrossSalary>
</EmployeeDetails>

Un-marshalling provides a client application the ability to convert XML data into JAXB derived Java objects.

Let’s see the steps to convert XML document into java object.

  1. Create POJO Class
  2. Create the JAXBContext object
  3. Create the Unmarshaller objects
  4. Call the unmarshal method
  5. Use getter methods of POJO to access the data

Now, let us create the Java Objects (POJO) for the above XML.

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlRootElement(name = "EmployeeDetails")
@XmlAccessorType(XmlAccessType.FIELD)

//Define the order in which the fields are written in XML
@XmlType(propOrder = { "firstName", "lastName", "gender", "age", "maritalStatus", "designation", "contactNumber","emailId", "salary" })

public class Employee {

	private String firstName;
	private String lastName;
	private int age;

	@XmlElement(name = "GrossSalary")
	private double salary;
	private String designation;
	private String contactNumber;
	private String emailId;
	private String gender;
	private String maritalStatus;

	public Employee() {
		super();

	}

	// Getter and setter methods
	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 int getAge() {
		return age;
	}

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

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public String getDesignation() {
		return designation;
	}

	public void setDesignation(String designation) {
		this.designation = designation;
	}

	public String getContactNumber() {
		return contactNumber;
	}

	public void setContactNumber(String contactNumber) {
		this.contactNumber = contactNumber;
	}

	public String getEmailId() {
		return emailId;
	}

	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public String getMaritalStatus() {
		return maritalStatus;
	}

	public void setMaritalStatus(String maritalStatus) {
		this.maritalStatus = maritalStatus;
	}

	@Override
	public String toString() {
		return "Employee [FirstName=" + firstName + ", LastName=" + lastName + ", Age=" + age + ", Salary=" + salary
				+ ", Designation=" + designation + ", ContactNumber=" + contactNumber + ", EmailId=" + emailId
				+ ", Gender=" + gender + ", MaritalStatus=" + maritalStatus + "]";
	}
}

Create the following test program for reading the XML file. The XML file is present under src/test/resources.

Let’s use JAXB Unmarshaller to unmarshal our JAXB_XML back to a Java object:

import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import org.junit.Test;

public class JAXBDeserialization {
	
	@Test
	public void JAXBUnmarshalTest() {

		try {

			String userDir = System.getProperty("user.dir");
			File file = new File(userDir + "\\src\\test\\resources\\JAXB_XML.xml");
			JAXBContext jaxbContext = JAXBContext.newInstance(Employee.class);

			Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
			Employee employee = (Employee) jaxbUnmarshaller.unmarshal(file);

			System.out.println("FirstName: " + employee.getFirstName());
			System.out.println("LastName: " + employee.getLastName());
			System.out.println("Age: " + employee.getAge());
			System.out.println("Salary: " + employee.getSalary());
			System.out.println("Contact Number: " + employee.getContactNumber());
			System.out.println("Designation: " + employee.getDesignation());
			System.out.println("Gender: " + employee.getGender());
			System.out.println("EmailId: " + employee.getEmailId());
			System.out.println("MaritalStatus: " + employee.getMaritalStatus());

		} catch (JAXBException e) {
			e.printStackTrace();
		}

	}

	}

When we run the code above, we may check the console output to verify that we have successfully converted XML data into a Java object:

There is another simple way of unmarshalling the XML to Java Objects.

    @Test
	public void JAXBUnmarshalTest1() {

		try {

			String userDir = System.getProperty("user.dir");
			File file = new File(userDir + "\\src\\test\\resources\\JAXB_XML.xml");

			JAXBContext jaxbContext = JAXBContext.newInstance(Employee.class);
			Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
			Employee emp = (Employee) jaxbUnmarshaller.unmarshal(file);

			System.out.println(emp);

		} catch (JAXBException e) {
			e.printStackTrace();
		}
	}

When we run the code above, we may check the console output to verify that we have successfully converted XML data into a Java object:

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

Marshalling- How to convert Java Objects to XML using JAXB

HOME

This tutorial explains how to use JAXB (Java Architecture for XML Binding) to convert Java Objects to XML documents.

JAXB provides a fast and convenient way to marshal (write) Java Objects into XML and un-marshal (read) XML into Java Objects. It supports a binding framework that maps XML elements and attributes to Java fields and properties using Java annotations.

With Java releases lower than Java 11, JAXB was part of the JVM and you could use it directly without defining additional libraries.

As of Java 11, JAXB is not part of the JRE anymore, and you need to configure the relevant libraries via your dependency management system, for example, either Maven or Gradle.

Configure the Java compiler level to be at least 11 and add the JAXB dependencies to your pom file.

<?xml version="1.0" encoding="UTF-8"?>

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>JAXBDemo</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <name>JAXBDemo</name>
  <url>http://www.example.com</url>

  <properties>  

    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
  </dependency>
    
 <dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.3.3</version>
   </dependency>
 </dependencies>
   
</project>

JAXB Annotations

  1. @XmlRootElement: Define the root element for an XML tree
  2. @XmlType: Define the order in which the fields are written in the XML file
  3. @XmlElement: Define the actual XML element name which will be used
  4. @XmlAttribute: Define the id field is mapped as an attribute instead of an element
  5. @XmlTransient: Annotate fields that we don’t want to be included in XML

Sample XML Structure

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<EmployeeDetails>
    <firstName>Vibha</firstName>
    <lastName>Singh</lastName>
    <gender>female</gender>
    <age>30</age>
    <maritalStatus>married</maritalStatus>
    <designation>Manager</designation>
    <contactNumber>+919999988822</contactNumber>
    <emailId>abc@test.com</emailId>
    <GrossSalary>75000.0</GrossSalary>
</EmployeeDetails>

Marshalling

Marshalling provides a client application the ability to convert a JAXB derived Java object tree into XML data.

Let’s see the steps to convert Java Objects into XML document.

  1. Create POJO Class of XML
  2. Create the JAXBContext object
  3. Create the Marshaller objects
  4. Create the content tree by using set methods
  5. Call the marshal method

Now, let us create the Java Objects (POJO).

@XmlRootElement(name = "EmployeeDetails")
@XmlAccessorType(XmlAccessType.FIELD)

//Define the order in which the fields are written in XML
@XmlType(propOrder = { "firstName", "lastName", "gender", "age", "maritalStatus", "designation", "contactNumber",
		"emailId", "salary" })

public class Employee {

	private String firstName;
	private String lastName;
	private int age;

    @XmlElement(name = "GrossSalary")
	private double salary;
	private String designation;
	private String contactNumber;
	private String emailId;
	private String gender;
	private String maritalStatus;

	// Getter and setter methods
	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 int getAge() {
		return age;
	}

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

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public String getDesignation() {
		return designation;
	}

	public void setDesignation(String designation) {
		this.designation = designation;
	}

	public String getContactNumber() {
		return contactNumber;
	}

	public void setContactNumber(String contactNumber) {
		this.contactNumber = contactNumber;
	}

	public String getEmailId() {
		return emailId;
	}

	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public String getMaritalStatus() {
		return maritalStatus;
	}

	public void setMaritalStatus(String maritalStatus) {
		this.maritalStatus = maritalStatus;
	}

   @Override
	public String toString() {
		return "Employee [FirstName=" + firstName + ", LastName=" + lastName + ", Age=" + age + ", Salary=" + salary
				+ ", Designation=" + designation + ", ContactNumber=" + contactNumber + ", EmailId=" + emailId
				+ ", Gender=" + gender + ", MaritalStatus=" + maritalStatus + "]";
	}
}

Create the following test program for writing the XML file.

   @Test
	public void serializationTest1() {

		try {

			Employee employee = new Employee();

			employee.setFirstName("Terry");
			employee.setLastName("Mathew");
			employee.setAge(30);
			employee.setSalary(75000);
			employee.setDesignation("Manager");
			employee.setContactNumber("+919999988822");
			employee.setEmailId("abc@test.com");
			employee.setMaritalStatus("married");
			employee.setGender("female");

			// Create JAXB Context
			JAXBContext context = JAXBContext.newInstance(Employee.class);

			// Create Marshaller
			Marshaller jaxbMarshaller = context.createMarshaller();

			// Required formatting
			jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

           // Write XML to StringWriter
			StringWriter sw = new StringWriter();	
			jaxbMarshaller.marshal(employee, sw);

			// Convert XML to String
			String xmlContent = sw.toString();
			System.out.println(xmlContent);

		} catch (PropertyException e) {
			e.printStackTrace();

		} catch (JAXBException e) {

		}
	}

When we run the code above, we may check the console output to verify that we have successfully converted Java object to XML:

By default, the Marshaller uses UTF-8 encoding when generating XML data.

The javax.xml.bind.JAXBContext class provides a client’s entry point to JAXB API. By default, JAXB does not format the XML document. This saves space and prevents that any white-space may accidentally be interpreted as significant.

To have JAXB format the output, we simply set the Marshaller.JAXB_FORMATTED_OUTPUT property to true on the Marshaller. The marshal method uses an object and an output file where to store the generated XML as parameters.

You can see that we have used JAXB Annotations like @XMLRootElement are changed from Employee to EmployeeDetails.

The order of elements in the XML is defined by

@XmlType(propOrder = { "firstName", "lastName", "gender", "age", "maritalStatus", "designation", "contactNumber","emailId", "salary" })

@XMLElement has set the element name to GrossSalary from Salary.

The below example is the short way of writing the same test and saving XML. We need to add a constructor in the POJO class so that we can set the values to the variables through the Constructor.

@XmlRootElement(name = "EmployeeDetails")
@XmlAccessorType(XmlAccessType.FIELD)

//Define the order in which the fields are written in XML
@XmlType(propOrder = { "firstName", "lastName", "gender", "age", "maritalStatus", "designation", "contactNumber",
		"emailId", "salary" })

public class Employee {

	private String firstName;
	private String lastName;
	private int age;

	private double salary;
	private String designation;
	private String contactNumber;
	private String emailId;
	private String gender;
	private String maritalStatus;

	public Employee() {
		super();

	}

	public Employee(String firstName, String lastName, int age, double salary, String designation, String contactNumber,
			String emailId, String gender, String maritalStatus) {

		this.firstName = firstName;
		this.lastName = lastName;
		this.age = age;

       @XmlElement(name = "GrossSalary")
		this.salary = salary;
		this.designation = designation;
		this.contactNumber = contactNumber;
		this.emailId = emailId;
		this.gender = gender;
		this.maritalStatus = maritalStatus;
	}

	// Getter and setter methods
	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 int getAge() {
		return age;
	}

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

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public String getDesignation() {
		return designation;
	}

	public void setDesignation(String designation) {
		this.designation = designation;
	}

	public String getContactNumber() {
		return contactNumber;
	}

	public void setContactNumber(String contactNumber) {
		this.contactNumber = contactNumber;
	}

	public String getEmailId() {
		return emailId;
	}

	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public String getMaritalStatus() {
		return maritalStatus;
	}

	public void setMaritalStatus(String maritalStatus) {
		this.maritalStatus = maritalStatus;
	}

  @Override
	public String toString() {
		return "Employee [FirstName=" + firstName + ", LastName=" + lastName + ", Age=" + age + ", Salary=" + salary
				+ ", Designation=" + designation + ", ContactNumber=" + contactNumber + ", EmailId=" + emailId
				+ ", Gender=" + gender + ", MaritalStatus=" + maritalStatus + "]";
	}
}

The below JAXB example for XML marshalling convert Java objects into an XML.

    @Test
	public void serializationTest2() {

		try {

			Employee employee = new Employee("Thomas", "Pawsey", 35, 100000, "Director", "+919999988822","Test@test.com", "married", "female");

			// Create JAXB Context
			JAXBContext context = JAXBContext.newInstance(Employee.class);

			// Create Marshaller
			Marshaller jaxbMarshaller = context.createMarshaller();

			// Required formatting
			jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

			// Write XML to StringWriter
			StringWriter writer = new StringWriter();
			jaxbMarshaller.marshal(employee, writer);

			// Convert XML to String
			String xmlContent = writer.toString();
			System.out.println(xmlContent);

			// Save the file
			String userDir = System.getProperty("user.dir");
			jaxbMarshaller.marshal(employee, new File(userDir + "\\src\\test\\resources\\JAXB_XML.xml"));

		} catch (PropertyException e) {
			e.printStackTrace();

		} catch (JAXBException e) {

		}
	}
}

When we run the code above, we may check the console output to verify that we have successfully converted Java object to XML:

The XML is saved under src/test/resources. To see this file, after the execution of the test, you need to refresh the project.

Similarly, we can unmarshal an XML to Java Objects in the next tutorial.

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

Jackson Annotations for XML – JacksonXmlRootElement

HOME

The Jackson XML module adds some additional support for XML-specific features, just like JSON has some additional features. These annotations allow us to control the XML namespace and local name for elements, including the root element, whether a field is rendered in an element or as plain text, whether the content of an element is rendered in a CData wrapper, and whether a collection should use a wrapper element or not.

We need to add Jackson XML dependency to the project.

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.13.0</version>
</dependency>

It is used to define the name of the root element used for the root-level object when serialized, which normally uses the name of the type (class). This can only adjust the Namespace and Local name – since the root element can never be serialized as an attribute.

@JacksonXmlRootElement(localName = "Employee_Details")

Below is the example of JacksonXmlRootElement.

@JacksonXmlRootElement(localName = "Employee_Details")
public class Employee {

	// private variables or data members of POJO class
	private String firstName;
	private String lastName;
	private int age;
	private double salary;
	private String designation;
	private String contactNumber;
	private String emailId;
	private String gender;
	private String maritalStatus;

	// Getter and setter methods
	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 int getAge() {
		return age;
	}

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

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public String getDesignation() {
		return designation;
	}

	public void setDesignation(String designation) {
		this.designation = designation;
	}

	public String getContactNumber() {
		return contactNumber;
	}

	public void setContactNumber(String contactNumber) {
		this.contactNumber = contactNumber;
	}

	public String getEmailId() {
		return emailId;
	}

	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public String getMaritalStatus() {
		return maritalStatus;
	}

	public void setMaritalStatus(String maritalStatus) {
		this.maritalStatus = maritalStatus;
	}

}

Let us create a test to build an XML.

public class EmployeeXMLTest {

	@Test
	public void serializationTest() {

		Employee employee = new Employee();

		employee.setFirstName("Vibha");
		employee.setLastName("Singh");
		employee.setAge(30);
		employee.setSalary(75000);
		employee.setDesignation("Manager");
		employee.setContactNumber("+919999988822");
		employee.setEmailId("abc@test.com");
		employee.setMaritalStatus("married");
		employee.setGender("female");

		// Converting a Java class object to XML
		XmlMapper xmlMapper = new XmlMapper();

		try {
			String employeeXml = xmlMapper.writerWithDefaultPrettyPrinter().writeValueAsString(employee);
			System.out.println(employeeXml);

		} catch (JsonProcessingException e) {
			e.printStackTrace();
		} 
	}
}

You can see here that localName of XML is Employee_Details, not Employee.

@JacksonXmlRootElement(namespace = "urn:request:jacksonxml", localName = "Employee_Details")

The XML is shown below.

Hope this helps to understand @JacksonXmlRootElement.

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!


Deserialization – How to convert XML to Java Objects using Jackson API

HOME

The previous tutorials have explained the conversion of Java Objects to XML using Jackson API. This tutorial explains parsing the XML document to Java objects using Jackson API.

To parse the XML, we will use the Jackson library. Use the latest Jackson library.

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.13.0</version>
</dependency>

Jackson allows us to read the contents of an XML file and deserialize the XML back into a Java object. In our example, we will read an XML document containing details about an Employee, and use Jackson to extract this data and use it to create Java objects containing the same information.

First, let us create an XML document matching our class to read from. Create to_deserialize.xml with the following contents:

<Employee>
  <firstName>Vibha</firstName>
  <lastName>Singh</lastName>
  <age>30</age>
  <salary>75000.0</salary>
  <designation>Manager</designation>
  <contactNumber>+919999988822</contactNumber>
  <emailId>abc@test.com</emailId>
  <gender>female</gender>
  <maritalStatus>married</maritalStatus>
</Employee>

Deserialization – It is the reverse of serializing. In this process, we will read the Serialized byte stream from the file and convert it back into the Class instance representation. Here, we are converting a XML to an Employee class object.

Let us add a deserializeFromXML() function to deserialize the XML file above into a Java object:

	@Test
	public void deserializeFromXML() {

		XmlMapper xmlMapper = new XmlMapper();
		String userDir = System.getProperty("user.dir");

		// Converting Employee XML to Employee class object
		try {
			Employee emp = xmlMapper.readValue(new File(userDir + "\\src\\test\\resources\\XMLExample.xml"),
					Employee.class);
			System.out.println("Deserialized data: ");
			System.out.println("First Name of employee : " + emp.getFirstName());
			System.out.println("Last Name of employee : " + emp.getLastName());
			System.out.println("Age of employee : " + emp.getAge());
			System.out.println("Salary of employee : " + emp.getSalary());
			System.out.println("Designation of employee : " + emp.getDesignation());
			System.out.println("Contact Number of employee : " + emp.getContactNumber());
			System.out.println("EmailId of employee : " + emp.getEmailId());
			System.out.println("Marital Status of employee : " + emp.getMaritalStatus());
			System.out.println("Gender of employee : " + emp.getGender());

		} catch (StreamReadException e) {
			e.printStackTrace();
		} catch (DatabindException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

Manipulating Nested Elements in XML

Let us enhance our XML file to add nested elements and loops and modify our code to deserialize the following updated structure.

<Employees>
  <name>
    <firtsname>John</firtsname>
    <middlename>Dave</middlename>
    <lastname>William</lastname>
  </name>
  <contactdetails>
    <deskNumber>00-428507</deskNumber>
    <mobileNumber>+917823561231</mobileNumber>
    <emergencyDetails>
      <emergency_no1>+91 1212898920</emergency_no1>
      <emergency_no2>+91 9997722123</emergency_no2>
      <emergency_no3>+91 8023881245</emergency_no3>
    </emergencyDetails>
  </contactdetails>
  <age>30</age>
  <salary>75000.0</salary>
  <designation>Manager</designation>
  <emailId>abc@test.com</emailId>
  <gender>female</gender>
  <maritalStatus>married</maritalStatus>
</Employees>

There will be a slight change for the method deserializeFromXML() for the nested XML Structure.

   @Test
	public void deserializeFromXML() {

		XmlMapper xmlMapper = new XmlMapper();

		String userDir = System.getProperty("user.dir");

		// Converting Employee XML to Employee class object
		try {
			Employees employee2 = xmlMapper
					.readValue(new File(userDir + "\\src\\test\\resources\\NestedXMLExample.xml"), Employees.class);
			System.out.println("Deserialized data: ");
			System.out.println("First Name of employee : " + employee2.getName().getFirtsname());
			System.out.println("Middle Name of employee : " + employee2.getName().getMiddlename());
			System.out.println("Last Name of employee : " + employee2.getName().getLastname());
			System.out.println("Age of employee : " + employee2.getAge());
			System.out.println("Salary of employee : " + employee2.getSalary());
			System.out.println("Designation of employee : " + employee2.getDesignation());
			System.out.println("Desk Number of employee : " + employee2.getContactdetails().getDeskNumber());
			System.out.println("Mobile Number of employee : " + employee2.getContactdetails().getMobileNumber());
			System.out.println("Emergency Number1 of employee : "
					+ employee2.getContactdetails().getEmergencyDetails().getEmergency_no1());
			System.out.println("Emergency Number2 of employee : "
					+ employee2.getContactdetails().getEmergencyDetails().getEmergency_no2());
			System.out.println("Emergency Number3 of employee : "
					+ employee2.getContactdetails().getEmergencyDetails().getEmergency_no3());
			System.out.println("EmailId of employee : " + employee2.getEmailId());
			System.out.println("Gender of employee : " + employee2.getGender());
			System.out.println("Marital Status of employee : " + employee2.getMaritalStatus());

		} catch (StreamReadException e) {
			e.printStackTrace();
		} catch (DatabindException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

Here, you can see that when we need to serialize the nested attributes like Firstname, we have called the first Name class and then getFirstName().

System.out.println("First Name of employee : " + employee2.getName().getFirtsname());

To know about Serialization – Conversion of Java Objects to XML, you can refer to this tutorial.

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

Serialization – How to convert Java Objects to XML using Jackson API

HOME

The previous tutorials have explained the conversion of Java Objects to JSON payload and vice versa, i.e. conversion of JSON payload to Java Objects using Jackson API.

This tutorial explains parsing the XML document to Java objects using Jackson API.

To parse the above XML, we will use the Jackson library. Use the latest Jackson library.

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.13.0</version>
</dependency>

We are going to parse the following XML.

<Employee>
  <firstName>Vibha</firstName>
  <lastName>Singh</lastName>
  <age>30</age>
  <salary>75000.0</salary>
  <designation>Manager</designation>
  <contactNumber>+919999988822</contactNumber>
  <emailId>abc@test.com</emailId>
  <gender>female</gender>
  <maritalStatus>married</maritalStatus>
</Employee>

We will create an XML from POJO and vice versa now, which is generally called serialization and deserialization using Jackson APIs.

XmlMapper is a subclass of ObjectMapper which is used in JSON serialization. However, it adds some XML-specific tweaks to the parent class.

XmlMapper xmlMapper = new XmlMapper();

We can now look at how to use it to do the actual serialization. Let’s create a Java class first:

Below is the sample code of the Employee table, which contains the data members needed for Employee XML and their corresponding getter and setter methods.

public class Employee {

	// Data members of POJO class
	private String firstName;
	private String lastName;
	private int age;
	private double salary;
	private String designation;
	private String contactNumber;
	private String emailId;
	private String gender;
	private String maritalStatus;

	// Getter and setter methods
	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 int getAge() {
		return age;
	}

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

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public String getDesignation() {
		return designation;
	}

	public void setDesignation(String designation) {
		this.designation = designation;
	}

	public String getContactNumber() {
		return contactNumber;
	}

	public void setContactNumber(String contactNumber) {
		this.contactNumber = contactNumber;
	}

	public String getEmailId() {
		return emailId;
	}

	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public String getMaritalStatus() {
		return maritalStatus;
	}

	public void setMaritalStatus(String maritalStatus) {
		this.maritalStatus = maritalStatus;
	}

}

Writing XML is done using the various writeValue() methods that Jackson exposes.

  public class EmployeeXMLTest {

	@Test
	public void serializationTest() {

		// Create an object of POJO class
		Employee employee = new Employee();
	
		employee.setFirstName("Vibha");
		employee.setLastName("Singh");
		employee.setAge(30);
		employee.setSalary(75000);
		employee.setDesignation("Manager");
		employee.setContactNumber("+919999988822");
		employee.setEmailId("abc@test.com");
		employee.setMaritalStatus("married");
		employee.setGender("female");

		// Converting a Java class object to XML
		XmlMapper xmlMapper = new XmlMapper();

		try {
			String employeeXml = xmlMapper.writerWithDefaultPrettyPrinter().writeValueAsString(employee);
			System.out.println(employeeXml);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}

	}
}

Output

Nested Elements in XML

Let us create a complex XML now as shown below.

<Employees>
  <name>
    <firtsname>John</firtsname>
    <middlename>Dave</middlename>
    <lastname>William</lastname>
  </name>
  <contactdetails>
    <deskNumber>00-428507</deskNumber>
    <mobileNumber>+917823561231</mobileNumber>
    <emergencyDetails>
      <emergency_no1>+91 1212898920</emergency_no1>
      <emergency_no2>+91 9997722123</emergency_no2>
      <emergency_no3>+91 8023881245</emergency_no3>
    </emergencyDetails>
  </contactdetails>
  <age>30</age>
  <salary>75000.0</salary>
  <designation>Manager</designation>
  <emailId>abc@test.com</emailId>
  <gender>female</gender>
  <maritalStatus>married</maritalStatus>
</Employees>

Here, In this new structure, we have introduced a nested name element as well as contactdetails element which is further nested to emergencyDetails elements. With our current code, we cannot extract or create the new nested section. So, along with creating a POJO class for Employees, will create a POJO class for name, contactDetails, and emergencyDetails.

Employees

public class Employees {

	Name name;
	ContactDetails contactdetails;

	private int age;
	private double salary;
	private String designation;
	private String emailId;
	private String gender;
	private String maritalStatus;

	// Getter and setter methods
	public Name getName() {
		return name;
	}

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

	public ContactDetails getContactdetails() {
		return contactdetails;
	}

	public void setContactdetails(ContactDetails contactdetails) {
		this.contactdetails = contactdetails;
	}

	public int getAge() {
		return age;
	}

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

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public String getDesignation() {
		return designation;
	}

	public void setDesignation(String designation) {
		this.designation = designation;
	}

	public String getEmailId() {
		return emailId;
	}

	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public String getMaritalStatus() {
		return maritalStatus;
	}

	public void setMaritalStatus(String maritalStatus) {
		this.maritalStatus = maritalStatus;
	}

}

Name

public class Name {

	private String firtsname;
	private String middlename;
	private String lastname;

	public String getFirtsname() {
		return firtsname;
	}

	public void setFirtsname(String firtsname) {
		this.firtsname = firtsname;
	}

	public String getMiddlename() {
		return middlename;
	}

	public void setMiddlename(String middlename) {
		this.middlename = middlename;
	}

	public String getLastname() {
		return lastname;
	}

	public void setLastname(String lastname) {
		this.lastname = lastname;
	}

}

ContactDetails -As you can see that EmergencyDetails element which contains emergency_no1, emergency_no2, and emergency_no3 are nested within ContactDetails, so we have created a separate POJO class for EmergencyDetails.

public class ContactDetails {

	private String deskNumber;
	private String mobileNumber;

	EmergencyDetails emergencyDetails;

	public EmergencyDetails getEmergencyDetails() {
		return emergencyDetails;
	}

	public void setEmergencyDetails(EmergencyDetails emergencyDetails) {
		this.emergencyDetails = emergencyDetails;
	}

	public String getDeskNumber() {
		return deskNumber;
	}

	public void setDeskNumber(String deskNumber) {
		this.deskNumber = deskNumber;
	}

	public String getMobileNumber() {
		return mobileNumber;
	}

	public void setMobileNumber(String mobileNumber) {
		this.mobileNumber = mobileNumber;
	}

}

EmergencyDetails

public class EmergencyDetails {

	private String emergency_no1;
	private String emergency_no2;
	private String emergency_no3;

	public String getEmergency_no1() {
		return emergency_no1;
	}

	public void setEmergency_no1(String emergency_no1) {
		this.emergency_no1 = emergency_no1;
	}

	public String getEmergency_no2() {
		return emergency_no2;
	}

	public void setEmergency_no2(String emergency_no2) {
		this.emergency_no2 = emergency_no2;
	}

	public String getEmergency_no3() {
		return emergency_no3;
	}

	public void setEmergency_no3(String emergency_no3) {
		this.emergency_no3 = emergency_no3;
	}

}

Next, we create our serializeToXML() method:

public class XmlSerializationDemo {

	@Test
	public void serializationXML() throws JsonProcessingException {

		Employees employee = new Employees();

		Name empname = new Name();
		empname.setFirtsname("John");
		empname.setMiddlename("Dave");
		empname.setLastname("William");

		employee.setName(empname);
		employee.setAge(30);
		employee.setSalary(75000);
		employee.setDesignation("Manager");

		ContactDetails contdetails = new ContactDetails();
		contdetails.setDeskNumber("00-428507");
		contdetails.setMobileNumber("+917823561231");

		EmergencyDetails emergency = new EmergencyDetails();
		emergency.setEmergency_no1("+91 1212898920");
		emergency.setEmergency_no2("+91 9997722123");
		emergency.setEmergency_no3("+91 8023881245");
		contdetails.setEmergencyDetails(emergency);

		employee.setContactdetails(contdetails);

		employee.setEmailId("abc@test.com");
		employee.setMaritalStatus("married");
		employee.setGender("female");

		XmlMapper xmlMapper = new XmlMapper();

		try {
			String employeeXml = xmlMapper.writerWithDefaultPrettyPrinter().writeValueAsString(employee);
			System.out.println(employeeXml);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}

      //To save the XML in a file and place under the project
		String userDir = System.getProperty("user.dir");
		try {
			xmlMapper.writerWithDefaultPrettyPrinter()
					.writeValue(new File(userDir + "\\src\\test\\resources\\NestedXMLExample.xml"), employee);
		} catch (StreamWriteException e) {
			e.printStackTrace();
		} catch (DatabindException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

Output

The file is saved under src/test/resources as NestedXMLExample.

There is another way to do the same job of converting Java Object to a complex XML, but which looks more sophisticated and less a number of lines of code.

I’ll use the same complex XML structure.

In this method, we will create a default constructor as well as a parametrized Constructor to pass the arguments for each POJO Class.

Employee

public class Employees {

	Name name;
	ContactDetails contactdetails;

	private int age;
	private double salary;
	private String designation;
	private String emailId;
	private String gender;
	private String maritalStatus;

	public Employees() {
		super();
	}

	public Employees(Name name, ContactDetails contactdetails, int age, double salary, String designation,
			String emailId, String gender, String maritalStatus) {

		this.name = name;
		this.contactdetails = contactdetails;
		this.age = age;
		this.salary = salary;
		this.designation = designation;
		this.emailId = emailId;
		this.gender = gender;
		this.maritalStatus = maritalStatus;
	}

	// Getter and setter methods
	public Name getName() {
		return name;
	}

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

	public ContactDetails getContactdetails() {
		return contactdetails;
	}

	public void setContactdetails(ContactDetails contactdetails) {
		this.contactdetails = contactdetails;
	}

	public int getAge() {
		return age;
	}

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

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public String getDesignation() {
		return designation;
	}

	public void setDesignation(String designation) {
		this.designation = designation;
	}

	public String getEmailId() {
		return emailId;
	}

	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public String getMaritalStatus() {
		return maritalStatus;
	}

	public void setMaritalStatus(String maritalStatus) {
		this.maritalStatus = maritalStatus;
	}

}

Name

public class Name {

	private String firtsname;
	private String middlename;
	private String lastname;

	public Name() {
		super();
	}

	public Name(String firtsname, String middlename, String lastname) {
		super();
		this.firtsname = firtsname;
		this.middlename = middlename;
		this.lastname = lastname;
	}

	public String getFirtsname() {
		return firtsname;
	}

	public void setFirtsname(String firtsname) {
		this.firtsname = firtsname;
	}

	public String getMiddlename() {
		return middlename;
	}

	public void setMiddlename(String middlename) {
		this.middlename = middlename;
	}

	public String getLastname() {
		return lastname;
	}

	public void setLastname(String lastname) {
		this.lastname = lastname;
	}
}

ContactDetails

public class ContactDetails {

	private String deskNumber;
	private String mobileNumber;
	EmergencyDetails emergencyDetails;

	public ContactDetails() {
		super();
	}

	public ContactDetails(String deskNumber, String mobileNumber, EmergencyDetails emergencyDetails) {
		super();
		this.deskNumber = deskNumber;
		this.mobileNumber = mobileNumber;
		this.emergencyDetails = emergencyDetails;
	}

	public EmergencyDetails getEmergencyDetails() {
		return emergencyDetails;
	}

	public void setEmergencyDetails(EmergencyDetails emergencyDetails) {
		this.emergencyDetails = emergencyDetails;
	}

	public String getDeskNumber() {
		return deskNumber;
	}

	public void setDeskNumber(String deskNumber) {
		this.deskNumber = deskNumber;
	}

	public String getMobileNumber() {
		return mobileNumber;
	}

	public void setMobileNumber(String mobileNumber) {
		this.mobileNumber = mobileNumber;
	}
}

EmergencyDetails

public class EmergencyDetails {

	private String emergency_no1;
	private String emergency_no2;
	private String emergency_no3;

	public EmergencyDetails() {
		super();
	}

	public EmergencyDetails(String emergency_no1, String emergency_no2, String emergency_no3) {
		super();
		this.emergency_no1 = emergency_no1;
		this.emergency_no2 = emergency_no2;
		this.emergency_no3 = emergency_no3;
	}

	public String getEmergency_no1() {
		return emergency_no1;
	}

	public void setEmergency_no1(String emergency_no1) {
		this.emergency_no1 = emergency_no1;
	}

	public String getEmergency_no2() {
		return emergency_no2;
	}

	public void setEmergency_no2(String emergency_no2) {
		this.emergency_no2 = emergency_no2;
	}

	public String getEmergency_no3() {
		return emergency_no3;
	}

	public void setEmergency_no3(String emergency_no3) {
		this.emergency_no3 = emergency_no3;
	}
}

Now, let us create a Serialization Test

public class XmlSerializationDemo2 {

	@Test
	public void serializationTest() {

		try {

			EmergencyDetails emergency = new EmergencyDetails("+91 894132345", "+91 8888221102", "+91 7223156288");
			ContactDetails contdetails = new ContactDetails("00-428507", "+917823561231", emergency);
			Name empname = new Name("Trina", "Sophia", "William");

			// Converting a Java class object to a XML
			XmlMapper xmlMapper = new XmlMapper();

			String xmlString = xmlMapper.writerWithDefaultPrettyPrinter().writeValueAsString(new Employees(empname,
					contdetails, 35, 100000.00, "Director", "trina@test.com", "female", "married"));
			System.out.println(xmlString);

			// write XML string to file
			String userDir = System.getProperty("user.dir");
			File xmlOutput = new File(userDir + "\\src\\test\\resources\\XMLExample.xml");
			FileWriter fileWriter = new FileWriter(xmlOutput);
			fileWriter.write(xmlString);
			fileWriter.close();

		} catch (

		JsonProcessingException e) {

		} catch (IOException e) {

		}
	}
}

Output

The newly created XML file is saved under src/test/resources as shown in the below image.

We have successfully serialized our Java object into XML and written it into an XML file.

In our serializationTest() function, we create an XmlMapper object, which is a child class to the ObjectMapper class used in JSON serialization. This class converts our Java Object into an XML output that we can now write to a file.

Hope it is useful. Happy Learning !!