Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Converting between Java objects and XML with Quick

Integrating Java objects and XML data

Brett McLaughlin (brett@newInstance.com), Author and Editor, O'Reilly Media Inc.
Photo of Brett McLaughlin
Brett McLaughlin has been working in computers since the Logo days (Remember the little triangle?). He currently specializes in building application infrastructure using Java and Java-related technologies. He has spent the last several years implementing these infrastructures at Nextel Communications and Allegiance Telecom, Inc. Brett is one of the co-founders of the Java Apache project Turbine, which builds a reusable component architecture for Web application development using Java servlets. He is also a contributor to the EJBoss project, an open source EJB application server, and Cocoon, an open source XML Web-publishing engine.

Summary:  Quick is an open source data binding framework with an emphasis on runtime transformations. This instructional article shows you how to use this framework to quickly and painlessly turn your Java data into XML documents, without the class generation semantics required by other data binding frameworks. Extensive code samples are included.

Date:  01 Aug 2002
Level:  Intermediate
Also available in:   Japanese

Activity:  73194 views
Comments:  

XML has certainly taken the programming world by storm over the last several years. However, the complexity of XML applications, which started out high, has not diminished much in the recent past. Developers still have to spend weeks, if not months, learning the complicated semantics of XML, as well as APIs to manipulate XML, such as SAX and DOM. However, in just the last six to 12 months a new class of XML API, called Quick, has become increasingly popular as a simpler alternative to these more complex APIs.

Data binding allows you to directly map between the Java objects and XML, without having to deal with XML attributes and elements. Additionally, it allows Java developers to work with XML without having to spend hours boning up on XML specifications. Quick is one such data binding API -- a project that's geared toward business use in Java applications.

Installation and setup

Before diving into the details of using Quick, you'll need to download and install the project. Visit Quick's Web site (see Resources ), and select Download. You can then download a .zip file for the project; as of this writing, the latest version available was Quick 4.3.1, accessed through the Quick4.3.1.zip file.

Expand the .zip file to create the Quick distribution. The directory hierarchy is shown in Listing 1:


Listing 1. Quick directory stucture

Quick4
  |
  +-- JARs
  +-- BATs
  +-- Doc
  +-- dtdParserSrc
  +-- DTDs
  +-- examples
  +-- JARs
  +-- QDMLs
  +-- QJMLs
  +-- quickSrc
  +-- UTILs
  +-- utilSrc
  +-- XSLs

The two directories of most interest to developers are Quick4/BATs, which should be added to your PATH environment variable, and Quick4/JARs, which contains jar files that should be added to your CLASSPATH environment variable. Specifically, you need to add dtdparser115.jar, Quick4rt.jar, and Quick4util.jar to your current class path. You'll also need a SAX parser implementation, such as the Apache project's Xerces-J (see Resources ). Add xerces.jar, or your own favorite parser, to your class path as well.


Java classes and XML documents

Data binding centers around XML and Java, so let's take a look at how these XML documents and Java classes relate to Quick. To illustrate these points, I look at several simple Java classes, and a simple XML document.

A simple XML document

First, Listing 2 shows a small XML document. I've kept things simple so that you don't miss out on the concepts by wading through 10 or 15 Java classes.


Listing 2. XML representing a person


<?xml version="1.0"?>
<!DOCTYPE person SYSTEM "person.dtd">
<person>
  <firstName>Gary</firstName>
  <lastName>Greathouse</lastName>
  <address type="home">
    <street>10012 Townhouse Drive</street>
    <city>Waco</city>
    <state>TX</state>
    <zipCode>76713</zipCode>
  </address>
  <phoneNumber>
    <type>home</type>
    <number>2545550287</number>
  </phoneNumber>
  <phoneNumber>
    <type>work</type>
    <number>2545556127</number>
  </phoneNumber>
</person>


Listing 2, while not a prime example of how to write XML, brings out several Quick points that are worth noting. You'll also want to take a look at the DTD for the document, shown in Listing 3.


Listing 3. DTD for person.xml


<!ELEMENT person (firstName, lastName, address+, phoneNumber+)>

