JAXB – A XML Parsing technique

In this article, we will learn and implement JAXB (Java Architecture for XML Binding) which converts XML to Java objects and vice-versa i.e.; Java objects to XML on the fly. The specific terms used for the above conversion is

  • Un-marshalling (XML –> Java objects)
  • Marshalling (Java objects –> XML)

Previously, developers has to implement parsing techniques like SAX, DOM, etc to accomplish above task. But with the introduction of JAXB, developers task is one cut-off and they can allocate more time on business implementation

Nowadays, JAXB are most widely used in the implementation of Web Services as data exchanged here are in the form XML which needs to be converted into objects at the server end (and vice-versa)

Let us see few definitions and later we will implement a basic example to illustrate JAXB marshalling & un-marshalling

Technology Used

  • Java 1.7
  • Eclipse Luna IDE
  • Apache Maven 3.2.1

JAXB

  • JAXB stands for Java Architecture for XML Binding
  • It’s a JSR 222 specification see here
  • JAXB provides rich API to convert XML to Java objects & vice-versa
  • The main advantage of using JAXB API for reading/processing XML documents is that, we don’t need to aware of any parsing techniques. (unlike SAX, DOM)

1_JAXB_1

XML Schema (XSD)

  • XSD stands for XML Schema Definition
  • XSD describes the structure of XML document
  • Basically XSD describes the syntax/rules for XML document
  • XSD’s aren’t mandatory to have with respect to JAXB. But, if we have it will be useful for XML validation before marshalling/un-marshalling

Maven-zing JAXB

  • It is always preferred to mavenize your JEE or Java framework projects
  • It helps in resolving your dependencies & creates a deployable jar/war/ear
  • If you are using JDK 1.7, then there is no need to add any extra libraries as dependency in pom.xml as JAXB 2.0 comes shipped with JDK 7.0
  • But, with maven you can add your desired plugins/dependencies
  • Note: if you are using JDK version less than 6, then you can download jaxb-impl.jar and include library into project classpath
  • Or else,  you can add these dependencies in your pom.xml as below
<dependencies>
	<dependency>
		<groupId>com.sun.xml.bind</groupId>
		<artifactId>jaxb-impl</artifactId>
		<version>${jaxb.impl.version}</version>
	</dependency>
</dependencies>

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/maven-v4_0_0.xsd">

	<modelVersion>4.0.0</modelVersion>
	<groupId>in.bench.resources</groupId>
	<artifactId>JAXB</artifactId>
	<packaging>jar</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>JAXB Maven jar</name>
	<url>http://maven.apache.org</url>

	<properties>
		<jaxb.impl.version>2.2.7-b53</jaxb.impl.version>
		<compileSource>1.7</compileSource>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.target>1.7</maven.compiler.target>
		<maven.compiler.source>1.7</maven.compiler.source>
	</properties>

	<build>
		<finalName>JAXB</finalName>
		<plugins>
			<!-- plugin - maven compiler plugin -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
				</configuration>
			</plugin>

			<!-- plugin - maven jaxb goal - generate java objects from XSD -->
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>jaxb2-maven-plugin</artifactId>
				<version>1.5</version>
				<executions>
					<execution>
						<goals>
							<goal>xjc</goal>
						</goals>
						<configuration>
							<!-- <packageName>my.jaxb.data</packageName> -->
							<outputDirectory>${basedir}/generated/java/source</outputDirectory>
							<schemaDirectory>${basedir}/src/main/resources/entities</schemaDirectory>
							<schemaFiles>*.xsd</schemaFiles>
							<schemaLanguage>XMLSCHEMA</schemaLanguage>
							<extension>true</extension>
							<args>
								<arg>-XtoString</arg>
							</args>
							<plugins>
								<plugin>
									<groupId>org.jvnet.jaxb2_commons</groupId>
									<artifactId>jaxb2-basics</artifactId>
									<version>0.6.4</version>
								</plugin>
							</plugins>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>

	<!-- <dependencies>
		<dependency>
			<groupId>com.sun.xml.bind</groupId>
			<artifactId>jaxb-impl</artifactId>
			<version>${jaxb.impl.version}</version>
		</dependency>
	</dependencies> -->

