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

advertisement

AddThis Social Bookmark Button

XML Data Binding with Castor
Pages: 1, 2

Developing data-binding for Address Book

We define the address book as holding a collection of persons. To build this, we will have to create a mapping for the data-binding framework, and we will see how it will be able to set up a java.util.Collection of Persons. We will also learn about mapping attributes (as in <foo anAttribute="somevalue">).



Here are the steps we will follow:

  1. Create an XML representation of the address book
  2. Create a Java object representing the address book
  3. Create a mapping.xml file to allow Castor XML to marshal and unmarshal
  4. Use Castor XML to display the address book

Step One: Create an XML representation of the address book

Our address book will have an <addressbook> tag wrapping around the <person> elements that we defined earlier:

<addressbook name="Manchester United Address Book">
  <person name="Roy Keane">
    <address>23 Whistlestop Ave</address>
    <ssn>111-222-3333</ssn>
    <email>roykeane@manutd.com</email>
    <home-phone>720.111.2222</home-phone>
    <work-phone>111.222.3333</work-phone>
  </person>
  <person name="Juan Sebastian Veron">
    <address>123 Foobar Lane</address>
    <ssn>222-333-444</ssn>
    <email>juanveron@manutd.com</email>
    <home-phone>720.111.2222</home-phone>
    <work-phone>111.222.3333</work-phone>  
  </person>
</addressbook>

Step Two: Create a Java object representing the address book

Now that we have the address book defined in XML, we need to create the AddressBook object that represents it. We will make the AddressBook hold a java.util.List of Persons:

import java.util.List;
import java.util.ArrayList;

public class Addressbook {
  private String addressBookName;
  private List   persons = new ArrayList();

  public Addressbook() { }

// -- manipulate the List of Person objects
  public void addPerson(Person person) {
    persons.add(person);
  }

  public List getPersons() {
    return persons;
  }

// -- manipulate the name of the address book
  public String getName() {
    return addressBookName;
  }

  public void setName(String name) {
    this.addressBookName = name;
  }
}

Now we have the programming interface that we'll use to work with an address book, and we have defined the XML representation. We need to tie these together, and that is where the mapping file comes in.

Step Three: Create a mapping.xml file to allow Castor XML to marshal and unmarshal

In our simple example of a person, we didn't have to create a mapping file, because Castor could work out what to do based on the JavaBean conventions that we followed.

We have to use the mapping file now, however, as we need to instruct Castor that:

  • We are going to have a collection of persons
  • We changed the <person> element to contain the name as an attribute
  • We are using an attribute to name the address book

Here is the mapping file (mapping.xml):

<?xml version="1.0"?>
<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Object Mapping DTD Version 1.0//EN" "http://castor.exolab.org/mapping.dtd">

<mapping>
<description>A mapping file for our Address Book application</description>

<class name="Person">
  <field name="name" type="string">
    <bind-xml name="name" node="attribute" />
  </field>
  <field name="address" type="string" />
  <field name="ssn" type="string" />
  <field name="email" type="string" />
  <field name="homePhone" type="string" />
  <field name="workPhone" type="string" />
</class>

<class name="Addressbook">
  <field name="name" type="string">
    <bind-xml name="name" node="attribute" />
  </field>
  <field name="persons" type="Person" collection="collection" />
</class>

</mapping>

Looking at the mapping file, you will see that it is built from the point of view of the Java class. We have Person.java and Addressbook.java, and both have a <class> element to describe them.

Each <class> has fields. This is where we tell Castor the name of the fields, their type, if they are an element or an attribute, and if there is one of them or a collection.

The following snippet describes the fact that the given tag has an attribute, of type String, with the name name. From this, Castor knows that the XML document will hold <addressbook name="the value">.

<field name="name" type="string">
    <bind-xml name="name" node="attribute" />
</field>

The next snippet gives the framework the ability to use a collection (in our case a java.util.List) of persons.

<field name="persons" type="Person" collection="collection" />

You can model many things in this mapping file, but let's not digress. For extensive coverage of this mapping file, see the Castor Web site.

Step Four: Use Castor XML to display the address book

To display the address book, we will want to unmarshal addressbook.xml. Unlike the simple person.xml, we will have to load the mapping file.

Here is the code for ViewAddressBook.java:

import org.exolab.castor.xml.*;
import org.exolab.castor.mapping.*;

import java.io.FileReader;
import java.util.List;
import java.util.Iterator;

public class ViewAddressbook {
  public static void main(String args[]) {
    try {
     // -- Load a mapping file
     Mapping mapping = new Mapping();
     mapping.loadMapping("mapping.xml");

     Unmarshaller un = new Unmarshaller(Addressbook.class);
     un.setMapping( mapping );

     // -- Read in the Addressbook using the mapping
     FileReader in = new FileReader("addressbook.xml");
     Addressbook book = (Addressbook) un.unmarshal(in);
     in.close();

     // -- Display the addressbook
     System.out.println( book.getName() );

     List persons = book.getPersons();
     Iterator iter = persons.iterator();

     while ( iter.hasNext() ) {
       Person person = (Person) iter.next();

       System.out.println("\n" + person.getName() );
       System.out.println("-----------------------------");
       System.out.println("Address = "+ person.getAddress());
         System.out.println("SSN = " + person.getSsn() );
       System.out.println("Home Phone = " +  
                             person.getHomePhone() );
       }
    } catch (Exception e) {
      System.out.println( e );
    }
  }
}

The only real difference here is that we are no longer using the static Unmarshaller.unmarshal() method. Now we instantiate an Unmarshaller object, and set the mapping to the newly created Mapping() object. The Mapping() object loads the XML mapping file that we just created:

Mapping mapping = new Mapping();
mapping.loadMapping("mapping.xml");

Unmarshaller un = new Unmarshaller(Addressbook.class);
un.setMapping( mapping );

Conclusion

We have shown that working with XML doesn't mean that you have to delve into the books to learn SAX, DOM, JAXP, and all the other TLAs. Castor's XML data-binding provides a simple but powerful mechanism to work with XML and Java objects.

Dion Almaer is a Principal Technologist for The Middleware Company, and Chief Architect of TheServerSide.Com J2EE Community.


Return to ONJava.com.