castor.jar 란 넘을 분석하다가..찾아 보게된 자료...
SUN : http://docs.sun.com/app/docs/doc/819-4707/gbvjl?a=view
-------------
From : http://www.onjava.com/pub/a/onjava/2001/10/24/xmldatabind.html
XML Data Binding with Castor
by Dion Almaer
10/24/2001
In this article, we will walk through marshalling data to
and from XML, using a XML data-binding API. The first question is, why? Why not
use SAX or DOM? Personally, when I sit down to work with XML, I get frustrated
with the amount of code that you need to write to do simple things.
I came across JDOM and found it to be something I
was looking for. DOM is built to be language-agnostic, and hence doesn't feel
very "Java-like." JDOM does a great job in being DOM, in a way I would like
to use it in Java.
For some applications, I don't want to even think about
"parsing" data. It would be so nice if I could have a Java object to work with,
and have it saved off as an XML representation to share, or store. This is
exactly what XML data-binding can do for us. There are a few frameworks to help
us do this, but we will walk through Castor, an open source
framework from Exolab. Castor is a data-binding framework, which is a path
between Java objects, XML documents, SQL tables, and LDAP directories. Today, we
will work with Castor XML, the XML piece of the Castor project
We will discover the different aspects of Castor XML as we
develop an Address Book XML document. We will create, read, and modify this XML
document via the data-binding framework.
All of the code from this article should work with any JVM
supporting the Java 2 platform.
We will walk through the following tasks:
- Create/modify/read a simple data-binding (Person
representation)
- Develop the data-binding for the Address Book
Create/modify/read a simple data-binding
Let's get to work, building a "person" for the Address
Book, which will sit between an XML representation and a Java object
representation.
- Create an XML representation of a person
- Create a Java object representing a person
- Use Castor XML to read in XML to create a JavaBean
- Use Castor XML to create a "person"
- Use Castor XML to modify a "person"
Step One: Create an XML representation of a
person
First of all, let us generate an XML representation of a
person:
Michael Owen
222 Bazza Lane, Liverpool, MN
111-222-3333
michael@owen.com
720.111.2222
111.222.3333
Download the code for this article
here. Code includes Person and Addressbook directories, as well as the
castor.properties file, and a readme file. For the code to work, you must have
either the castor.jar or the castor-xml.jar
file. |
Step Two: Create a Java object representing a
person
Now that we have defined a person in XML, we need to
generate a Java object that maps to this definition. To make things easy, we can
follow a convention and create get and set methods which match the names of the
elements in the XML document. If an element name is name
, the corresponding methods in the Java object will
be getName()
and setName()
. When elements have hyphens (such as
home-phone
), the corresponding method will
uppercase the first letter after the hyphen. So, home-phone
becomes getHomePhone()
. With this in mind, let's look at
Person.java
:
public class Person {
private String name;
private String address;
private String ssn;
private String email;
private String homePhone;
private String workPhone;
// -- allows us to create a Person via the constructor
public Person(String name, String address, String ssn,
String email, String homePhone, String workPhone) {
this.name = name;
this.address = address;
this.ssn = ssn;
this.email = email;
this.homePhone = homePhone;
this.workPhone = workPhone;
}
// -- used by the data-binding framework
public Person() { }
// -- accessors
public String getName() { return name; }
public String getAddress() { return address; }
public String getSsn() { return ssn; }
public String getEmail() { return email; }
public String getHomePhone() { return homePhone; }
public String getWorkPhone() { return workPhone; }
// -- mutators
public void setName(String name) { this.name = name; }
public void setAddress(String address) {
this.address = address;
}
public void setSsn(String ssn) { this.ssn = ssn; }
public void setEmail(String email) { this.email = email; }
public void setHomePhone(String homePhone) {
this.homePhone = homePhone;
}
public void setWorkPhone(String workPhone) {
this.workPhone = workPhone;
}
}
Step Three: Use Castor XML to create a
JavaBean
It's pretty simple so far: a simple XML document, a simple
JavaBean. Now we will use Castor to read in that XML and return a JavaBean. Here
is where we see the power of the framework. We are reading in XML, yet to us, it
looks like we are just working with a normal JavaBean.
Here is the code that reads the XML into the JavaBean, and
displays information on the person
:
import! org.exolab.castor.xml.*;
import! java.io.FileReader;
public class ReadPerson {
public static void main(String args[]) {
try {
Person person = (Person)
Unmarshaller.unmarshal(Person.class,
new FileReader("person.xml"));
System.out.println("Person Attributes");
System.out.println("-----------------");
System.out.println("Name: " + person.getName() );
System.out.println("Address: " + person.getAddress() );
System.out.println("SSN: " + person.getSsn() );
System.out.println("Email: " + person.getEmail() );
System.out.println("Home Phone: " +
person.getHomePhone() );
System.out.println("Work Phone: " +
person.getWorkPhone() );
} catch (Exception e) {
System.out.println( e );
}
}
}
The magic is in the Unmarshaller
class, and in this example, the
static method unmarshal()
. You simply give the method the
XML document from which to read, and the Java object that will be instantiated.
The framework then automatically goes through the XML,
uses reflection to look for methods that match the conventions that
we mentioned before, and set()
the values in the instantiated Java object.
Then we can talk to the Person
class to call any methods that we wish.
Notice that there are no SAX event handlers, and no need to walk the DOM tree.
You don't even really know that you are using XML!
Step Four: Use Castor XML to create a person
We have discussed unmarshalling (reading) XML into a Java object.
We can also create XML by simply marshalling a Person
object out to a file.
Ever had to go from a DOM to a file? This is a lot nicer!
Here is the code that will generate a person in the file bob_person.xml
:
import! org.exolab.castor.xml.*;
import! java.io.FileWriter;
public class CreatePerson {
public static void main(String args[]) {
try {
// -- create a person to work with
Person person = new Person("Bob Harris",
"123 Foo Street", "222-222-2222",
"bob@harris.org", "(123) 123-1234",
"(123) 123-1234");
// -- marshal the person object out as a
FileWriter file = new FileWriter("bob_person.xml");
Marshaller.marshal(person, file);
file.close();
} catch (Exception e) {
System.out.println( e );
}
}
}
In this source file we instantiate a person passing in initial values.
Then we use the Marshaller
class to write out this person as an
XML document to the bob_person.xml
file.
Indentation of XML files
If you run this program and look at the file,
you will see that it looks something like this:
Bob Harris
123 Foo Street111-222-3333
bob@harris.org(123) 123-1234
(123) 123-1234
This isn't very pretty on the eyes is it? By default,
Castor XML does not indent or format the XML representation,
as that requires extra resources. For development purposes,
you can make the output "pretty" by creating a castor.properties
file
that has the following property:
org.exolab.castor.indent=true
Step Five: Use Castor XML to modify a person
We now know how to read in a person,
and how to create a person
.
Now we can put these two together to modify an existing person
.
Here is the code that unmarshalls person.xml
, makes a change to the name,
and then marshals the Java object back into an XML file:
import! org.exolab.castor.xml.*;
import! java.io.FileWriter;
import! java.io.FileReader;
public class ModifyPerson {
public static void main(String args[]) {
try {
// -- read in the person
Person person = (Person)
Unmarshaller.unmarshal(Person.class,
new FileReader("person.xml"));
// -- change the name
person.setName("David Beckham");
// -- marshal the changed person back to disk
FileWriter file = new FileWriter("person.xml");
Marshaller.marshal(person, file);
file.close();
} catch (Exception e) {
System.out.println( e );
}
}
}
Just like that we modify a person, again without having to work with
any XML-specific APIs. Now that we have a person,
let's move on to setting up an Address Book.
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
).
Here are the steps we will follow:
- Create an XML representation of the address book
- Create a Java object representing the address book
- Create a
mapping.xml
file to allow Castor XML to marshal and unmarshal - Use Castor XML to display the address book
Step One: Create an XML representation of the address book
Our address book will have an
tag wrapping around
the
elements that we defined earlier:
23 Whistlestop Ave
111-222-3333
roykeane@manutd.com
720.111.2222
111.222.3333
123 Foobar Lane
222-333-444
juanveron@manutd.com
720.111.2222
111.222.3333
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
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
):
A mapping file for our Address Book application
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
element to describe them.
Each
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
.
The next snippet gives the framework the ability to use a collection
(in our case a java.util.List
) of persons
.
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.
Copyright © 2004 O'Reilly Media, Inc.
http://www.castor.org/