</project>

 

Generating POJO’s from XSD using maven plugins

2_JAXB_2

 

JAXB – Generating java source files from XSD

Steps to generate java-sources from XML Schema Definition (XSD)

  • configure JAXB Maven plugin in pom.xml
  • write well-defined XSD for your service
  • use maven command “mvn generate-sources” to generate java source files

Note: Its not a mandate, well if one wish to write supporting POJOs with JAXB annotation. Also, be careful while designing XSD

Configure JAXB Maven plugin

<!-- plugin - maven jaxb goal - generate java objects from XSD -->
<plugin>
	<groupId>org.codehaus.mojo</groupId>
	<artifactId>jaxb2-maven-plugin</artifactId>
	<version>1.5</version>
	<executions>
		<execution>
			<goals>
				<goal>xjc</goal>
			</goals>
			<configuration>
				<!-- <packageName>my.jaxb.data</packageName> -->
				<outputDirectory>${basedir}/generated/java/source</outputDirectory>
				<schemaDirectory>${basedir}/src/main/resources/entities</schemaDirectory>
				<schemaFiles>*.xsd</schemaFiles>
				<schemaLanguage>XMLSCHEMA</schemaLanguage>
				<extension>true</extension>
				<args>
					<arg>-XtoString</arg>
				</args>
				<plugins>
					<plugin>
						<groupId>org.jvnet.jaxb2_commons</groupId>
						<artifactId>jaxb2-basics</artifactId>
						<version>0.6.4</version>
					</plugin>
				</plugins>
			</configuration>
		</execution>
	</executions>
</plugin>

Music.xsd

Below XSD contains two elements with name “Movies” and “Music”

  • Movies element has four attributes namely movieName, year, director, comments
  • Music elements has three attributes with two simple type & one complex type which refers above declared movies element using ref attribute
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	targetNamespace="http://benchresources.in/entities/music" xmlns:tns="http://benchresources.in/entities/music"
	elementFormDefault="qualified">

	<xsd:element name="music">
		<xsd:complexType>
			<xsd:sequence>
				<xsd:element name="composer" type="xsd:string" />
				<xsd:element name="languages" type="xsd:string" />
				<xsd:element ref="tns:movies" />
			</xsd:sequence>
		</xsd:complexType>
	</xsd:element>

	<xsd:element name="movies">
		<xsd:complexType>
			<xsd:sequence>
				<xsd:element name="movie" maxOccurs="unbounded">
					<xsd:complexType>
						<xsd:sequence>
							<xsd:element name="movieName" type="xsd:string" />
							<xsd:element name="year" type="xsd:string" />
							<xsd:element name="director" type="xsd:string" />
							<xsd:element name="comments" type="xsd:string" />
						</xsd:sequence>
					</xsd:complexType>
				</xsd:element>
			</xsd:sequence>
		</xsd:complexType>
	</xsd:element>
</xsd:schema>

Run mvn generate-sources

Look at the generated java source files in the generated folder and also view console statements while JAXB generating classes using source XSD

3_console_JAXB_for_generated_java_source_class

Music.java

package in.benchresources.entities.music;

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;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "composer",
    "languages",
    "movies"
})
@XmlRootElement(name = "music")
public class Music {

    @XmlElement(required = true)
    protected String composer;
    @XmlElement(required = true)
    protected String languages;
    @XmlElement(required = true)
    protected Movies movies;

    public String getComposer() {
        return composer;
    }

    public void setComposer(String value) {
        this.composer = value;
    }

    public String getLanguages() {
        return languages;
    }

    public void setLanguages(String value) {
        this.languages = value;
    }

    public Movies getMovies() {
        return movies;
    }

    public void setMovies(Movies value) {
        this.movies = value;
    }
}

Movies.java

package in.benchresources.entities.music;

import java.util.ArrayList;
import java.util.List;
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;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "movie"
})
@XmlRootElement(name = "movies")
public class Movies {

