JAXB – Java API for XML Binding

I am going to show you how to generate JAXB classes from XSD file using maven build tool. I am going to use JAXB-2 Maven Plugin to generate the Java classes from XSD file. Finally I am also going to show you how unmarshal XML file using JAXB 2 API. This will ensure the validity of your XSD file.

Related Posts:

XML Binding

  • XML binding maps XML to objects
  • It generates Classes to represent XML elements. Classes follow JavaBean property access conventions.
  • Supports three principal operations. Marshalling – it marshalls a tree of objects into XML document. Unmarshalling – it unmarshalls an XMl document into a tree of objects. It also validates XML against the schema used to generate classes of objects. Validation of object trees against the schema used to generate classes.

XML Binding Relationship

Why use XML Bindings?

  • We do not need to write much code while we have to if we use SAX or DOM
  • We do not need to learn SAX or DOM parser
  • It is less error prone because we do not have to manually implement them and all features of schema are utilized
  • It allows us to customize the XML structure

JAXB Use Cases

  • It is used to create, read or modify XML using Java but without using SAX or DOM parser
  • Using rules defined in XML schema it can validate user input


Now I will show you step by step how you can use JAXB 2 API to marshall and unmarshall XML document easily.

Prerequisites

Java at least 8, Maven 3.6.3, JAXB-2 Maven Plugin

You can create maven based project in your favorite IDE or tool. The name of the project is java-jaxb-maven.

Use below pom.xml file for your maven project to generate Java class from XSD 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.roytuts</groupId>
	<artifactId>java-jaxb-maven</artifactId>
	<version>0.0.1-SNAPSHOT</version>

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

	<dependencies>
		<!--required only if jdk 9 or higher version is used -->
		<dependency>
			<groupId>com.sun.xml.bind</groupId>
			<artifactId>jaxb-core</artifactId>
			<version>2.3.0.1</version>
		</dependency>
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.1</version>
		</dependency>
		<dependency>
			<groupId>com.sun.xml.bind</groupId>
			<artifactId>jaxb-impl</artifactId>
			<version>2.3.1</version>
		</dependency>
		<dependency>
			<groupId>org.javassist</groupId>
			<artifactId>javassist</artifactId>
			<version>3.27.0-GA</version>
		</dependency>
	</dependencies>

	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.8.1</version>
				</plugin>
			</plugins>
		</pluginManagement>
		<plugins>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>jaxb2-maven-plugin</artifactId>
				<version>2.5.0</version>
				<executions>
					<execution>
						<id>xjc</id>
						<goals>
							<goal>xjc</goal>
						</goals>
					</execution>
				</executions>
				<configuration>
					<!-- The schema directory or xsd files. -->
					<sources>
						<source>
							${project.basedir}/src/main/resources/xsd
						</source>
					</sources>
					<!-- The package in which the java source files will be generated. -->
					<packageName>com.roytuts.jaxb</packageName>
					<!-- The working directory to create the generated java source files. -->
					<!-- <outputDirectory>${project.basedir}/src/main/java</outputDirectory> -->
					<!-- <cleanOutputDirectory>false</cleanOutputDirectory> -->
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

In the above pom.xml file, <sources><source></source></sources> tag is used to specify the XSD file location. The default location is src/main/xsd, so if you keep file under default location then you do not need to specify the source directory.

The default type of file read by JAXB-2 plugin is XSD. If you have any other file type then you need to specify the type also using the tag <sourceType>. For example, you can specify DTD file type using <sourceType>DTD</sourceType>.

The package name is where the generated Java classes will be generated.

The <outputDirectory></outputDirectory>, under which I want to generate the generated classes. If you do not specify then it will generate under target directory.

XSD File

I have put a sample XSD file (book.xsd) under src/main/resources/xsd folder. You can use the below sample XSD file.

<xs:schema attributeFormDefault="unqualified"
	elementFormDefault="qualified"
	xmlns:xs="http://www.w3.org/2001/XMLSchema">
	<xs:element name="Catalog">
		<xs:complexType>
			<xs:sequence>
				<xs:element name="Book" maxOccurs="unbounded"
					minOccurs="0">
					<xs:complexType>
						<xs:sequence>
							<xs:element type="xs:string" name="Author" />
							<xs:element type="xs:string" name="Title" />
							<xs:element type="xs:string" name="Genre" />
							<xs:element type="xs:float" name="Price" />
							<xs:element type="xs:date" name="PublishDate" />
							<xs:element type="xs:string" name="Description" />
						</xs:sequence>
						<xs:attribute type="xs:string" name="id"
							use="optional" />
					</xs:complexType>
				</xs:element>
			</xs:sequence>
		</xs:complexType>
	</xs:element>
