Object Meta Data Example

The ORB compilers and runtime provide standard support for passing Java objects by-value. An argument to, or a return value from, a remote object can be any Java type that is serializable. This includes Java primitive types, and Java objects that implement the java.io.Serializable interface.

In this example we will ask a remote object for its meta-data Object. Using the meta-object's remote interface we will set/get arbitrary serializable java.lang.Objects as properties.

1 Component Interface

package metaData;
                                                                           
public interface Component extends java.rmi.Remote
{
    MetaData getMetaData() throws java.rmi.RemoteException;
}

2 MetaData Interface

package metaData;
                                                                           
import java.util.Enumeration;
import java.rmi.RemoteException;
                                                                           
/**
   The MetaData emulates the java.util.Dictionary interface.
 */
public interface MetaData extends java.rmi.Remote
{
    // returns the number of keys
    int size() throws RemoteException;
                                                                           
    // tests if there is currently no keys
    boolean isEmpty() throws RemoteException;
                                                                           
    // get the value for the given key
    Object get(Object key) throws RemoteException;
                                                                           
    // put the value with the given key
    Object put(Object key, Object value) throws RemoteException;
                                                                           
    // remove the key and its corresponding value
    Object remove(Object key) throws RemoteException;
                                                                           
    // get the enumeration of keys 
    Enumeration keys() throws RemoteException;
                                                                           
    // get the enumeration of values
    Enumeration elements() throws RemoteException;
}
Notice that several MetaData methods have plain java.lang.Object in their signatures. It is the programmer's responsibility to pass a java.io.Serializable object at runtime. Otherwise, the ORB will throw a class cast or marshalling exception. Of course, we could have made the signatures type specific. For example, we could have restricted the key above to always be a String.

3 Component Implementation

package metaData;
                                                                           
import java.rmi.RemoteException;
import javax.rmi.PortableRemoteObject;
                                                                           
public class ComponentImpl extends PortableRemoteObject implements Component
{
    private MetaData _metaData;
                                                                           
    ComponentImpl() throws RemoteException
    {
    |   _metaData = new MetaDataImpl();
    }
                                                                           
    public MetaData getMetaData() throws RemoteException
    {
    |   return _metaData;
    }
}

4 MetaData Implementation

We will use the standard java.util.Hashtable for implementing the Meta Data. Notice that since the Hashtable's enumerator is not Serializable, we will need to write our own version.
package metaData;
                                                                           
import java.io.Serializable;
                                                                           
import java.rmi.RemoteException;
import javax.rmi.PortableRemoteObject;
                                                                           
import java.util.Hashtable;
import java.util.Enumeration;
                                                                           
public class MetaDataImpl extends PortableRemoteObject implements MetaData
{
    private Hashtable _metaData;
                                                                           
    MetaDataImpl() throws RemoteException
    {
    |   _metaData = new Hashtable();
    }
                                                                           
    public int size() throws RemoteException
    {
    |   return _metaData.size();
    }
                                                                           
    public boolean isEmpty() throws RemoteException
    {
    |   return _metaData.isEmpty();
    }
                                                                           
    public Object get(Object key) throws RemoteException
    {
    |   return _metaData.get(key);
    }
                                                                           
    public Object put(Object key, Object value) throws RemoteException
    {
    |   return _metaData.put(key, value);
    }
                                                                           
    public Object remove(Object key) throws RemoteException
    {
    |   return _metaData.remove(key);
    }
                                                                           
    public Enumeration keys() throws RemoteException
    {
    |   synchronized (_metaData) {
    |   |   return new MetaDataEnumerator(_metaData.keys(), size());
    |   }
    }
                                                                           
    public synchronized Enumeration elements() throws RemoteException
    {
    |   synchronized (_metaData) {
    |   |   return new MetaDataEnumerator(_metaData.elements(), size());
    |   }
    }
}
                                                                           
class MetaDataEnumerator implements Enumeration, Serializable
{
    private int      _cursor;
    private Object[] _elements;
                                                                           
    MetaDataEnumerator(Enumeration e, int size)
    {
    |   _elements = new Object[size];
    |                                                                      
    |   int i=0;
    |   while (e.hasMoreElements()) {
    |   |   _elements[i++] = e.nextElement();
    |   }
    |                                                                      
    |   _cursor = 0;
    }
                                                                           