    @XmlElement(required = true)
    protected List&lt;Movies.Movie&gt; movie;

    public List&lt;Movies.Movie&gt; getMovie() {
        if (movie == null) {
            movie = new ArrayList&lt;Movies.Movie&gt;();
        }
        return this.movie;
    }

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "movieName",
        "year",
        "director",
        "comments"
    })
    public static class Movie {

        @XmlElement(required = true)
        protected String movieName;
        @XmlElement(required = true)
        protected String year;
        @XmlElement(required = true)
        protected String director;
        @XmlElement(required = true)
        protected String comments;

        public String getMovieName() {
            return movieName;
        }

        public void setMovieName(String value) {
            this.movieName = value;
        }

        public String getYear() {
            return year;
        }

        public void setYear(String value) {
            this.year = value;
        }

        public String getDirector() {
            return director;
        }

        public void setDirector(String value) {
            this.director = value;
        }

        public String getComments() {
            return comments;
        }

        public void setComments(String value) {
            this.comments = value;
        }
    }
}

Directory Structure

Before moving on, let us understand the directory/package structure once you create project in Eclipse IDE
Maven has to follow certain directory structure

  • src/test/java –> test related files, mostly JUnit test cases
  • src/main/java –> create java source files under this folder
  • src/main/resources –> all configuration files placed here
  • generated/java/source –> generated java source files are placed here
  • Maven Dependencies or Referenced Libraries –> includes jars in the classpath
  • WEB-INF under webapp –> stores web.xml & other configuration files related to web application

Project Structure (Package Explorer view in Eclipse)

4_JAXB_Project_Structure_In_Eclipse

Let’s see coding in action

 

Marshalling & Un-marshalling

5_MarshalUnmarshal

Un-marshalling: Converts XML documents to corresponding Java objects
Marshalling: Converts Java objects to XML

Un-marshalling program

This class generates Java objects from input file “Music.xml”. Also, sets XSD to validate the input XML before un-marshalling. There are other validation mechanism to do same like using javax.xml.validation.Validator class

Note: programs has some commented lines, which can be used as alternative approach to get values from input xml

JAXBUnMarshaller.java

package in.mycompany.entities.music;

import in.benchresources.entities.music.Movies;
import in.benchresources.entities.music.Movies.Movie;
import in.benchresources.entities.music.Music;

import java.io.File;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

public class JAXBUnMarshaller {

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

	public static void createJavaObject(){

		JAXBContext jaxbContext = null;
		Unmarshaller unmarshaller = null;
		File file = new File("src\\main\\resources\\sourcexml\\Music.xml");

		try{
			// validation
			SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
			Schema schema = schemaFactory.newSchema(new File("src\\main\\resources\\entities\\Music.xsd"));

			// create JAXB context
			jaxbContext = JAXBContext.newInstance(Music.class);//"in.mycompany.entities.music"

			// initializing unmarshaller
			unmarshaller = jaxbContext.createUnmarshaller();

			// validate here against XSD
			unmarshaller.setSchema(schema);

			// creates Java Objects from XML file
			/*JAXBElement<?> muzix = (JAXBElement<?>) unmarshaller.unmarshal(file);
			MusicType musicType = (MusicType) muzix.getValue();*/

			Music musicType = (Music) unmarshaller.unmarshal(file);

			System.out.println(" Composer :- " + musicType.getComposer());
			System.out.println(" Languages :- " + musicType.getLanguages());

			Movies movies = musicType.getMovies();

			for(Movie movie : movies.getMovie()){
				System.out.println(" \tMovie Name :- " + movie.getMovieName());
				System.out.println(" \tYear :- " + movie.getYear());
				System.out.println(" \tDirector :- " + movie.getDirector());
				System.out.println(" \tComments :- " + movie.getComments() + "\n");
			}
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}
		finally{
			// release resources, if any
		}
	}
}

