Table of Contents

Naming and Managing Objects

Why name objects?

Thus far we have discussed how to work with sessions and transactions, before we can proceed to some practical aspects of working with Facets we need to discuss the naming of objects. Earlier on we touched on the fact that Facets works out which objects to persist by ascertaining whether an object is reachable by an object that is already persistent. We need to be able to insert root objects into the repository and make them persistent.

A persistent root object, is an object that exists in the repository but is not referred to or contained by any other object that is persistent in the repository. Root objects are important, since typically they are the means by which we navigate to other objects that are of interest to us. In the game example we have been using, we would typically like to find out which games are currently defined, so that a player can join them. We can achieve this by creating a GameManager object and making this a root persistent object. Naming a root object allows us to store an object in such a way that we can retrieve a reference to it at any time merely by knowing it's name. Naming an object therefore is the primary mechanism for making a root object peristent.

While we place emphasis on the fact that root objects are typically the ones that are named, any object in Facets can be placed into a namespace with a name, and therefore can be named, however it does not make sense to name each and every object in the repository, since the overhead would be far too high. For this reason then, you should consider carefully how you wish to access your objects, and the typical types of navigation that will take place, since this will dictate how you should name and hence "publish" your root objects. You may also find that sometimes you may wish to name not only your root objects, but also other objects of importance for quick retrieval.

Namespaces in Facets

Facets implements the Java Naming and Directory Interface (JNDI) to allow the management and naming of objects in the repository. You may wish to think of the namespaces in Facets as large efficient hashtables that allow keyed access to objects of importance. Namespaces in Facets obey all of the rules that you may be familiar with such as the ability to create nested namespaces, and to navigate through these. We have used the term namespace and context interchageably in this discussion, however there is a difference between a namespace and a context, in Facets a namespace provides read-only access to a Context, whereas a Context provides full read write access. The most important operations on Context in Facets are

  1. bind

    this operation connects the name (or key) to the object
  2. rebind

    occasionally it may be necessary to replace the object associated with a particular name, this operation effectively replaces the named object with the new object in a single a operation
  3. remove

    does exactly what it says, it removes the specified binding

Because the reachability of objects in Facets is the attribute that defines whether an object will be persisted or not, Facets requires one context that is known as the "root context" which in turn will contain all the other objects that are reachable. This is effectively a single absolute context which is the root of ALL objects in the Facets repository. This root context can be obtained by sending the message getInitialContext to a session object.

One important thing to remember about Facets namespaces is that because they are persistent and are potentially accessed concurrently by more than one VM or thread, they have to be transactional in nature. For this reason all changes made to a Namespace must be made in the context of a transaction that follows the normal transactional semantics.

Working with Namespaces

In order to make the nature and use of namespaces clear, we are going to use some of the classes from the Game Application and create an instance of the GameManager and store it in the repository.

Figure : Root Context after executing sample code

The piece of code shown below is extracted from the main method of the GameManager classes. This method is used to install an instance of the GameManager in the Facets repository. Note the required imports at the top of the example:

import com.gemstone.persistence.collections.*;
import com.gemstone.persistence.*;
import com.gemstone.persistence.naming.*;
import javax.naming.*;
import javax.jdo.*;
GameManager		manager;
GsSession		session;
SessionFactory		factory;
Context			context;

System.out.println("installing GameManager...");
//
// retrieve the singleton SessionFactory instance
//
factory = SessionFactory.getInstance();
if (factory == null) {
	System.err.println("unable to retrieve instance of SessionFactory");
	System.exit(5);
}
//
// now attempt to retrieve a session
//
session = null;
try {
	session = factory.getSession();
} catch  (Exception exception) {
	System.err.println("exception while retrieving a session");
	exception.printStackTrace();
	factory.close();
	System.exit(5);
}
//
// now create the GameManager instance and store it
// in the default namespace for this session
//
try { 
        manager = new GameManager();
	context = session.getInitialContext();
	session.begin();
	context.bind("GameManager",manager);
	session.commit();
	System.out.println("successfully installed GameManager instance");
} catch  (GsTransactionInProgressException inProgress) {
	System.out.println("unable to start a transaction");
	inProgress.printStackTrace();
} catch  (Exception exception) {
	session.abort();
	System.err.println("unable to commit the installation transaction");
	exception.printStackTrace();
}
//
// return the session to the factory
// and shutdown the factory for this VM
//
session.close();
factory.close();
©2005 GemStone Systems, Inc.