    public boolean hasMoreElements()
    {
    |   return _cursor != _elements.length;
    }
                                                                           
    public Object nextElement()
    {
    |   return _elements[_cursor++];
    }
}

5 MetaData Server

The server creates the ORB, creates a Java RMI servant, writes out it's stringified object reference, and then waits for invocations. Notice, that since HelloImpl is not a CORBA object (does not implement org.omg.CORBA.Object,) you need to first get its stub/object reference before using the object_to_string method.
package metaData;
                                                                           
import util.Util;
                                                                           
import org.omg.CORBA.ORB;
import org.omg.CORBA.Object;
                                                                           
import javax.rmi.PortableRemoteObject;
                                                                           
public class Server
{
    public static void main(String[] args)
    {
    |   try {
    |   |                                                                  
    |   |   // create the jBroker ORB
    |   |   ORB orb = ORB.init(args, null);
    |   |                                                                  
    |   |   // create a servant
    |   |   Component component = new ComponentImpl();
    |   |                                                                  
    |   |   // create a stringified object reference
    |   |   String ior = orb.object_to_string((Object) PortableRemoteObject.
    |   |       toStub(component));
    |   |                                                                  
    |   |   // write the stringified object reference
    |   |   Util.writeIOR(ior, "ior", true);
    |   |                                                                  
    |   |   // wait for invocations
    |   |   System.out.println("waiting for invocations ...");
    |   |   orb.run();
    |   |                                                                  
    |   } catch (Exception ex) {
    |   |   ex.printStackTrace();
    |   }
    }
}

6 MetaData Client

The client creates the ORB, reads the stringified object reference of the Component object, and casts it to the Component type. It then gets the MetaData interface from the Component and sets and gets meta data on it.

Notice, that java.lang.String and the java.util.Vector are JDK classes that are already Serializable. The Enumeration is the Serializable object that we wrote in the above section.

package metaData;
                                                                           
import util.Util;
import org.omg.CORBA.ORB;
import java.util.Vector;
import java.util.Enumeration;
import javax.rmi.PortableRemoteObject;
                                                                           
public class Client
{
    public static void main(String[] args)
    {
    |   try {
    |   |                                                                  
    |   |   // create the jBroker ORB
    |   |   ORB orb = ORB.init(args, null);
    |   |                                                                  
    |   |   // read the stringified object reference
    |   |   String ior = Util.readIOR("ior");
    |   |                                                                  
    |   |   // narrow the stringified object
    |   |   Component component = (Component) orb.string_to_object(ior);
    |   |                                                                  
    |   |   // get the component's meta-data interface
    |   |   MetaData metaData = component.getMetaData();
    |   |                                                                  
    |   |   // add lifecycle and timeout meta data
    |   |   metaData.put("lifecycle", "transient");
    |   |   metaData.put("timeout", new Integer(5000));
    |   |                                                                  
    |   |   // set the access control list (ACL)
    |   |   Vector acl = new Vector();
    |   |   acl.addElement("user1");
    |   |   acl.addElement("user2");
    |   |   metaData.put("acl", acl);
    |   |                                                                  
    |   |   // enumerate the meta data keys
    |   |   System.out.print("Component Keys: ");
    |   |   Enumeration keys = metaData.keys();
    |   |   while (keys.hasMoreElements()) {
    |   |   |   System.out.print(keys.nextElement() + ", ");
    |   |   }
    |   |   System.out.println();
    |   |                                                                  
    |   |   // print out the Component ACL
    |   |   System.out.print("Component ACL : ");
    |   |   acl = (Vector) metaData.get("acl");
    |   |   for (int i=0; i < acl.size(); i++) {
    |   |   |   System.out.print(acl.elementAt(i) + ((i==(acl.size()-1)) ?
    |   |   |       "\n" : ", "));
    |   |   }
    |   |                                                                  
    |   } catch (Exception ex) {
    |   |   ex.printStackTrace();
    |   }
    }
}
Copyright © 2000-2003, Novell, Inc. All rights reserved.