<!ELEMENT firstName (#PCDATA)>
<!ELEMENT lastName (#PCDATA)>

<!ELEMENT address (street, city, state, zipCode)>
<!ATTLIST address
          type    (home | work | other)    "home"
>

<!ELEMENT street (#PCDATA)>
<!ELEMENT city (#PCDATA)>
<!ELEMENT state (#PCDATA)>
<!ELEMENT zipCode (#PCDATA)>

<!ELEMENT phoneNumber (type, number)>
<!ELEMENT type (#PCDATA)>
<!ELEMENT number (#PCDATA)>


The Java classes

In many data binding implementations, you would now need to generate Java source files to represent this type of XML document. That sort of implementation assumes, generally falsely, that you lack the Java business objects you want to use. More commonly, you have a set of Java classes that you want to begin persisting to XML. This use case is exactly what Quick helps to solve. In light of that, then, Listings 4, 5, and 6 are three Java source files that represent a person.


Listing 4. The Person class


import java.util.LinkedList;
import java.util.List;

public class Person {

    /** The first name of the person */
    private String firstName;
    
    /** The last name of the person */
    private String lastName;
    
    /** The addresses of the person */
    private List addressList;
    
    /** The phone numbers of the person */
    private List phoneNumberList;
    
    public Person() {
        addressList = new LinkedList();
        phoneNumberList = new LinkedList();
    }
    
    public Person(String firstName, String lastName,
        List addressList, List phoneNumberList) {
            
        this.firstName = firstName;
        this.lastName = lastName;
        this.addressList = addressList;
        this.phoneNumberList = phoneNumberList;
    }
    
    public String getFirstName() {
        return firstName;
    }
    
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    
    public String getLastName() {
        return lastName;
    }
    
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    
    public List getAddressList() {
        return addressList;
    }
    
    public void setAddressList(List addressList) {
        this.addressList = addressList;
    }
    
    public void addAddress(Address address) {
        addressList.add(address);
    }
    
    public List getPhoneNumberList() {
        return phoneNumberList;
    }
    
    public void setPhoneNumberList(List phoneNumberList) {
        this.phoneNumberList = phoneNumberList;
    }
    
    public void addPhoneNumber(PhoneNumber phoneNumber) {
        phoneNumberList.add(phoneNumber);
    }
}


Listing 5. The Address class


public class Address {

    /** The type of address */
    private String type;
    
    /** The street address */
    private String street;
    
    /** The city */
    private String city;
    
    /** The state */
    private String state;
    
    /** The zip code */
    private String zipCode;
    
    public Address() { }
    
    public Address(String type, String street, String city, 
        String state, String zipCode) {
        
        this.type = type;
        this.street = street;
        this.city = city;
        this.state = state;
        this.zipCode = zipCode;
    }
    
    public String getType() {
        return type;
    }
    
    public void setType(String type) {
        this.type = type;
    }
    
    public String getStreet() {
        return street;
    }
    
    public void setStreet(String street) {
        this.street = street;
    }
    
    public String getCity() {
        return city;
    }
    
    public void setCity(String city) {
        this.city = city;
    }
    
    public String getState() {
        return state;
    }
    
    public void setState(String state) {
        this.state = state;
    }
    
    public String getZipCode() {
        return zipCode;
    }
    
    public void setZipCode(String zipCode) {
        this.zipCode = zipCode;
    }
}


Listing 6. The PhoneNumber class


public class PhoneNumber {

    /** The number itself */
    private String number;
    
    /** The type of number */
    private String type;
    
    public PhoneNumber() { }
    
    public PhoneNumber(String type, String number) {
        this.type = type;
        this.number = number;
    }
    
    public String getNumber() {
        return number;
    }
    
    public void setNumber(String number) {
        this.number = number;
    }
    
    public String getType() {
        return type;
    }
    
    public void setType(String type) {
        this.type = type;
    }
}

These classes should be fairly self-explanatory. They are the analogs of the XML structure you saw back in Listing 2. Presumably, you will want to convert XML documents to instances of these Java objects, and back again. Quick makes these conversions a piece of cake.


Initialization

Once you have your XML document (or documents), your DTD, and your Java classes, you need to tell the Quick framework how to map data from one format to the other. This is a multi-step process:

  1. Create a QDML file from the XML document's DTD
  2. Create a QJML file from the QDML document
  3. Create a QIML file from the QJML document
  4. Use the QIML to map Java to XML and back again

I'll show you how to accomplish each step in turn in the next several sections. While this may seem like a lot of steps to get Quick going, you should note that each of these only needs to occur one time so this is an up-front cost for using the Quick framework. Once you have taken care of these steps, you can use Quick in your applications as many times as you want, without this process overhead.

Creating QDML

The first thing you need to do in getting Quick ready to roll is create a QDML file. QDML (Quick Document Markup Language) is essentially Quick's version of a DTD, and defines the XML document's structure for the Quick framework. At this point, you aren't providing any mapping information; you're just defining your document in a format that Quick can understand. Of course, this is accomplished through a Quick tool, which makes life easier for developers.

First, make sure that your class path is set up as indicated in Installation and setup. You can then use the cfgDtd2Qdml script, located in the Quick distribution's BATs directory. For Windows users, you would use cfgDtd2Qdml.bat; for Unix users, use cfgDtd2Qdml.sh. (The examples in this article are all in Unix format, but you can easily accomplish the tasks on Windows.)

Issue the following command:

sh cfgDtd2Qdml.sh -in=person.dtd -out=person.qdml

You won't see much exciting in terms of output, but you should get a new file, called person.qdml. With your DTD in a format that's more easily understood by Quick, you're almost ready to move to the next step.

Before moving on, you need to let Quick (and the QDML file it uses) know the root element of your XML document. In this case, it's the person element. To do this, use another Quick utility:

sh cfgSetQdmlRoot.sh -in=person.qdml -out=person.qdml -root=person

Creating QJML

You now need to create a QJML file for Quick to use. QJML is the Quick Java Markup Language, and is the equivalent of a binding schema, for those of you familiar with JAXB or other data binding implementations. Quick uses QJML to convert the constructs in your XML file to their Java counterparts, and vice versa.

It's possible to create a QJML file from scratch; however, Quick supplies a tool for generating one automatically, and you generally only need to make minimal changes. For that reason, this is the recommended approach. Use either the cfgQdml2Qjml.bat or cfgQdml2Qjml.sh script to accomplish this, supplying your newly-generated QDML file as input (Quick reads the QDML to determine the constructs to map; see why you needed that file now?):

sh cfgQdml2Qjml.sh -in=person.qdml -out=person.qjml

You should now have a new file, person.qjml.

As I've said, you will need to make some changes to this file, since Quick makes some problematic assumptions about Java variable names. Open up your file, and add the property elements for each item (highlighted in bold) so it resembles Listing 7.


Listing 7. Editing your QJML


<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE qjml SYSTEM "classpath:///qjml.dtd">
<qjml root="person">
    <bean tag="person">
        <targetClass>Person</targetClass>
        <elements>
            <item coin="firstName">
                <property name="firstName"/>
            </item>
            <item coin="lastName">
                <property name="lastName"/>
            </item>
            <item coin="address" repeating="True">
                <property kind="list" name="addressList"/>
            </item>
            <item coin="phoneNumber" repeating="True">
                <property kind="list" name="phoneNumberList"/>
            </item>
        </elements>
    </bean>
    <text tag="firstName"/>
    <text tag="lastName"/>
    <bean tag="address">
        <targetClass>Address</targetClass>
        <attributes>
            <item coin="address.type" optional="True" value="home">
                <property initializer="home" name="type"/>
            </item>
        </attributes>
        <elements>
            <item coin="street">
                <property name="street"/>
            </item>
            <item coin="city">
                <property name="city"/>
            </item>
            <item coin="state">
                <property name="state"/>
            </item>
            <item coin="zipCode">
                <property name="zipCode"/>
            </item>
        </elements>
    </bean>
    <text label="address.type" tag="type">
        <enum value="home"/>
        <enum value="work"/>
        <enum value="other"/>
    </text>
    <text tag="street"/>
    <text tag="city"/>
    <text tag="state"/>
    <text tag="zipCode"/>
    <bean tag="phoneNumber">
        <targetClass>PhoneNumber</targetClass>
        <elements>
            <item coin="type">
                <property name="type"/>
            </item>
            <item coin="number">
                <property name="number"/>
            </item>
        </elements>
    </bean>
    <text tag="type"/>
    <text tag="number"/>
</qjml>


These changes should be pretty obvious when you compare the original file to the one shown in Listing 7; they all involve mapping the XML property to the correct Java property name, as defined in the source code (see Listings 4, 5, and 6 for a refresher on these).

Creating QIML

You're almost done with the setup work; you still need to perform one final step. Quick performs much better with a QIML file -- the Quick Internal Markup Language. As the name implies, Quick uses this internal format to avoid runtime compilation, conversion, and processing of QJML files. Perform the following simple step to put your QJML into a format that Quick can use more handily:

sh cfgQjml2Qiml.sh -in=person.qjml -out=person.qiml

Finally, to improve performance even further, turn this text-based format into a Java source file that you can compile (binary objects are always better to work with than non-compiled textual file formats):

sh cfgQiml2Java.sh -in=person.qiml -out=PersonSchema.java 
-class=PersonSchema -key=person.qjml

You really don't need to worry too much about what is happening here; it's all Quick-specific, and the utilities take care of things. You should now compile this created source (and the rest of your Java source if you haven't already), and make sure everything is added to your classpath. With all these steps complete, you're ready to do some data binding.


Data binding

With all the setup work done, it is now trivial to use the Quick framework to convert your XML document into Java bytecode and then back again. I'm going to keep the example for this simple; once you've got the basics down, the uses of data binding become limitless, and rather than assume I know your use-case, I'll just let you use the information you need from the sample code and take off! Take a look at Listing 8, and then I'll explain the main concepts.


Listing 8. Using Quick in Java


import java.util.Iterator;

// Quick imports
import com.jxml.quick.QDoc;
import com.jxml.quick.Quick;

public class PersonTest {

  public static void main(String[] args) {
    try {
      if (args.length != 2) {
        System.err.println("Usage: java PersonTest [input file] [output file]");
        return;
      }

      // Initialize Quick
      QDoc schema = PersonSchema.createSchema();

      // Convert input XML to Java
      QDoc doc = Quick.parse(schema, args[0]);

      // Get the result
      Person person = (Person)Quick.getRoot(doc);

      // Output block
      System.out.println(" --------------- Person ------------------ ");
      System.out.println(" First Name: " + person.getFirstName());
      System.out.println(" Last Name : " + person.getLastName());
      for (Iterator i = person.getAddressList().iterator(); i.hasNext(); ) {
        Address address = (Address)i.next();
        System.out.println(" Address (" + address.getType() + "):");
        System.out.println("   " + address.getStreet());
        System.out.println("   " + address.getCity() + ", " + address.getState() +
           " " + address.getZipCode());
      }
      for (Iterator i = person.getPhoneNumberList().iterator(); i.hasNext(); ) {
        PhoneNumber number = (PhoneNumber)i.next();
        System.out.println(" Phone Number (" + number.getType() + "):");
        System.out.println("   " + number.getNumber());
      }

      // Add a new address
      Address address = 
        new Address("work", "357 West Magnolia Lane", "Waco", "TX", "76710");
      person.getAddressList().add(address);

      // Change a phone number
      PhoneNumber number = (PhoneNumber)person.getPhoneNumberList().get(1);
      number.setNumber("2547176547");

      // Write out modified XML
      Quick.express(doc, args[1]);
    } catch (Exception e) {
       e.printStackTrace();
    }
  }
}

The portion of this code that deals with Quick turns out to be only about four lines! You first must load the QIML (compiled as Java bytecode) so Quick knows which XML elements and attributes become which Java classes and properties. Do this through the createSchema() method (which is static) of the generated PersonSchema class. Once that schema is loaded, it and the input file are handed off to the Quick.parse() method, which does the conversion. From there, you simply have to grab the root element of the resulting QDoc and work with it as you would any other Java object. Quick enters the picture again in the last bit of the code where the express() method outputs a modified version of the XML. Pretty easy, isn't it?

Note: Do not supply the same filename for both input and output, as you will overwrite your original data, and can cause all sorts of unexpected things to happen.


Conclusion

Ideally, you've seen some really intriguing functionality here. First, data binding in general can greatly simplify programming tasks, especially when you need to persist data to some type of static storage (like a file, as shown in this article). Additionally, Quick provides a fast, simple way to achieve this in your own projects. Take a spin around the block with Quick, and see how you like it. Enjoy, and I'll see you online!



Download

NameSizeDownload method
x-quick/quick.zip HTTP

Information about download methods


Resources

About the author

Photo of Brett McLaughlin

Brett McLaughlin has been working in computers since the Logo days (Remember the little triangle?). He currently specializes in building application infrastructure using Java and Java-related technologies. He has spent the last several years implementing these infrastructures at Nextel Communications and Allegiance Telecom, Inc. Brett is one of the co-founders of the Java Apache project Turbine, which builds a reusable component architecture for Web application development using Java servlets. He is also a contributor to the EJBoss project, an open source EJB application server, and Cocoon, an open source XML Web-publishing engine.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Java technology
ArticleID=10689
ArticleTitle=Converting between Java objects and XML with Quick
publish-date=08012002
author1-email=brett@newInstance.com
author1-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers