ExoLab     OpenEJB     OpenJMS     OpenORB     Castor     Tyrex     

  Castor Forums
  Mailing Lists
  CVS / Bugzilla

  Using XML
  Source Generator
  Schema Support
  XML Mapping

  Using JDO
  JDO Config
  JDO Mapping
  Other Features

Advanced JDO
  Trans. & Locks
  Long Trans.
  Nested Attrs.
  Pooling Examples

  The Examples
  3rd Party Tools
  JDO Tests
  XML Tests
  Tips & Tricks
  Full JavaDoc

  Status, Todo
  Project Name


Reference: The XML Framework API

Note: This documentation is not yet finished

The Marshalling Framework
Using Existing Classes/Objects
Class Descriptors
        Compile-Time Descriptors
        Run-Time Descriptors


Castor XML is an XML databinding framework. Unlike the two main XML APIs, DOM (Document Object Model) and SAX (Simple API for XML) which deal with the structure of an XML document, Castor enables one to deal with the data defined in an XML document through an object model which represents that data.

Castor XML can marshal almost any "bean-like" Java Object to and from XML. In most cases the marshalling framework uses a set of ClassDescriptors and FieldDescriptors to describe how an Object should be marshalled and unmarshalled from XML.

For those not familiar with the terms "marshal" and "unmarshal", it's simply the act of converting a stream (sequence of bytes) of data to and from an Object. The act of "marshalling" consists of converting an Object to a stream, and "unmarshalling" from a stream to an Object.

The Marshalling Framework

The marshalling framework, as it's name implies, is responsible for doing the conversion between Java and XML. The framework consists of two main classes, org.exolab.castor.xml.Marshaller and org.exolab.castor.xml.Unmarshaller.

Lets walk through a very simple example. Assume we have a simple Person class as follows:

import java.util.Date;

 * An simple person class
public class Person implements java.io.Serializable {

     * The name of the person
   private String name = null;

     * The Date of birth
   private Date dob = null;

     * Creates a Person with no name
   public Person() {

     * Creates a Person with the given name
   public Person(String name) {
      this.name  = name;

     * @return date of birth of the person
   public Date getDateOfBirth() {
      return dob;

     * @return name of the person
   public String getName() {
      return name;

     * Sets the date of birth of the person
     * @param name the name of the person
   public void setDateOfBirth(Date dob) {
      this.dob = dob;

     * Sets the name of the person
     * @param name the name of the person
   public void setName(String name) {
      this.name = name;

To marshal an instance of the person class you simply call the Marshaller as follows:

// Create a new Person
Person person = new Person("Ryan 'Mad Dog' Madden");
person.setDateOfBirth(new Date(1955, 8, 15));

// Create a File to marshal to
writer = new FileWriter("test.xml");

// Marshal the person object
Marshaller.marshal(person, writer);

To unmarshal an instance of the person class you simply call the Unmarshaller as follows:

// Create a Reader to the file to unmarshal from
reader = new FileReader("test.xml");

// Marshal the person object
Person person = (Person)Unmarshaller.unmarshal(Person.class, reader);


Marshalling and Unmarshalling is basically that simple!

Note: A common mistake when using a Mapping file is to call the Marshaller or Unmarshaller as in the above example. This won't work because the mapping will be ignored. The above example uses the static methods of the marshalling framework. If you are using a mapping file simply call the Marshaller or Unmarshaller as follows:

// Load Mapping
Mapping mapping = new Mapping();

// Create a Reader to the file to unmarshal from
reader = new FileReader("test.xml");

// Create a new Unmarshaller
Unmarshaller unmarshaller = new Unmarshaller(Person.class);
// Unmarshal the person object
Person person = (Person)unmarshaller.unmarshal(reader);


Using Existing Classes/Objects

Castor can marshal "almost" any arbitrary Object to and from XML. When descriptors are not available for a specfic Class, the marshalling framework uses reflection to gain information about the object.

Actually an in memory set of descriptors are created for the object and we will soon have a way for saving these descriptors as Java source, so that they may be modified and compiled with little effort.

If a set of descriptors exist for the classes, then Castor will use those to gain information about how to handle the marshalling. See Class Descriptors for more information.

There is one main restrictions to marshalling objects. These classes must have have a public default constructor (ie. a constructor with no arguments) and adequete "getter" and "setter" methods to be properly be marshalled and unmarshalled.

The example illustrated in the previous section The Marshalling Framework demonstrates how to use the framework with existing classes.

Class Descriptors

Class descriptors provide the "Castor Framework" with necessary information so that the Class can be marshalled properly. The class descriptors can be shared between the JDO and XML frameworks.

Class descriptors contain a set of Field Descriptors

XML Class descriptors provide the marshalling framework with the information it needs about a class in order to be marshalled to and from XML. The XMLClassDescriptor org.exolab.castor.xml.XMLClassDescriptor.

XML Class Descriptors are created four main ways. Two of these are basically run-time, and the other two are compile time.

Compile-Time Descriptors

To use "compile-time" class descriptors, one can either implement the org.exolab.castor.xml.XMLClassDescriptor interface for each class which needs to be "described", or have the Source Code Generator create the proper descriptors.

The main advantage of compile-time descriptors is that they are faster than the run-time approach.

Run-Time Descriptors

To use "run-time" class descriptors, one can either simply let Castor introspect the classes, a mapping file can be provided, or a combination of both "default introspection" and a specified mapping file may be used.

For "default introspection" to work the class being introspected must have adequete setter/getter methods for each field of the class that should be marshalled and unmarshalled. If no getter/setter methods exist, Castor can handle direct field access to public fields. It does not do both at the same time. So if the respective class has any getter/setter methods at all, then no direct field access will take place.

There is nothing to do to enable "default introspection". If a descriptor cannot be found for a class, introspection occurs automatically.

Some behavior of the introspector may be controlled by setting the appropriate properties in the castor.properties file. Such behavior consists of changing the naming conventions, and whether primitive types are treated as attributes or elements. See castor.properties file for more information.

A mapping file may also be used to "describe" the classes which are to be marshalled. The mapping is loaded before any marshalling/unmarshalling takes place. See org.exolab.castor.mapping.Mapping

The main advantage of run-time descriptors is that it takes very little effort to get something working.


Copyright © 1999-2004 ExoLab Group. All rights reserved.
Java, EJB, JDBC, JNDI, JTA, Sun, Sun Microsystems are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and in other countries. XML, XML Schema, XSLT and related standards are trademarks or registered trademarks of MIT, INRIA, Keio or others, and a product of the World Wide Web Consortium. All other product names mentioned herein are trademarks of their respective owners.