Output in console

 Composer :- AR Rahman
 Languages :- English, Hindi, Tamil
 	Movie Name :- Roja
 	Year :- 1992
 	Director :- Mani Ratnam
 	Comments :- Indian National Award

 	Movie Name :- Alaipayuthey
 	Year :- 2000
 	Director :- Mani Ratnam
 	Comments :- Tamil Filmfare Award

 	Movie Name :- Slumdog Millionaire
 	Year :- 2008
 	Director :- Danny Boyle
 	Comments :- Oscar, Bafta, Grammy, Golden Globe Award

 	Movie Name :- Raanjhanaa
 	Year :- 2013
 	Director :- Anand Rai
 	Comments :- Topping musiz charts

Marshalling program

This class creates(generates/outputs) XML from Java objects defined in the class. With XSD set in the SchemaFactory, it checks for correctness and validates the XML before marshalling

Note: Some lines are commented out, which is an alternative approach

JAXBMarshaller.java

package in.mycompany.entities.music;

import in.benchresources.entities.music.Movies;
import in.benchresources.entities.music.Movies.Movie;
import in.benchresources.entities.music.Music;

import java.io.File;
import java.util.List;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

public class JAXBMarshaller {

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

	public static void createXML(){

		JAXBContext jaxbContext = null;
		Marshaller marshaller = null;

		try{

			// validation
			SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
			Schema schema = schemaFactory.newSchema(new File("src\\main\\resources\\entities\\Music.xsd"));

			jaxbContext = JAXBContext.newInstance(Music.class);
			marshaller = jaxbContext.createMarshaller();
			marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
			File file = new File("src\\main\\resources\\marshalledxml\\Music.xml");

			// validate here against XSD
			marshaller.setSchema(schema);

			marshaller.marshal(JAXBMarshaller.createJavaObject(), file);
			marshaller.marshal(JAXBMarshaller.createJavaObject(), System.out);

			// create an element for marshalling
			//JAXBElement<MusicType> element = (new ObjectFactory()).createMusic(createJavaObject());

			// create a Marshaller and marshal to System.out
			//JAXB.marshal(element, new FileOutputStream(new File("Muzix.xml")));

		}
		catch(Exception ex){
			ex.printStackTrace();
		}
		finally{
			// release resources, if any
		}
	}

	public static Music createJavaObject(){

		Movies movies = new Movies();
		List<Movies.Movie> mvLst = movies.getMovie();

		Movie movie1 = new Movie();
		movie1.setMovieName("Omkara");
		movie1.setYear("2006");
		movie1.setDirector("Vishal Bhardwaj");
		movie1.setComments("National Award - Special Jury");

		Movie movie2 = new Movie();
		movie2.setMovieName("Ishqiya");
		movie2.setYear("2010");
		movie2.setDirector("Vishal Bhardwaj");
		movie2.setComments("National Award");

		mvLst.add(movie1);
		mvLst.add(movie2);

		Music music = new Music();
		music.setComposer("Vishal Bhardwaj");
		music.setLanguages("Hindi");
		music.setMovies(movies);
		return music;
	}
}

Output in console

    Vishal Bhardwaj
    Hindi
            Omkara
            2006
            Vishal Bhardwaj
            National Award - Special Jury

            Ishqiya
            2010
            Vishal Bhardwaj
            National Award

Marshalled xml file (src\main\resources\marshalledxml\Musix.xml)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<music xmlns="http://benchresources.in/entities/music">
	<composer>Vishal Bhardwaj</composer>
	<languages>Hindi</languages>
	<movies>
		<movie>
			<movieName>Omkara</movieName>
			<year>2006</year>
			<director>Vishal Bhardwaj</director>
			<comments>National Award - Special Jury</comments>
		</movie>
		<movie>
			<movieName>Ishqiya</movieName>
			<year>2010</year>
			<director>Vishal Bhardwaj</director>
			<comments>National Award</comments>
		</movie>
	</movies>
</music>

Conclusion: SOAP web service approaches like Top-down & Bottom-up uses JAXB for conversion of XML to Java objects and vice-versa for their data exchange with external client

Download project

JAXB - A XML Parsing technique (19kB)

Happy Coding !!
Happy Learning !!