Introduction to JAXB starts with:
Java Architecture for XML Binding (JAXB) provides a fast and
convenient way to bind XML schemas
and Java representations, making it easy for Java developers to incorporate XML
data and processing functions in Java applications.
This blog is not going to touch on XML Schema part, I found JAXB to be excellent architecture for binding XML and Java objects. To compile and run the examples, you can use any version of JDK6 and above that includes JAXB2.X.
JAXB provides methods for
unmarshalling (reading) XML instance documents into Java content trees, and then
marshalling (writing) Java content trees back into XML instance documents.
In simple
words, JAXB offers you APIs for converting your Java objects trees to XML
document and vice versa through marshaling and unmarshalling processes.
In order to facilitate this conversion (for ex:
marshalling), we need to map our Java instances with corresponding XML
element. In simple words, we need to explain the JAXB that ‘productName’
attribute in my class has to be mapped with <productName> element,
similarly ‘quantity’ attribute will be mapped with <quantity> element in
XML document.
private String productName; // to be mapped with <productName>
private int quantity; // to be mapped with <quantity>
This mapping could be achieved by writing some JAXB
annotations in Java classes to indicate XML element name for each attribute.
For our case, the annotations would be:
@XmlElement(name = "productName")
private String productName;
private String productName;
@XmlElement(name = "quantity")
private int quantity;
private int quantity;
If your Java attribute name and XML element name is same (as
in above scenario), you don’t even need to specify this annotation, JAXB would
automatically create an XML Element with same name as that of attribute in Java
class. So we could simply write our attributes as below and let JAXB handle the
conversion (or marshaling).
private String productName;
private int quantity;
private int quantity;
Let’s create a simple class for which we will use JAXB to
marshal this instance for creating corresponding XML document.
Item.java
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Item {
public String
getProductName() {
return productName;
}
public void
setProductName(String productName) {
this.productName = productName;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
private String productName;
private int quantity;
}
JAXBMarshaler.java
import
javax.xml.bind.JAXBContext;
import
javax.xml.bind.Marshaller;
public class JAXBMarshaler {
public static void main(String[] args) throws Exception{
Item
item = new Item();
item.setProductName("Entrepreneur
- March 2013 edition");
item.setQuantity(1);
JAXBContext
jaxbContext = JAXBContext.newInstance(Item.class);
Marshaller
jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(item,
System.out);
}
}
Compiling above classes and running JaxmMarshaler produces below output:
Output
<?xml version="1.0"
encoding="UTF-8" standalone="yes"?>
<item>
<productName>Entrepreneur - March 2013 edition</productName>
<quantity>1</quantity>
</item>
In Item class, we have just one annotation ‘@XmlRootElement’. As per JAXB tutorial,
If a Java class has a straight forward mapping to XML schema (or XML document),
XmlRootElement is the only annotation you’ve to make.
# If I’ve more than one Items in a Purchase Order, class definition would change
PurchaseOrder.class
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import
javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class PurchaseOrder {
private
String orderNumber;
private
List<Item> items = new ArrayList<Item>();
public
String getOrderNumber() {
return
orderNumber;
}
public
void setOrderNumber(String orderNumber) {
this.orderNumber
= orderNumber;
}
public
List<Item> getItems() {
return
items;
}
public
void setItems(List<Item> items) {
this.items
= items;
}
}
Item.java
import
javax.xml.bind.annotation.XmlType;
public class Item {
public String
getProductName() {
return productName;
}
public void
setProductName(String productName) {
this.productName = productName;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
private String productName;
private int quantity;
}
JAXBMarshaler.java
import java.util.ArrayList;
import java.util.List;
import
javax.xml.bind.JAXBContext;
import
javax.xml.bind.Marshaller;
public class JAXBMarshaler {
public static void main(String[] args) throws Exception{
List<Item>
items = new ArrayList<Item>();
Item
item = new Item();
item.setProductName("Entrepreneur
- March 2013 edition");
item.setQuantity(1);
Item
item2 = new Item();
item2.setProductName("Food and Fun
- April 2013 edition");
item2.setQuantity(1);
items.add(item);
items.add(item2);
PurchaseOrder
po = new PurchaseOrder();
po.setItems(items);
po.setOrderNumber("1-1XY6FG");
JAXBContext
jaxbContext = JAXBContext.newInstance(PurchaseOrder.class);
Marshaller
jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(po,
System.out);
}
}
Compiling and running JAXBMarshalar produces expected XML with PurchaseOrder as top document element. We've also moved @XmlRootElement annotation toPurchaseOrder.java
Output.xml
<?xml version="1.0"
encoding="UTF-8" standalone="yes"?>
<purchaseOrder>
<items>
<productName>Entrepreneur - March 2013 edition</productName>
<quantity>1</quantity>
</items>
<items>
<productName>Food and Fun - April 2013 edition</productName>
<quantity>1</quantity>
</items>
<orderNumber>1-1XY6FG</orderNumber>
</purchaseOrder>
In XML document, all the Items are appearing in <items> element,
If you want to create a container element <items> that contains <item>
sub-elements, we need to modify our classes to follow XML structure.
Item.java
import
javax.xml.bind.annotation.XmlType;
public class Item {
public String
getProductName() {
return productName;
}
public void
setProductName(String productName) {
this.productName = productName;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
private String productName;
private int quantity;
}
Items.java
import java.util.ArrayList;
import java.util.List;
public class Items {
private List<Item> item = new
ArrayList<Item>();
public List<Item>
getItem() {
return item;
}
public void
setItem(List<Item> item) {
this.item = item;
}
}
JAXBMarshalar.java
import java.util.ArrayList;
import java.util.List;
import
javax.xml.bind.JAXBContext;
import
javax.xml.bind.Marshaller;
public class JAXBMarshaler {
public static void main(String[] args) throws Exception{
List<Item>
itemList = new ArrayList<Item>();
Item
item = new Item();
item.setProductName("Entrepreneur
- March 2013 edition");
item.setQuantity(1);
Item
item2 = new Item();
item2.setProductName("Food and Fun
- April 2013 edition");
item2.setQuantity(1);
itemList.add(item);
itemList.add(item2);
Items
items = new Items();
items.setItem(itemList);
PurchaseOrder
po = new PurchaseOrder();
po.setItems(items);
po.setOrderNumber("1-1XY6FG");
JAXBContext
jaxbContext = JAXBContext.newInstance(PurchaseOrder.class);
Marshaller
jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(po,
System.out);
}
}
Output.xml
<?xml version="1.0"
encoding="UTF-8" standalone="yes"?>
<purchaseOrder>
<items>
<item>
<productName>Entrepreneur -
March 2013 edition</productName>
<quantity>1</quantity>
</item>
<item>
<productName>Food and Fun -
April 2013 edition</productName>
<quantity>1</quantity>
</item>
</items>
<orderNumber>1-1XY6FG</orderNumber>
</purchaseOrder>
Summary
In Java classes, there is just one annotation for PurchaseOrder.java
that makes this whole thing work. Quite simple! If we need to design our Java
classes from XML, simply creating our classes by following the XML document
structure would suffice.
References:
No comments:
Post a Comment