Java™ Object Database 

25 July 2000


 Home

 Download

 API Javadoc

 Release History

 Feedback

 License

 XL2-INTEREST
 Subscribe by email.
 Subscribe on the web.

 
 Getting Started
Understand These Technologies Java Object Serialization
Serialization converts an object and all objects referentially reachable from it (called a graph) into a single stream of bytes.  As wonderful as it is, it was not designed to scale to large collections of objects:
  • Accessing a serialized object requires the entire graph be loaded into memory.
  • Modifing an already serialized object requires the entire graph be reserialized.
XL2 Scales Object Serialization
XL2 overcomes these limitions with persistent references.  XL2References terminate serialization of a graph, but resurrect referents across process boundries.  An XL2 database is a network of serialized graphs:
  • Accessing an object from an XL2 database does not require the entire database be loaded into memory.
  • Modifying and saving an object from an XL2 database only requires the modified graph to be reserialized.
Designing XL2 Storable Objects
All rules of Java object serialization apply.

Instead of declaring fields with their class type, declare them as XL2References.  Not all object fields need to be declared this way, it is a design consideration unique to each object model.

Lets define an XL2 storable Person object.

public class Person implements java.io.Serializable {
     //fields
     protected String NameString = null;
     protected xl2.odb.XL2Reference Mother = null;
     protected xl2.odb.XL2Reference Father = null;
     protected xl2.odb.XL2Reference[] Children = null;
     //constructor
     public Person() {}
     }//class

Mother, Father and Children were declared using XL2Reference instead of Person.  When a Person is loaded into memory, it's Mother, Father and Children are not loaded until calling get() on their XL2Reference.  Furthermore, modifications to a Person's NameString do not require their Mother, Father or any Children to be reserialized.

Working with XL2References
When a XL2Reference is modified (XL2Reference.set(Object)), the XL2Reference must be reserialized along with it's encapsulating graph.  The XL2Reference must know the root object of it's encapsulating graph for this to happen.  This parent root is specified during construction of the XL2Reference.

A graph root is a first class object.  Objects embedded within a graphs are second class objects.  XL2References only point to first class objects and are only constructed with first class parents.

Lets implement the Mother accessor methods of the Person object to demonstrate XL2Reference usage.

     public Person getMother() {
          if (Mother == null) return null;
          return (Person) Mother.get();
          }

     public void setMother(Person person) {
          if (Mother == null)
               Mother = new xl2.odb.XL2Reference(this);
          Mother.set(person);
          }

Critically Important
To clear an XL2Reference, set the referent to null.  For example:
     this.Mother.set(null);
     somePerson.Father.set(null);

But never reassign an XL2Reference field.  This will result in a persistent garbage leak.  Given the Person object, the following kinds of statements should never be written:
     this.Mother = null;
     somePerson.Father = anotherPerson.Father;

Working with Other Types
Not all fields will be XL2References.  Programmers are responsible for notifying the current transaction of second class object and primitive field changes.  This is achieved by locking the parent first class object (the root of the encapsulating graph) in the current Transaction.  Let us implement the Person NameString accessors to demonstrate this.

     public String getName() {
          return NameString;
          }

     public void setName(String name) {
          xl2.odb.XL2TransactionMgr.lock(this,Transaction.WRITE);
          NameString = name;
          }

Notice the lock operation occurs before changing the field in setName(String). Always attempt to lock the parent first class object first before changing anything.  If the person being modified is already locked by another Transaction, or there is no Transaction, a LockNotGrantedException will be thrown.  If an exception is thrown the NameString field will not be modified and there will be no concurrently issues.

Databases and Transactions
Databases are composed of several files so they are created and opened with their parent directory name.  Once a database is opened, transactions are acquired from the database instance.

XL2Database db = new XL2Database();
db.open("c:\xl2demo",db.OPEN_READ_WRITE);
Transaction t = db.newTransaction();
t.begin();
//...
Perhaps the only tricky part is remembering to join the current thread to the appropriate transaction.  This shouldn't be a problem unless a thread works with multiple transactions concurrently or a transaction in a web app spans multiple requests.  The primary reason for joining threads to transactions is so XL2References can "find" their database.  XL2TransactionMgr provides the method for finding the current transaction for the calling thread:
XL2TransactionMgr.currentTransaction();
Examples
Included with the distribution is an example subdirectory.  In it are examples using the Person object.  See the README.txt file in that directory.

Warning

  • Databases must be explicitly closed prior to JDK 1.3.
  • XL2 can not recover from abnormal VM termination (crashes) if any transactions are in the process of committing (this includes gc & compaction which are transactional).  Back up your database directory often until this is resolved (and it will be).
 
Sun, Sun Microsystems, the Sun Logo and Java are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.