ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

The State of JAXB: Availability, Suitability, Analysis, and Architecture
Pages: 1, 2, 3, 4

The Ant Build File to the Rescue

The Ant build file looks something like this:



<?xml version="1.0"?>
<project basedir="." default="jar">
    <!-- if you are not running from
         $JWSDP_HOME/JAXB/samples AND you are using
         your own version of Ant, then you need to specify
         "ant -Djwsdp.home=..." -->
    <property name="jwsdp.home" value="../../.." />
<!--
**************************************************
* In the project I have identified that my goal
* is generate an eventual jar file
* Identify all the needed jar files
**************************************************
-->
    <path id="classpath">
        <pathelement path="." />
        <!-- for use with bundled ant -->
        <fileset dir="${jwsdp.home}"
            includes="JAXB/lib/*.jar" />
        <fileset dir="${jwsdp.home}"
            includes="jwsdp-shared/lib/*.jar" />
        <fileset dir="${jwsdp.home}"
            includes="jaxp/lib/**/*.jar" />
        
    </path>

<!--
**************************************************
* Get hold of the XJCTask that generates the
* Java class files
**************************************************
-->
    <taskdef name="xjc"
        classname="com.sun.tools.xjc.XJCTask">
        <classpath refid="classpath" />
    </taskdef>
    
<!--
**************************************************
* This target compile does the following
* 1. Use sample.xsd in the current directory
* 2. Generate in a sub directory called "gen"
* 3. (You have to Make sure the directory
*    "gen" is created before)
* 4. Use a package name called "com.ai.xmltest"
* 5. All the needed sub directories to suit the
*    package names will be created
* 6. All the needed files will be created
**************************************************
-->
    <target name="compile">
        <echo message="Compiling the schema..."/>
        <xjc schema="sample.xsd"
            target="./gen" package="com.ai.xmltest"/>
    </target>
    
<!--
**************************************************
* This target Javacompile compiles the Java into
* classes. This activity depends on the previous 
* "compile" activity. It takes the sources 
* from "gen" and creates the classes into
* "gen" as well
**************************************************
-->
    <target name="Javacompile" depends="compile">    
        <Javac srcdir="./gen"
            destdir="./gen" debug="on">
            <classpath refid="classpath" /> 
        </Javac>
    </target>
    
<!--
**************************************************
* Finally the "jar" activity will jar up the output 
* from the previous activity
* You can specify the zip or jar file that you want
* In my case I have placed the output in a sep directory
* I used zip extension so that pkzip will pick it up easily 
* to verify the output
**************************************************
-->
    <target name="jar" depends="Javacompile">
        <jar destfile="c:\work\xmltest.zip"
            basedir="./gen">
        </jar>
    </target>
    
</project>

You can change the XSD file references and other directory references to make this file work for you. To run this file, you can name this file build.xml and run Ant from that directory. Here is a batch file that runs Ant on this file.

set path=C:\jws-pack-13\apache-ant\bin
set Java_HOME=c:\jdk142
ant

This batch file will set the path to where Ant is available. As you can see, the JAXB distribution includes this in the apache-ant subdirectory. You also need to set the Java_HOME path variable. Then run this batch file in the directory where you have the build.xml and XSD files.

The end result of running this batch file is a .jar file with all of the generated classes.

Summary of the Compilation Process

Compared to .NET, the compilation process is quite painful until you get a hang of the Ant build files. So expect to spend some time to get yourself familiarized with Ant. One good thing about the Ant build files is that you can generate the .jar file directly from the XSD files. This will give you a nice packaged .jar file that you can include in your IDEs and the runtime.

Story of the Generated Classes

It will be interesting to see what the generated classes look like and how they compare with .NET's generated classes.

//************************************************
// Folder classes
// Notice the following
// 1. There is an intermediate class called FolderType
// 2. The contained files is returned as List interface
// 3. This is quite useful comaped to .NET which
//    returns an array 
//************************************************
package com.ai.xmltest;
public interface FolderType 
{
    Java.lang.String getName();
    void setName(Java.lang.String value);

    Java.lang.String getId();
    void setId(Java.lang.String value);
    Java.util.List getFile();

}
public interface Folder
    extends Javax.xml.bind.Element,
            com.ai.xmltest.FolderType
{
}

//************************************************
// File classes
// Notice the following
// 1. See how it is possible to generate
//    "isSet" methods
//************************************************
package com.ai.xmltest;
public interface File {
    Java.lang.String getDescription();
    void setDescription(Java.lang.String value);

    boolean isSetDescription();
    void unsetDescription();

    Java.lang.String getContents();
    void setContents(Java.lang.String value);

    Java.lang.String getName();
    void setName(Java.lang.String value);

    Java.lang.String getId();
    void setId(Java.lang.String value);
}

We can conclude a few things from the generated classes. JAXB generates interfaces as opposed to concrete classes. Also, JAXB sometimes appends type as part of a classname. This matter falls under the topic of customizing the Java class generation and is discussed in one of the included references. Another important thing to note is that the children of a container-like folder are represented using List. This is quite convenient, as one can use this object to add any number of items as children. This seems obvious until one examines the class generation in the .NET world, where this object is represented using typed, fixed-length, un-instantiated arrays. These fixed-length arrays are quite distracting. On the other hand, one problem with the interface-based approach is that you can't add constructors to these interfaces to force the mandatory arguments to these classes. With that, let us take a look at the generated .NET classes

Comparing to .NET class generation

using System.Xml.Serialization;
namespace XMLSerializationTest 
{
    /// <remarks/>
    [System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
    public class folder 
    {
        //Default constructor
        public folder() {}
        public folder(string inId, string inName,
                      int numberOfItems)
        {
            id = inId;
            name = inName;
            files = new file[numberOfItems];
        }
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("file")]
        public file[] files;
    
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string id;
    
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string name;
    }

    /// <remarks/>
    public class file
    {
        public file(){}
        public file(string inId, string inName)
        {
            id = inId;
            name = inName;
        }
        /// <remarks/>
        public string description;
    
        /// <remarks/>
        public string contents;
    
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string id;
    
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string name;
    }//eof-class
}//eof-namespace

I have modified the generated .NET classes slightly. This is possible in .NET because the generated classes are concrete classes with public variables. I have added constructors to both classes so that mandatory arguments can be passed in during the construction phase. There is one drawback I have mentioned before with the .NET generated classes: for containment, .NET uses typed, fixed-length, un-instantiated arrays. For example, the variable files[] is just a reference. To use this variable you have to instantiate an object memory for it. You can see this in the constructor of the folder class.

Pages: 1, 2, 3, 4

Next Pagearrow