Lately, I have been working on a few interesting problems that I wanted to talk about. So I started studying more of JAXB
APIs and the whole rabbit hole is huge. There are a lot of things that I can focus on these APIs. In this post, I will show how to use JAXB APIs for XML processing.
What’s JAXB and how to use APIs for XML Processing?
First, let me talk about JAXB APIs. So XML has been a language for data exchange for some time now. Java and XML came up with a partner to help developers a standard to facilitate between applications, web services, organizations using a similar technology stack. So all developers came together and they built a standard API for Java Architecture for XML Binding (JAXB). I will not describe any other detail about these API in this post, but you can check out this official documentation JAXB. JAXB APIs help to convert XML documents into Java Object and vice versa.
Scenario 1
In this scenario, how do bind a schema to Java object?
JAXB
basically simplifies the access of the XML document in Java program. So as part of this, we bind schema for XML document into a set of Java classes.
To demonstrate this example, I am showing a sample XML books.xml
as below:
<bookstore>
<book category="cooking">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="children">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="web">
<title lang="en">XQuery Kick Start</title>
<author>James McGovern</author>
<author>Per Bothner</author>
<author>Kurt Cagle</author>
<author>James Linn</author>
<author>Vaidyanathan Nagarajan</author>
<year>2003</year>
<price>49.99</price>
</book>
<book category="web" cover="paperback">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
To convert this XML into Java object, we will follow the following process
- Create a
JAXBContext
Object - Create a
Unmarshaller
using JAXBContext
Object - Call
Unmarshal
method on Unmarshaller
- The result will be a Java object
package com.betterjavacode.jaxbexample;
import java.util.ArrayList;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlRootElement
@XmlType(propOrder = {"bookcategory"})
public class Bookstore
{
private String bookCategory;
private List books;
public Bookstore(){}
public String getBookCategory()
{
return this.bookCategory
}
public void setBookCategory(String bookCategory)
{
this.bookCategory = bookCategory;
}
public List getBooks()
{
return this.books;
}
public void setBooks(List books)
{
this.books = books;
}
}
package com.betterjavacode.jaxbexample;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(namespace = "com.betterjavacode.jaxbexample.Bookstore")
public class Book
{
private String title;
private String author;
private int year;
private long price;
public Book()
{
}
public Book(String title, String author, int year, long price)
{
this.title = title;
this.author = author;
this.year = year;
this.price = price;
}
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getAuthor()
{
return author;
}
public void setAuthor(String author)
{
this.author = author;
}
public int getYear()
{
return year;
}
public void setYear(int year)
{
this.year = year;
}
public long getPrice()
{
return price;
}
public void setPrice(long price)
{
this.price = price;
}
}
Using annotations and base classes, we can convert xml into java object easily. That process as described will look like below in program:
package com.betterjavacode.jaxbexample;
import java.io.File;
import java.util.ArrayList;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
public class JAXBXMLToJava
{
public static final Logger LOGGER = LogFactory.getLogger(JAXBXMLToJava.class);
public static void main(String[] args)
{
try
{
JAXBContext jaxbContext = JAXBContext.newInstance(Bookstore.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
File xmlFile = new File("C:\\temp\\books.xml");
Bookstore bookStore = (Bookstore) unmarshaller.unmarshal(xmlFile);
ArrayList books = bookStore.getBooks();
for(Book book:books)
{
System.out.println("Book: " + book.getTitle());
}
}
catch(JAXBException e)
{
LOGGER.debug("unable to unmarshal", e);
}
}
}
So in this scenario, we took an xml and converted that into a java object.
Scenario 2
In this scenario, I will show one of the features of JAXB APIs.
How to change the namespace prefixes?
By default when you marshal Java object to XML, JAXB Marshaller uses default namespace prefixes like ns1
, ns2
, ns3
etc. While this can be perfectly valid XML for readability purposes, you might run into an issue like signature validation if Signature validation API was expecting different namespaces.
In such cases, JAXB offers a NamespacePrefixMapper which allows you to change your namespace prefixes.
Advantages of JAXB
- JAXB offers different ways to handle the large size of XML
- Dealing with XML data can be complex, but in Java world, it is easier to deal with objects. JAXB makes that easy.
- JAXB allows you to access data in non-sequential order, but unlike DOM-based processing, it doesn’t force you to navigate through a tree to access the data.
- And JAXB is flexible
Conclusion
Previously, I had shown how to consume a SOAP webservice using JAXB marshaller. In this post, I have given a brief introduction to JAXB APIs and how to use them for XML processing. There are a lot of other features that JAXB APIs offer.
References
- JAXB User guide – user guide
- Java Architecture for XML Binding – JAXB