</xs:schema>

Build Project

Now open command prompt and navigate to the project root directory. Execute the below command to build the project:

mvn compile install

If build is successful, you will see the below classes generated in the folder target/genrated-sources/jaxb under package com.roytuts.jaxb.

Catalog.java, ObjectFactory.java

Marshal/Unmarshal XML

Next step is, you need an XML document (book.xml) which validates against the above XSD. Below is the sample file. Put this XML file under src/main/resources/xml.

<?xml version="1.0"?>
<Catalog>
	<Book id="bk101">
		<Author>Garghentini, Davide</Author>
		<Title>XML Developer's Guide</Title>
		<Genre>Computer</Genre>
		<Price>44.95</Price>
		<PublishDate>2000-10-01</PublishDate>
		<Description>An in-depth look at creating applications
			with XML.
		</Description>
	</Book>
	<Book id="bk102">
		<Author>Garcia, Debra</Author>
		<Title>Midnight Rain</Title>
		<Genre>Fantasy</Genre>
		<Price>5.95</Price>
		<PublishDate>2000-12-16</PublishDate>
		<Description>A former architect battles corporate zombies,
			an evil
			sorceress, and her own childhood to become queen
			of the world.
		</Description>
	</Book>
</Catalog>

Now I will create a class with main method which will marshal or unmarshal the above XMl file.

package com.roytuts.marshal.unmarshal;

import java.io.File;
import java.util.Date;
import java.util.GregorianCalendar;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import com.roytuts.jaxb.Catalog;
import com.roytuts.jaxb.Catalog.Book;

public class MarshalUnmarshal {

	public static void main(String[] args) {
		unmarshal();
		marshal();
	}

	private static void unmarshal() {
		try {
			JAXBContext jaxbContext = JAXBContext.newInstance(Catalog.class);
			Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
			Catalog catalogs = (Catalog) unmarshaller.unmarshal(new File("src/main/resources/xml/book.xml"));

			for (Book book : catalogs.getBook()) {
				System.out.println(book.getId());
				System.out.println(book.getTitle());
				System.out.println(book.getAuthor());
				System.out.println(book.getDescription());
				System.out.println(book.getGenre());
				System.out.println(book.getPrice());
				System.out.println(book.getPublishDate());
			}
		} catch (JAXBException e) {
			e.printStackTrace();
		}
	}

	private static void marshal() {
		try {
			JAXBContext jaxbContext = JAXBContext.newInstance(Catalog.class);
			Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
			jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

			Book book1 = new Book();
			Book book2 = new Book();

			GregorianCalendar gcalendar = new GregorianCalendar();
			gcalendar.setTime(new Date());
			XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(gcalendar);

			book1.setId("1001");
			book1.setTitle("Title for Book One");
			book1.setAuthor("S Roy");
			book1.setDescription("Description of Book One");
			book1.setGenre("IT");
			book1.setPrice(450.0f);
			book1.setPublishDate(xmlDate);
			book2.setId("1002");
			book2.setTitle("Title for Book Two");
			book2.setAuthor("S Roy");
			book2.setDescription("Description of Book Two");
			book2.setGenre("CS");
			book2.setPrice(400.0f);
			book2.setPublishDate(xmlDate);

			Catalog catalog = new Catalog();
			catalog.getBook().add(book1);
			catalog.getBook().add(book2);

			// Marshal the books list in file
			jaxbMarshaller.marshal(catalog, new File("src/main/resources/xml/newbooks.xml"));
		} catch (JAXBException e) {
			e.printStackTrace();
		} catch (DatatypeConfigurationException e) {
			e.printStackTrace();
		}
	}

}

Run the above class and you will get output in the console as shown below.

bk101
XML Developer's Guide
Garghentini, Davide
An in-depth look at creating applications
			with XML.
		
Computer
44.95
2000-10-01
bk102
Midnight Rain
Garcia, Debra
A former architect battles corporate zombies,
			an evil
			sorceress, and her own childhood to become queen
			of the world.
		
Fantasy
5.95
2000-12-16

That’s all. Hope you got an idea how to generate Java classes from XSD using JAXB-2 API.

Source Code

Download

Thanks for reading.

Leave a Reply

Your email address will not be published. Required fields are marked *