Thursday, October 10, 2013

Generating java files from XSD using Ant and JAXB

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. As part of this process, 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. JAXB also provides a way to generate XML schema from Java objects and vice-versa.

Here we are going to talk about generating java objects from your XSD (XML Schema Definition).

Note : If you are using Maven for build, then refer this article
Purpose of this article :
To demonstrate how to generate java objects from an XSD, compile them to classes and pack into a jar file.


Tools & Technologies:
  1. Java JDK 1.5 or above (jdk download)
  2. Apache Ant (Ant download
  3. Java Web Services Developer Pack (JWSDP download)
Lets get started !

1. Create customized XJB (JAXB Bindings) file

In most cases, the default bindings generated by the JAXB binding compiler will be sufficient to meet your needs. There are cases, however, in which you may want to modify the default bindings. For example, the following is a sample XJB file (gvBindings.xjb) which puts files into com.gv.test folder. The name Java class for every element would be prefixed with 'GV'.

<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <jxb:bindings schemaLocation="gvSchema.xsd" node="/xs:schema">
           <jxb:schemaBindings>
              <jxb:package name="com.gv.test"/>
                <jxb:nameXmlTransform>
                     <jxb:elementName prefix="GV"/>
                </jxb:nameXmlTransform>    
          </jxb:schemaBindings>
        </jxb:bindings> 
</jxb:bindings>

2. XSD file

Here I have a sample XSD file (gvSchema.xsd). It has an element with name 'details' which contains child elements.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="details"> 
 <xs:complexType>    
  <xs:sequence>                    
      <xs:element name="name" type="xs:string"/>       
      <xs:element name="address" type="xs:string"/>      
      <xs:element name="city" type="xs:string"/>        
      <xs:element name="country" type="xs:string"/> 
  </xs:sequence>  
 </xs:complexType>
</xs:element>
</xs:schema>
The above XSD file can be used to marshall/unmarshal XMLs which would be of following format :
<?xml version="1.0" encoding="ISO-8859-1"?>
 <details>
 <name>G V</name>
 <address>Somewhere in the world</address>
 <city>test city</city>
 <country>test country</country>
 </details>

3. Create build file

3.1 Add XJC task

The jaxb-xjc.jar file contains the XJCTask.class file, which allows the XJC binding compiler to be invoked from the Ant build tool. To use XJCTask, include the following statement in your build.xml file. Provide the path of JWSDP on your system:

<taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
 <classpath>
  <fileset dir="${JWSDP_PATH}" includes="*.jar" />
 </classpath>
</taskdef>

3.2 Use XJC task 

Now we can use the task defined above. It will refer to the xjb and xsd files which are present in schema.dir folder. The task will generate java files in src.dir folder :

<xjc destdir="${src.dir}" extension="true" binding="${schema.dir}/gvBindings.xjb" >
 <schema dir="${schema.dir}" includes="gvSchema.xsd"/>
</xjc>

As per the xjb binding a java file for element 'details' would be generated as com.gv.test.GVdetails.java Similar classes would be generated for other elements.

3.3 Compile the Java objects to class files

We would now compile our Java files to convert them to class files which we would be packing into the jar. Make sure that the JAVA_HOME variable is present in environment variables and points to your JDK directory. Also JAVA_HOME/bin is present in your classpath. 
<javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="${classpath}" debug="on" fork="true" memoryinitialsize="512m" memorymaximumsize="512m"/>

3.4 Packing the class files into the jar

The classes can be now packed into a jar and our project jar would be ready to use.
<jar destfile="${jar.name}"  index="true">
 <fileset dir="${classes.dir}">
  <include name="**/*.*" />
 </fileset>
</jar>

4. Running the Ant build file

Before running the ant build you need to make sure that the ANT_HOME variable is present in environment variables and points to your Ant directory. Also ANT_HOME/bin is present in your classpath.

We need to create a target in the build file and include statements mentioned in 3.1 to 3.4 sequentially to it.

<target name="GenerateJarFromXSD">
<taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
 <classpath>
  <fileset dir="${JWSDP_PATH}" includes="*.jar" />
 </classpath>
</taskdef>
<xjc destdir="${src.dir}" extension="true" binding="${schema.dir}/gvBindings.xjb" >
 <schema dir="${schema.dir}" includes="gvSchema.xsd"/>
</xjc>
<javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="${classpath}" debug="on" fork="true" memoryinitialsize="512m" memorymaximumsize="512m"/>
<jar destfile="${jar.name}"  index="true">
 <fileset dir="${classes.dir}">
  <include name="**/*.*" />
 </fileset>
</jar></target>

To run the target from command line, open cmd and go to the folder where we have stored our build.xml. Run the following :

ant -buildfile build.xml GenerateJarFromXSD

To run the target from eclipse, right click on the build file. Run As -> Ant Build.  

Your project jar should now be ready to use. Happy Coding !

No comments:

Post a Comment