Long Term Persistence of JavaBeans Components: XML Schema

   

Long Term Persistence of JavaBeans Components:
XML Schema

The persistence scheme added in v 1.4 uses instances of the XMLEncoder class to write out files representing JavaBeans components (beans). Every file written by XMLEncoder uses the same XML schema, regardless of the beans the file contains. In this document we describe this schema so that implementations other than XMLEncoder and its corresponding reader, XMLDecoder, can be used to write and read compatible files.

This document presents the basic elements of each XML archive, followed by the tags necessary to represent objects. Next comes a section of abbreviations -- tags that aren't strictly necessary to write out an XML archive, but that make the archive shorter and easier to read. The final sections describe the top level of the XML archive, which can refer to properties of the decoder, and give a DTD for the XML schema.

You can find an example XML archive here: Browse.xml . This example is an archive of a simple application that accepts a URL and, using a JEditorPane, displays the HTML from that URL. You can read the archive and run the application using the following code:

try {
    XMLDecoder d = new XMLDecoder(
                       new BufferedInputStream(
                           new FileInputStream("Browse.xml")));
    d.readObject();
    d.close();
} catch (IOException e) {
    ...
                   handle the exception...
}
                

For a ready-made program that reads XML archives, see TestInput.java . Sample scripts for running it on Win32 and UNIX are in xml.bat and xml , respectively.


Basic Elements

<java>
<?xml version="1.0" encoding="UTF-8" ?>
<java version="1.4.0" class="java.beans.XMLDecoder">
   
               ...objects go here...
</java>
            

The <java> element contains two informational attributes (not currently used by XMLDecoder): the version attribute, which records the version of the Java platform that was used to write the archive, and the class attribute, which specifies the class of the decoder for which the document was written. The objects that the archive contains make up the body of this element and appear in the order they will be returned by calls to the decoder's readObject method.


Objects

Objects are represented by the sequence of method calls that will be used to create them. Each element in the XML document represents a method call that either creates an object (an expression) or has a side effect on an object (a statement). Strings are treated as special kinds of expressions. Identifiers name objects so they can be referred to after their creation.


Strings

Strings are the atomic expressions of the XML document. The characters in a string form the body of an element with the <string> tag. For example, the string "Hello, World" is represented by the following XML code:

<string>Hello, World</string>

The '<' and ' &' characters are represented by the &lt; and &amp; escape sequences.


Expressions and Statements

<object><void><object><void>method

The class attribute can be used in <object> tags to specify a class as the target of a static method. Constructors are represented as static methods that have the name new.

When an expression or statement contains expressions, the contained expressions are used as arguments to the method represented by the outer expression or statement. For example, to create an instance of the JButton class we can write the following:

<object class="javax.swing.JButton" method="new">
  <string>Press me</string>
</object>
"Press me"JButton
new JButton("Press me");
new
<object class="javax.swing.JButton">
  <string>Press me</string>
</object>
<object class="javax.swing.JButton">
  <void method="setText">
    <string>Hello, world</string>
  </void>
</object>

JButton b = new JButton();
b.setText("Hello, world");
<void><void>

When an expression contains <void> tags (whether they denote expressions or statements) without class attributes, those <void> tags must follow all other tags in the expression. Each non- <void> expression is evaluated and the enclosing method is called with the results as arguments. The <void>-tagged statements and expressions are then applied, in order, to the result.

For example, consider the following expression:

<object class="javax.swing.JButton">
  <string>Press me</string>
  <void method="setName">
    <string>Greeting</string>
  </void>
</object>

JButton button1 = new JButton("Press me");
button1.setName("Greeting");

The ability to nest expressions and statements greatly reduces the number of identifiers that are needed to represent a given graph.


Identifiers

identifierid

The following expression creates an identifier button1, bound to an instance of the JButton class:

<object id="button1" class="javax.swing.JButton"/>
idref<object>button1
<object idref="button1"/>
<object class="javax.swing.JPanel">
  <void method="add">
    <object id="button1" class="javax.swing.JButton"/>
  </void>
  <void method="add">
    <object class="javax.swing.JLabel">
      <void method="setLabelFor">
        <object idref="button1"/>
      </void>
    </object>
  </void>
</object>

JPanel panel1 = new JPanel();
JButton button1 = new JButton();
JLabel label1 = new JLabel();
panel1.add(button1);
panel1.add(label1);
label1.setLabelFor(button1);

id<void>

For example, consider the following fragment:

<object class="java.util.Date">
  <void id="now" method="getTime"/>
