Table of Contents

Retrieving Objects

Looking up Named Objects

In module 9 (Naming and Managing Objects) we demonstrated how to bind an object in a Context so that it could later be retrieved by name. In this module we will show how to retrieve a named object from a Context and how to use that retrieved object to navigate to it's contents. The use of retrieved objects is often confusing to novice Facets users, because it is so simple. Many users of Facets are accustomed to the complex machinations that have to be used when using an RDBMS to store objects, and the sheer simplicity of the Facets approach is confusing.

In the example below, we are going to retrieve a collection of objects that we created when we installed the GameManager, and then we are going to store a reference to the retrieved collection in the root context under another name. This allows us to rapidly access the collection without having to navigate from the GameManager (although that is a perfectly acceptable manner in which to access the said collection). The GameManager class is defined as follows

	public class GameManager {
	    protected CuHashMap   games;
	    protected CuHashMap   registeredPlayers;
		...
	}

In the code snippet that we used in module 9, we created an instance of the GameManager and saved it away under the name "GameManager". First we obtain a session as we usually do from the SessionFactory

	GameManager     manager;
	GsSession       session;
	SessionFactorY  factory;
	Context         context;
	CuHashMap       players;
	
	System.out.println("publishing Registered Players...");
	
	//
	// retrieve the singleton SessionFactory instance
	//
	factory = SessionFactory.getInstance();
	if (factory == null) {
	    System.err.println("unable to retrieve instance of SessionFactory");
	    return;
	}
	
	//
	// 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();
	    return;
	}

You will remember from the module on Naming Objects after we inserted the GameManager into the Root Context, it looked as follows:


Figure : Root Context after binding an instance of GameManager to the name "GameManager"

We now have a session that we can work with, firstly we retrieve the instance of the GameManager that we stored away in the example in module 9, then we ask it to give us the collection that it contains with the registered players, and then we bind that object (i.e. the CuHashMap of registered players) into the naming context under the name "RegisteredPlayers". It is worth noting that when we store the CuHashMap of players in the context under the name "RegisteredPlayers" we are not storing a copy of the CuHashMap, we are actually storing a reference to the same object that is contained in the GameManager. In other words, if we add a player by retrieving the CuHashMap through a lookup of "RegisteredPlayers", we add it to the same CuHashMap that is an instance variable of GameManager, since they are the SAME CuHashMap. Note also that we abort the session prior to performing the lookup, to ensure that we have an up-to-date view of the repository.

	try {
	    session.abort();
	    context = session.getInitialContext();

	    manager = (GameManager)context.lookup("GameManager");
	    players = manager.registeredPlayers();
		
	    session.begin();
	    context.bind("RegisteredPlayers",players);
	    session.commit();
	    System.out.println("successfully published registered players");
		
	} catch  (NamingException namingException)	{
	    System.err.println("could not find GameManager instance");
	    namingException.printStackTrace();
	} 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();


Figure : Root Context after binding players to "RegisteredPlayers"


Using Retrieved Objects

Notice from the above code how simple it is to use a retrieved object, there are no special preparations required to make the object ready for use, no loading or other commands are required. Objects retrieved from the Facets Naming Service are complete in-memory Java objects and will automatically retrieve as much of the internal state as is necessary for their correct functioning. Even if your object tree is dozens or even hundreds of layers deep, Facets will transparently manage the loading of all subsequent objects in the tree for you. This makes Facets incredibly easy to use, and makes coding with Facets very simple and quick. To illustrate this point, consider the GameManager example above, once we had retrieved the GameManager instance, and cast it to the correct type, we could perform any action on it that we could normally perform on any other Java object, navigating to any depth. for example, lets say a Player object looked as follows:

    public class Player {
	protected String name;
	protected Address address;
	...
and lets say an Address object looked as follows:
    public class Address {
	protected String ipAddress;
	protected String physicalAddress[5];
	...
then we could issue the following command to a retrieved GameManager object:
	gameManager.registeredPlayers().get("Joe")).address().physicalAddress[0];

Facets will automatically figure out that it needs to load the appropriate player from the repository, and populate the instance variables contained in that instance of Player.

Caching Persistent Objects for later re-use

It was stated previously that Facets associates a session with a thread, and hence with a VM, for this reason the objects that are looked up and retrieved from within the Facets repository are also associated with that session and hence that thread. This means that persistent objects can not be freely stored away in an in-memory instance variable for later use, if the session is closed, or the thread ends. This is not a problem though, since Facets provides a special mechanism for storing references to persistent objects in such a way that they can very rapidly be accessed once they are needed. To achieve the same effect we use an instance of the class "ExportableSharedObjRef". Instances of this class store a reference to a persistent object in a session, thread and even machine independent way, and they can be used to cache persistent object references or even for passing refeerences to persistent obejcts between threads. The code below shows how a class can retrieve and cache an instance of GameManager between invocations of various methods.package
package com.gemstone.examples.maze;

import com.gemstone.persistence.collections.*;
import com.gemstone.persistence.*;
import com.gemstone.persistence.naming.*;
import javax.naming.*;
import javax.jdo.*;

public class GamePlayer {

    protected ExportableSharedObjRef managerReference;

    //
    // create an instance of the GamePlayer object,
    // retrieve and cache a reference to the GameManager object
    // for later use
    //
    public GamePlayer() {
        GameManager    manager;
        GsSession      session;
        SessionFactory factory;
        Context        context;
		
        //
        // retrieve the singleton SessionFactory instance
        //
        factory = SessionFactory.getInstance();
		
        if (factory == null) {
            System.err.println("unable to retrieve singleton instance of SessionFactory");
            return;
        }
	    
        //
        // 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();
            return;
        }
		
        //
        // now retrieve the GameManager instance and convert it to 
        // an ExportableSharedObjRef for storage in an instance
        // variable for later use
        //
        try {
            session.abort();
            context = session.getInitialContext();
            manager = (GameManager)context.lookup("GameManager");
            managerReference = new ExportableSharedObjRef(manager);
        } catch (NamingException namingException) {
            System.err.println("could not find GameManager instance");
            namingException.printStackTrace();
        } catch  (Exception exception) {
            session.abort();
            exception.printStackTrace();
        }
		
        //
        // return the session to the factory
        //
        session.close();
    }
	
    //
    // Use the cached reference to the GameManager to access the
    // available games and see if there is a game with the given name
    //
    public boolean doesGameWithNameExist(String name) {
        GameManager    manager;
        GsSession      session;
        SessionFactory factory;
        Context        context;
        
        //
        // retrieve the singleton SessionFactory instance
        //
        factory = SessionFactory.getInstance();
		
        if (factory == null) {
            System.err.println("unable to retrieve instance of SessionFactory");
            return(false);
        }
        
        //
        // 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();
            return(false);
        }	
        
        //
        // now convert the reference to the GameManager into a real game
        // manager
        //
        try {
            session.abort();
            manager = (GameManager)managerReference.get(session);
            return(manager.containsGameWithName(name));
        } catch  (Exception exception) {
            session.abort();
            exception.printStackTrace();
        } finally  {
            session.close();
        }
		
        return(false);
    }
}
©2005 GemStone Systems, Inc.