The JAXB Binding Process Explained
Today in the developer community, no one can dispute the importance of XML. It has become the backbone of many cutting edge technologies. XML is the core layer for data transport, communication, and configuration management. Most software projects are incomplete without the use of XML. It is a standard language when dealing with data. It allows developers to set standards in defining the information that should appear in a document, and in what sequence. Recently, many advanced technologies/protocols that were built used the simplified format of XML to capture and share information among applications. While this article is not about XML, it will highlight its importance with respect to JAXB (a Java library for communicating XMLs).
There are many way to convert data from XML to object and vise-versa. I am elaborating on one of these ways which is simple, light, and easy to learn and develop. So here we go…
JAXB stands for Java Architecture for XML Binding. It provides a mechanism to marshal Java objects into XML and un-marshal XML into objects. Simply, we can say JAXB provides an API to convert objects into XML and XML into objects.
JAXB 2.0 includes several important improvements to JAXB 1.0:-
- Support for all W3C XML Schema features. (JAXB 1.0 did not specify bindings for some of the W3C XML Schema features.)
- Support for binding Java-to-XML, with the addition of the javax.xml.bind.annotation package to control this binding. (JAXB 1.0 specified the mapping of XML Schema-to-Java, but not Java-to-XML Schema.)
- A significant reduction in the number of generated schema-derived classes.
- Additional validation capabilities through the JAXP 1.3 validation APIs.
- Smaller runtime libraries.
A JAXB implementation consists of the following architectural components:
- Schema compiler: Binds a source schema to a set of schema-derived program elements. The binding is described by an XML-based binding language.
- Schema generator: Maps a set of existing program elements to a derived schema. The mapping is described by program annotations.
- Binding runtime framework: Provides unmarshalling (reading) and marshalling (writing) operations for accessing, manipulating, and validating XML content using either schema-derived or existing program elements.
The JAXB Binding Process
The following figure shows what occurs during the JAXB binding process.
Figure: Steps in the JAXB Binding Process
Common steps in the JAXB data binding process:
- Generate classes: An XML schema is used as input to the JAXB binding compiler to generate JAXB classes based on that schema.
- Compile classes: All of the generated classes, source files, and application code must be compiled.
- Unmarshal: XML documents written according to the constraints in the source schema are unmarshalled by the JAXB binding framework. Note that JAXB also supports unmarshalling XML data from sources other than files and documents, such as DOM nodes, string buffers, SAX sources, and so forth.
- Generate content tree: The unmarshalling process generates a content tree of data objects instantiated from the generated JAXB classes; this content tree represents the structure and content of the source XML documents.
- Validate (optional): The unmarshalling process involves validation of the source XML documents before generating the content tree. Note that if you modify the content tree in Step 6, you can also use the JAXB Validate operation to validate the changes before marshalling the content back to an XML document.
- Process content: The client application can modify the XML data represented by the Java content tree by using interfaces generated by the binding compiler.
- Marshal: The processed content tree is marshalled out to one or more XML output documents. The content may be validated before marshalling
I have used jaxb-api-2.2.jar for all examples.
Example 1: Object to XML (Marshalling)
The following example shows the usage of java.xml.bind.JAXBElement class. To proceed, consider the following Employee class which will be used to have objects for marshalling and unmarshalling purposes:
import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name="Employee") publicclass Employee{ String name; intage; intid; public String getName(){ returnname; } @XmlElement(name="name") publicvoid setName(String name){ this.name = name; } publicint getAge(){ returnage; } @XmlElement(name = "age") publicvoid setAge(int age){ this.age = age; } publicint getId(){ returnid; } @XmlAttribute(name="id") publicvoid setId(int id){ this.id = id; } }
o @XmlRootElement: specifies the root element for the xml document.
o @XmlAttribute: specifies the attribute for the root element.
o @XmlElement: specifies the sub element for the root element.
Now we will create the main class which will be used to marshal, i.e. Convert Employee object to XML. Here we will create a JAXBElement of an Employee object and then update StringWriter object using JAXBContext. This example marshals the Employee object and prints the XML.
import java.io.StringWriter; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.namespace.QName; public class JAXBElementDemo { public static void main(String[] args) { //Create an employee object Employee employee = new Employee(); //fill details of the employee employee.setName("Prabhat"); employee.setId(1); employee.setAge(12); try { //create JAXBElement of type Employee //Pass it the employee object JAXBElement<Employee> jaxbElement = new JAXBElement( new QName(Employee.class.getSimpleName()),Employee.class, employee); //Create a String writer object which will be //used to write jaxbElment XML to string StringWriter writer = new StringWriter(); // create JAXBContext which will be used to update writer JAXBContext context = JAXBContext.newInstance(Employee.class); // marshall or convert jaxbElement containing employee to xml format context.createMarshaller().marshal(jaxbElement, writer /*new FileOutputStream("employee.xml")*/); //print XML string representation of Employee object System.out.println( writer.toString() ); } catch (JAXBException e) { e.printStackTrace(); } } }
- JAXBContext: class provides the client’s entry point to the JAXB API.
- JAXBElement: class is the JAXB representation of an Xml Element
Compile and run the above program. This will produce the following result:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Employee id="1"> <age>12</age> <name>Prabhat</name> </Employee>
Example 2: XML to Object (Un-marshaling)
import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name="Employee") publicclass Employee{ String name; intage; intid; public String getName(){ returnname; } @XmlElement(name="name") publicvoid setName(String name){ this.name = name; } publicint getAge(){ returnage; } @XmlElement(name = "age") publicvoid setAge(int age){ this.age = age; } publicint getId(){ returnid; } @XmlAttribute(name="id") publicvoid setId(int id){ this.id = id; } } import java.io.File; import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; publicclass EmployeeMain { publicstaticvoid main(String[] args) { try { JAXBContext context = JAXBContext.newInstance(Employee.class); Unmarshaller unmarshaller = context.createUnmarshaller(); /* * 1-way StringBuffer buffer = new StringBuffer("<?xml version='1.0' encoding='UTF-8' standalone='yes'?><Employee id='1'><age>12</age><name>Prabhat</name></Employee>"); Employee e = (Employee)unmarshaller.unmarshal(new StreamSource(new StringReader(buffer.toString()))); */ /* * 2-way * */ Employee e = (Employee)unmarshaller.unmarshal(new File("employee.xml")); System.out.println(e.getName()); System.out.println(e.getId()); System.out.println(e.getAge()); } catch (Exception e) { e.printStackTrace(); } } } employee.xml <?xml version='1.0' encoding='UTF-8' standalone='yes'?> <Employee id='1'> <age>12</age> <name>Prabhat</name> </Employee>
Output
Prabhat
1
12
Example 3: One to Many Relationship
Store.java 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(name="Store") @XmlType(propOrder={"name","books"}) publicclass Store { private String name; private ArrayList<Book> books; public String getName() { return name; } publicvoid setName(String name) { this.name = name; } @XmlElement(name = "Book") @XmlElementWrapper(name="booklist") public ArrayList<Book> getBooks() { returnbooks; } publicvoid setBooks(ArrayList<Book> books) { this.books = books; } } Book.java import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlRootElement(name="Book", namespace="default") @XmlType(propOrder={"name","author"}) public class Book { private String name; private String author; private int id; @XmlElement public void setName(String name) { this.name = name; } public String getName() { return name; } @XmlElement public void setAuthor(String author) { this.author = author; } public String getAuthor() { return author; } @XmlAttribute public void setId(int id){ this.id = id; } public int getId(){ return id; } } import java.util.ArrayList; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; public class StoresBookDemo { public static void main(String[] args) { Store store = new Store(); store.setName("Saraswati Book Store"); Book java = new Book(); java.setName("JAVA"); java.setAuthor("Kethi Sera"); java.setId(1); Book c = new Book(); c.setName("C++"); c.setAuthor("Bala Gurushwami"); c.setId(1); ArrayList<Book> books =new ArrayList<Book>(); books.add(java); books.add(c); store.setBooks(books); try { /*// One way // create JAXBElement of type Student //Pass it the student object JAXBElement<Student> jaxbElement = new JAXBElement( new QName(Student.class.getSimpleName()), Student.class, student); //Create a String writer object which will be //used to write jaxbElment XML to string StringWriter writer = new StringWriter(); // create JAXBContext which will be used to update writer JAXBContext context = JAXBContext.newInstance(Student.class); // marshall or convert jaxbElement containing student to xml format context.createMarshaller().marshal(jaxbElement, writer); //print XML string representation of Student object System.out.println( writer.toString() ); */ // 2nd way JAXBContext context = JAXBContext.newInstance(Store.class); Marshaller marshel = context.createMarshaller(); marshel.marshal(store, System.out); } catch (JAXBException e) { e.printStackTrace(); } } }
Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Store xmlns:ns2="default"> <name>Saraswati Book Store</name> <booklist> <Book id="1"> <name>JAVA</name> <author>Kethi Sera</author> </Book> <Book id="1"> <name>C++</name> <author>Bala Gurushwami</author> </Book> </Store>
Stay in Touch
Keep your competitive edge – subscribe to our newsletter for updates on emerging software engineering, data and AI, and cloud technology trends.
Thank you for submitting the form