</object>
now
long now = new Date().getTime();

Abbreviations

The preceding information is all you need to be able to write XML archives readable by XMLDecoder. To read all archives produced by XMLEncoder, however, you need to know about the abbreviations for primitives, null, Class objects, static constants, properties, indexes, and arrays.


Primitives

toStringcharStringcharCharacter

The following tags represent both the primitive types and their corresponding wrapper classes:

  • <boolean>
  • <byte>
  • <char>
  • <short>
  • <int>
  • <long>
  • <float>
  • <double>
<object class="java.lang.Integer">
  <string>123</string>
</object>
<int>123</int>
new Integer("123")        
123

Null

null<null>null
<null/>

Class Objects

<class>Class
<object class="java.lang.Class method="forName">
   <string>java.awt.event.ActionListener</string>
</object>
<class>java.awt.event.ActionListener</class>

which is equivalent to ActionListener.class.


Static Constants
(only in releases after 1.4.0 beta)

classfield
<void class="javax.swing.JTable" method="getField"> 
  <string>AUTO_RESIZE_OFF</string> 
  <void id="Integer0" method="get"> 
    <null/> 
  </void> 
</void> 
<object idref="Integer0"/> 

<object class="javax.swing.JTable" field="AUTO_RESIZE_OFF"/> 

which represents JTable.AUTO_RESIZE_OFF.


Properties

getsetpropertymethod

For expressions with methods whose names begin with "get", the property name is the method name with "get" removed and the next letter made lowercase. Thus

<void method="getText"/>
<void property="text"/>

For statements with methods whose names begin with "set", the property name is derived in a similar way. Thus

<void method="setText">
  <string>Hello, world</string>
</void>
<void property="text">
  <string>Hello, world</string>
</void>

Indexes

getset java.util.List indexmethod

For expressions with the method name get, the value of the index attribute is used as the argument. Thus

<void method="get">
  <int>3</int>
<void>
<void index="3"/>
Object o = aList.get(3);

For statements with the method name set, the value of the index attribute is prepended to the arguments of the enclosed body. Thus

<void index="3">
  <string>Hello, world</string>
</void>
<void method="set">
  <int>3</int>
  <string>Hello, world</string>
</void>
aList.set(3, "Hello, world")

Arrays

<array>classlengthid<array>
<array class="java.awt.Component" length="3"/>
Component[] a = new Component[3];
setgetjava.util.Listindex

Thus the expression

<array class="java.lang.String" length="3">
  <void index="1">
    <string>Hello, world</string>
  </void>
</array>
String[] s = new String[3];
s[1] = "Hello, world";

After the 1.4.0 beta release , you can omit the length attribute from an <array> tag and specify the values of entries directly, without using void tags. The length of the array is equal to the number of values specified. For example,

<array class="int">
  <int>123</int>
  <int>456</int>
</array>
int[] intArray = {123, 456};

The Top Level

<java>owner XMLDecoder XMLEncoder setOwnergetOwner
<?xml version="1.0" encoding="UTF-8" ?>
<java version="1.4.0" class="java.beans.XMLDecoder">
  <void id="myController" property="owner"/>
   
                     ...objects go here...
</java>
                  

The myController identifier can then by used throughout the body of the document to refer to the owner of the decoder. The following XML code creates a button that calls a no-argument doIt method on the owner when the button is pressed:

<?xml version="1.0" encoding="UTF-8" ?>
<java version="1.4.0" class="java.beans.XMLDecoder">
  <void id="myController" property="owner"/>
  <object class="javax.swing.JButton">
    <void method="addActionListener">
      <object class="java.beans.EventHandler" method="create">
        <class>java.awt.event.ActionListener</class>
        <object idref="myController"/>
        <string>doIt</string>
      </object>
    </void>
  </object>
</java>

It is also possible to use the top-level environment to produce side effects on the owner. Typically this is used to set property values on the owner to supply it with references to parts of a user interface so that the owner can manipulate the UI programatically. The following XML code creates a button and assigns it to the quitButton property of the owner by calling the setQuitButton method on the owner when the file is read.

<?xml version="1.0" encoding="UTF-8" ?>
<java version="1.4.0" class="java.beans.XMLDecoder">
  <void property="owner">
    <void property="quitButton">
       <object class="javax.swing.JButton"/>
    </void>
  </void>
</java>


DTD

XMLEncoder javabeans.dtd
Left Curve
Java SDKs and Tools
Right Curve
Left Curve
Java Resources
Right Curve
JavaOne Banner Java 8 banner (182)