JAXB Example : XML reading, writing in Java


Goal of this example

Java SE includes many XML parsing technologies like SAX, DOM and StaX providing API to directly manipulate XML. In contrast JAXB does not allow direct XML manipulation, instead it provides a way to transform Java objects to XML (called unmarshaling) and transform  XML to Java objects (called marshaling). Additionally it supports generating Java Objects from XSD files.

Technology Used
  • JAXB2
  • JAXB Maven integration
Techniques shown in this example
  • XML Marshalling
  • XML Unmarshalling
  • Java code generation from XSD using XJC
  • Schematic reuse using xs:import

Structure of the example project

This example contains two JUnit tests under /src/test/java/org/exampledriven/jaxb . These do the following :

  1. Read xml files from /src/main/resources and transform it to Java objects
  2. Modify Java objects
  3. Prints the modified XML generated from the updated objects
JAXB Overview

The basic principle in JAXB is that Java beans must be annotated with JAXP annotations. Here are the thee most common :

  • @XmlRootElement : this is the only mandatory, it needs to be added to the class
  • @XmlAttribute : indicates that the java field represents an XML attribute
  • @XmlTransient : indicates that the given java field should be excluded from the XML transformation

JAXB provides two options to create the annotated Java classes : create them manually or generate from XSD

Creating JAXB annotated classes manually

In this example Book.java was created manually. It is a POJO with JAXB annotations. TestNormalClasses.java will test marshaling and unmarshaling it.

package org.exampledriven.jaxb;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

@XmlRootElement
public class Book {

	private String author;
	private String title;
	private String secret;

	public String getAuthor() {
		return author;
	}
	public void setAuthor(String author) {
		this.author = author;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}

	public String getSecret() {
		return secret;
	}
	@XmlTransient
	public void setSecret(String secret) {
		this.secret = secret;
	}

}

Generating JAXB annotated classes
Consider the scenario when there are existing XML files or an XML based web-service that needs to be used from Java. One option would be to manually create the matching Java Classes, the other option is to generate them. Luckily JDK contains a command line tool called XJC that can generate JAXB annotated classes from, XSD (XML Schema Definition) files. If we consider the above example where only the XML is known not the XSD then we will need an extra step :

Generating XSD from XML

There are many online tools that can generate XSD from XML, for example http://www.xmlforasp.net/codebank/system_xml_schema/buildschema/buildxmlschema.aspx . The problem with these is that they don’t provide enough options. A more sophisticated solution is the inst2xsd tool that is freely downloadable as part of the XMLBeans project. The documentation of inst2xsd is here http://xmlbeans.apache.org/docs/2.0.0/guide/tools.html#inst2xsd

The benefit of inst2xsd is that it it supports three different styles through the -design parameter . In the /src/main/resources folder of the example project there are XML and generated XSD examples. It worth trying each style and see what Java Code is generated from the XSD. This example used the “salami slice” style.

Generating Java Objects from XSD

Once the XSD is ready XJC can be called executed. In case of a Maven project it is more convenient to use org.jvnet.jaxb2.maven2 the maven plugin, the example project’s pom file contains it. Once it is added

mvn schema-generate

will generate the Java Classes (and mvn install too)

Customizing the generated Java Classes

The first thing we should customize is the package. XJC has an option to specify it, see the -p option here : http://docs.oracle.com/javase/6/docs/technotes/tools/share/xjc.html

this works fine as long as we want everything to be generated into the same package, but this is not always the case.

Schematic reuse using xs:import

Consider the following two XML (they are in /src/main/resources)
request.xml



    
        
            a@test.com
            a@work.com
            Peter
            Szanto
        
    

response.xml



    
        
            a@test.com
            a@work.com
            Peter
            Szanto
        
    

The <ct:contacts> element is the same, but the root element is different. If we would generate XSD then Java from these then we would get two different Java Class for contacts, even though one would be enough. The solution is called schematic reuse and it means that the common parts of the XSD files can be included into other XSD files using the <xs:include> element.

request.xsd





	

	
		
			
				
			
		
	


response.xsd





	

	
		
			
				
			
		
	


contact.xsd




	
  
    
      
        
          
        
      
    
  

  
	

	

	
		
			
				
				
				
			
		
	
	
	
		
			
				
			
		
	
	

Each XSD has it’s own namespace, and the package of the generated Java Classes will be derived from it, in the given example there will be three packages generated

xmlns=”http://contact.generated.jaxb.exampledriven.org&#8221;
package org.exampledriven.jaxb.generated.contact;

xmlns=”http://response.generated.jaxb.exampledriven.org&#8221;
package org.exampledriven.jaxb.generated.request;

xmlns=”http://response.generated.jaxb.exampledriven.org&#8221;
package org.exampledriven.jaxb.generated.response;

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: