You are on page 1of 8

http://www.site.lalitbhatt.

com/java

JAXB Introduction
JAXB stands for Java architecture for XML binding .It is a standards specification which supports type mapping and helps in mapping Java to XML and vice versa. JAXB is a binding tool between XML and Java and provided a higher level of abstraction to work with.The reference implementation of JAXB can be seen at https://jaxb.dev.java.net. A good way of working with JAXB is to think of Java classes representing the XML instances. The scalar data types are mapped as java data types and the complex data types are mapped to object references. JAXB comes with basic set of tools which help in this mapping: xjc - compiler to generate the Java classes from the given XML schema defintion. schemagen - Generator to generate the XML schema definition for the given Java classes.

JAXB XML to Java


JAXB also supports generating of schema from the Java code. schemagen tool helps in this. Let's write a SimpleUser and SimpleAddress class with annotation and than we can generate the schema for it. SimpleUser.java @XmlRootElement(name="simpleUser") public class SimpleUser { protected List<SimpleAddress> addressList = new ArrayList<SimpleAddress>(); protected String comment; protected int age; @XmlElementWrapper(name="addresses") @XmlElement(name="address") public List<SimpleAddress> getAddressList() { return addressList; } .... SimpleAddress.java @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "address", propOrder = {"houseNo", "society", "locality", "city", "pin","phone"}) public class SimpleAddress { @XmlElement protected String houseNo; @XmlElement protected String society; @XmlElement

protected String locality; @XmlElement protected String city; @XmlElement protected int pin; @XmlTransient protected String country; Run the schmeagen tool on the above java classes schemagen.sh -d . //place where generated schema is kept -cp ../bin/ //classpath com.crayom.jaxb.SimpleUser //list of java files com.crayom.jaxb.SimpleAddress The generates schema looks like <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="simpleUser" type="simpleUser"/> <xs:complexType name="simpleUser"> <xs:sequence> <xs:element name="addresses" minOccurs="0"> <xs:complexType> <xs:sequence> <xs:element name="address" type="address" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="comment" type="xs:string" minOccurs="0"/> </xs:sequence> <xs:attribute name="age" type="xs:int" use="required"/> </xs:complexType> <xs:complexType name="address"> <xs:sequence> <xs:element name="houseNo" type="xs:string" minOccurs="0"/> <xs:element name="society" type="xs:string" minOccurs="0"/> <xs:element name="locality" type="xs:string" minOccurs="0"/> <xs:element name="city" type="xs:string" minOccurs="0"/> <xs:element name="pin" type="xs:int"/> <xs:element name="phone" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:complexType> </xs:schema>

JAXB Generating Java Classes From XML


Let's generate the Java classes using xjc compile. xjc tool is lying in the bin folder of download from [http://example.com|https://jaxb.dev.java.net]. The schema that we use for generating the class file is <?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <xsd:schema targetNamespace="http://www.crayom.com/om" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:om="http://www.crayom.com/om" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3.org/2001/XMLSchema-instance http://www.w3.org/2001/XMLSchema-instance.xsd http://www.w3.org/2001/XMLSchema http://www.w3.org/2001/XMLSchema.xsd"> <xsd:element name="user" type="om:UserType" /> <xsd:complexType name="UserType"> <xsd:sequence> <xsd:element name="homeAddress" type="om:Address" /> <xsd:element name="officeAddress" type="om:Address" /> <xsd:element name="comment" type="string" /> <xsd:element name="productBought" type="om:Products" /> </xsd:sequence> <xsd:attribute name="startDate" type="xsd:date" /> </xsd:complexType> <xsd:complexType name="Address"> <xsd:sequence> <xsd:element name="houseNo" type="xsd:string" /> <xsd:element name="society" type="xsd:string" /> <xsd:element name="locality" type="xsd:string" /> <xsd:element name="city" type="xsd:string" /> <xsd:element name="pin" type="xsd:decimal" /> </xsd:sequence> <xsd:attribute name="country" default="India"> </xsd:attribute> </xsd:complexType> <xsd:complexType name="Products"> <xsd:sequence> <xsd:element name="product" minOccurs="0" maxOccurs="unbounded"> <xsd:complexType> <xsd:sequence> <xsd:element name="name" type="xsd:string" /> <xsd:element name="quantity" type="xsd:integer" /> <xsd:element name="price" type="xsd:decimal" /> <xsd:element name="purchaseDate" type="xsd:date" minOccurs="0" /> </xsd:sequence> <xsd:attribute name="productNo" type="string" use="required" />

</xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> </xsd:schema> Run the compiler as shown below: xjc -d <folder where the classes to be generated> <location of xsd file> It will generate classes using the package structure as reflected by the target namespace of the xsd file. Once the classes are generated you will see the generated java classes having annotations. Let's look into the UserType.java class // // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-792 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> // Any modifications to this file will be lost upon recompilation of the source schema. // Generated on: 2009.04.02 at 03:42:03 PM IST // package com.crayom.om; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlSchemaType; import javax.xml.bind.annotation.XmlType; import javax.xml.datatype.XMLGregorianCalendar; /** * <p>Java class for UserType complex type. * * <p>The following schema fragment specifies the expected content contained within this class. * * <pre> * &lt;complexType name="UserType"> * &lt;complexContent> * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * &lt;sequence> * &lt;element name="homeAddress" type="{http://www.crayom.com/om}Address"/> * &lt;element name="officeAddress" type="{http://www.crayom.com/om}Address"/> * &lt;element name="comment" type="{http://www.w3.org/2001/XMLSchema}string"/> * &lt;element name="productBought" type="{http://www.crayom.com/om}Products"/> * &lt;/sequence> * &lt;attribute name="startDate" type="{http://www.w3.org/2001/XMLSchema}date" /> * &lt;/restriction> * &lt;/complexContent> * &lt;/complexType> * </pre> *

* */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "UserType", propOrder = { "homeAddress", "officeAddress", "comment", "productBought" }) public class UserType { @XmlElement(required = true) protected Address homeAddress; @XmlElement(required = true) protected Address officeAddress; @XmlElement(required = true) protected String comment; @XmlElement(required = true) protected Products productBought; @XmlAttribute @XmlSchemaType(name = "date") protected XMLGregorianCalendar startDate; //Getter and setters not shown here The java class has annotations which are self explanatory. The details are cover elsewhere. Now any XML file conforming to the above XSD can be read using JAXB api. Put the following jars from JAXB download activation.jar jaxb-api.jar jaxb-impl.jar jaxb-xjc.jar

The following code is used to read the XML: //Get the JAXB Context~~ JAXBContext jc = JAXBContext.newInstance("com.crayom.om"); Unmarshaller unmarshaller = jc.createUnmarshaller(); //Enable the validation handler~~ unmarshaller.setEventHandler(new javax.xml.bind.helpers.DefaultValidationEventHandler()); //Get the root and do processing in OO way~~ JAXBElement<UserType> userType = (JAXBElement<UserType>)unmarshaller.unmarshal(new File("src/user_jaxb.xml")); UserType user = (UserType)userType.getValue(); System.out.println(user.getProductBought().getProduct().size()); To generate the XML back using the marshaller is as follows //Generating the XML file using the generated code~~ //At the moment we will use the generated user object.~~ ObjectFactory of = new ObjectFactory();

JAXBElement jce = of.createUser(user); JAXBContext jcc = JAXBContext.newInstance("com.crayom.om"); Marshaller marshaller = jc.createMarshaller(); marshaller.marshal( jce, System.out ); The above code will generate the XML in the System.out console.

JAXB Validation using Schema


JAXB supports validation. It can validation an XML document before it is converted into Java object model.For validating the XML document register the schema with the unmarsheller //Setting the Validation Schema schema; SchemaFactory schemaFactory = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI ); schema = schemaFactory.newSchema(new File("src/user_jaxb.xsd")); unmarshaller.setSchema(schema); Another simple way is to register a EventHandler. There is a default Event handler is also provided. //Enable the validation handler~~ unmarshaller.setEventHandler(new javax.xml.bind.helpers.DefaultValidationEventHandler()); For customizing the validation messages a ValidationEventcollector is registered with the unmarshaller. The parsing fails at the moment the first exception is encountered. The code below might look that all the exceptions are collected at once but in reality the parsing stops the moment the first exception is encountered //If the message regarding validation to be customized~~ ValidationEventCollector validationCollector= new ValidationEventCollector(); unmarshaller.setEventHandler( validationCollector ); The message can be customized by iterating on the ValidationEventCollector for( ValidationEvent event: validationCollector.getEvents() ){ String msg = event.getMessage(); ValidationEventLocator locator = event.getLocator(); int line = locator.getLineNumber(); int column = locator.getColumnNumber(); System.out.println("Error at line " + line + " column "+ column ); }

JAXB Customizing Generated Java Code JAXB xjc compiler generates the code when it is passed the schema definition. However sometimes we may want to customize the nature of generated code like:
Package names class names Changing enum constants Associating Java types to XML built-in types

Documentation Customization can be added inline to the schema or can be provided in a separate file to the compiler. Customizing Package Name package name can be customized in couple of ways: Passing package name to the xjc compiler

xjc.sh -p <new package name> -d <directory to generate the code> <schema definition> Setting inline into the schema defintion file itself <xsd:annotation> <xsd:appinfo> <jaxb:schemaBindings> <jaxb:package name="com.lalit"/> </jaxb:schemaBindings> </xsd:appinfo> </xsd:annotation> Run the xjc compiler as xjc.sh -d <directory to generate the code> <schema definition> Writing the customization in a separate file itself Let's say we write customization.xjb <?xml version="1.0" encoding="UTF-8"?> <jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"> <jaxb:schemaBindings> <jaxb:package name="com.lalit"></jaxb:package> </jaxb:schemaBindings> </jaxb:bindings> Run the xjc compiler as follows xjc -b customization.xjb -d <directory to generate the code> <schema definition> Customizing Names The class name can be customized to give a different name. Let's change the name of our Address type in xsd <xsd:complexType name="class"> <xsd:annotation> <xsd:appinfo> <jaxb:class name="Address"/> </xsd:appinfo> </xsd:annotation> <xsd:sequence> <xsd:element name="houseNo" type="xsd:string" />

<xsd:element name="society" type="xsd:string" /> <xsd:element name="locality" type="xsd:string" /> <xsd:element name="city" type="xsd:string" /> <xsd:element name="pin" type="xsd:decimal" /> </xsd:sequence> <xsd:attribute name="country" default="India"> </xsd:attribute> </xsd:complexType> Now run the xjc compiler keeping and removing the xsd:annotation block.

You might also like