CONTENTS | PREV | NEXT Java Remote Method Invocation


7.3.3 The Activatable Class

The Activatable class provides support for remote objects that require persistent access over time and that can be activated by the system. The class Activatable is the main API that developers need to use to implement and manage activatable objects. Note that you must first run the activation system daemon, rmid, before objects can be registered and/or activated.

package java.rmi.activation;
public abstract class Activatable
extends java.rmi.server.RemoteServer
{
protected Activatable(java.security.CodeSource source,
java.rmi.MarshalledObject data,
int port)
throws ActivationException, java.rmi.RemoteException;

protected Activatable(ActivationID id, int port)
throws java.rmi.RemoteException;

protected ActivationID getID();

public static RemoteStub register(ActivationDesc desc)
throws UnknownGroupException, ActivationException,
java.rmi.RemoteException;

public static void inactive(ActivationID id)
throws UnknownObjectException, ActivationException,
java.rmi.RemoteException;

public static void unregister(ActivationID id)
throws UnknownObjectException, ActivationException,
java.rmi.RemoteException;

public static ActivationID exportObject(Remote obj,
CodeSource source,
MarshalledObject data,
int port)
throws ActivationException,java.rmi.RemoteException;

public static RemoteStub exportObject(Remote obj,
ActivationID id,
int port)
throws java.rmi.RemoteException;
}
An implementation for an activatable remote object may or may not extend the class Activatable. A remote object implementation that does extend the Activatable class inherits the appropriate definitions of the hashCode and equals methods from the superclass java.rmi.server.RemoteObject. So, two remote object references that refer to the same Activatable remote object will be equivalent (the equals method will return true). Also, an instance of the class Activatable will be "equals" to the appropriate stub object for the instance (i.e., the Object.equals method will return true if called with the matching stub object for the implementation as an argument, and vice versa).


Activatable Class Methods

The first constructor for the Activatable class is used to register and export the object on a specified port (an anonymous port is chosen if port is zero). The object's CodeSource for downloading its class code is source, and its initialization data is data.

A concrete subclass of the Activatable class must call this constructor to register and export the object during initial construction. As a side-effect of activatable object construction, the remote object is both "registered" with the activation system and "exported" (on an anonymous port, if port is zero) to the RMI runtime so that it is available to accept incoming calls from clients.

The constructor throws ActivationException if registering the object with the activation system fails. RemoteException is thrown if exporting the object to the RMI runtime fails.

The second constructor is used to activate/export the object (with the ActivationID, id) on a specified port. A concrete subclass of the Activatable class must call this constructor when the object itself is activated via its special "activation" constructor whose parameters must be the following:

As a side-effect of construction, the remote object is "exported" to the RMI runtime (on the specified port) and is available to accept incoming calls from clients. The constructor throws RemoteException if exporting the object to the RMI runtime fails.

The getID method returns the object's activation identifier. The method is protected so that only subclasses can obtain and object's identifier. The object's identifier is used to report the object as inactive or to unregister the object's activation descriptor.

The register method registers, with the activation system, an object descriptor, desc, for an activatable remote object so that it can be activated on demand. This method is used to register an activatable object without having to first create the object. This method returns the RemoteStub for the activatable object so that it can be saved and called at a later time thus forcing the object to be created/activated for the first time. The method throws UnknownGroupException if the group identifier in desc is not registered with the activation system. ActivationException is thrown if the activation system is not running. Finally, RemoteException is thrown if the remote call to the activation system fails.

The inactive method is used to inform the system that the object with the corresponding activation id is currently inactive. If the object is currently active, the object is forcibly "unexported" from the RMI runtime so the that it can no longer receive incoming calls. This call informs this VM's ActivationGroup that the object is inactive; the group, in turn, informs its ActivationMonitor. After this call completes, subsequent activate requests to the activator will cause the object to reactivate. The method throws UnknownObjectException if the object is not known (it may already be inactive); an ActivationException is thrown if the group is not active; a RemoteException is thrown if the call informing the monitor fails.

The unregister method revokes previous registration for the activation descriptor associated with id. An object can no longer be activated via that id. If the object id is unknown to the activation system, a UnknownObjectException is thrown. If the activation system is not running an ActivationException is thrown. If the remote call to the activation system fails, then a RemoteException is thrown.

The first exportObject method may be invoked explicitly by an "activatable" object, that does not extend the Activatable class, in order to both a) register the object's activation descriptor, desc, constructed from the supplied source and data, with the activation system (so the object can be activated), and b) export the remote object, obj, on a specific port (if the port is zero, then an anonymous port is chosen). Once the object is exported, it can receive incoming RMI calls.

This exportObject method returns the activation identifier obtained from registering the descriptor, desc, with the activation system. If the activation group is not active in the VM, then ActivationException is thrown. If the object registration or export fails, then RemoteException is thrown.

This method does not need to be called if obj extends Activatable, since the first Activatable constructor calls this method.

The second exportObject method exports an "activatable" remote object (not necessarily of type Activatable) with the identifier, id, to the RMI runtime to make the object, obj, available to receive incoming calls. The object is exported on an anonymous port, if port is zero.

During activation, this exportObject method should be invoked explicitly by an "activatable" object, that does not extend the Activatable class. There is no need for objects that do extend the Activatable class to invoke this method directly; this method is called by the second constructor above (which a subclass should invoke from its special activation constructor).

This exportObject method returns the RemoteStub for the activatable object. If the object export fails, then the method throws RemoteException.


Constructing an Activatable Remote Object

In order for an object to be activated, the "activatable" object implementation class (whether or not it extends the Activatable class) must define a special public constructor that takes two arguments, its activation identifier of type ActivationID, and its activation data, a java.rmi.MarshalledObject, supplied in the activation descriptor used during registration. When an activation group activates a remote object inside its VM, it constructs the object via this special constructor (described in more detail below). The remote object implementation may use the activation data to initialize itself in a suitable manner. The remote object may also wish to retain its activation identifier, so that it can inform the activation group when it becomes inactive (via a call to the Activatable.inactive method).

The first constructor form for Activatable is used to both register and export an activatable object on a specified port. This constructor should be used when initially constructing the object; the second form of the constructor is used when re-activating the object.

A concrete subclass of Activatable must call the first constructor form to register and export the object during initial construction. This constructor first creates an activation descriptor (ActivationDesc) with the object's class name, the object's supplied source and data, and whose activation group is the default group for the VM. Next, the constructor registers this descriptor with the default ActivationSystem. Finally, the constructor exports the activatable object to the RMI runtime on the specific port (if port is zero, then an anonymous port is chosen) and reports the object as an activeObject to the local ActivationGroup. If an error occurs during registration or export, the constructor throws RemoteException. Note that the constructor also initializes its ActivationID (obtained via registration), so that subsequent calls to the protected method getID will return the object's activation identifier.

The second constructor form for Activatable is used to export the object on a specified port. A concrete subclass of Activatable must call the second constructor form when it is activated via the object's own "activation" constructor which takes two arguments:

This constructor only exports the activatable object to the RMI runtime on the specific port (if port is 0, then an anonymous port is chosen), it does not inform the ActivationGroup that the object is active, since it is the ActivationGroup that is activating the object and knows it to be active already.

The following is an example of a remote object interface, Server, and an implementation, ServerImpl, that extends the Activatable class:

package examples;
public interface Server extends java.rmi.Remote {
public void doImportantStuff()
throws java.rmi.RemoteException;
}

public class ServerImpl extends Activatable implements Server
{
// Constructor for initial construction, registration and export
public ServerImpl(CodeSource source, MarshalledObject data)
throws java.rmi.RemoteException
{
// register object with activation system, then
// export on anonymous port
super(source, data, 0);
}

// Constructor for activation and export; this constructor
// is called by the ActivationInstantiator.newInstance
// method during activation in order to construct the object.
public ServerImpl(ActivationID id, MarshalledObject data)
throws java.rmi.RemoteException
{
// call the superclass's constructor in order to
// export the object to the RMI runtime.
super(id, 0);
// initialize object (using data, for example)
}

public void doImportantStuff() { ... }
}
An object is responsible for exporting itself. The constructors for Activatable take care of exporting the object to the RMI runtime with the live reference type of a UnicastRemoteObject, so the object implementation extending Activatable does not need to worry about the detail of exporting the object explicitly (other than invoking the appropriate superclasses constructor). If an object implementation does not extend the class Activatable, the object must export the object explicitly via a call to one of the Activatable.exportObject static methods,.

In the following example, ServerImpl does not extend Activatable, but rather another class, so ServerImpl is responsible for exporting itself during initial construction and activation. The following class definition shows ServerImpl's initialization constructor and its special "activation" constructor and the appropriate call to export the object within each constructor:

package examples;
public class ServerImpl extends SomeClass implements Server
{
// constructor for initial creation
public ServerImpl(CodeSource source, MarshalledObject data)
throws ActivationException, java.rmi.RemoteException
{
// register and export the object
Activatable.exportObject(this, source, data, 0);
}

// constructor for activation
public ServerImpl(ActivationID id, MarshalledObject data)
throws java.rmi.RemoteException
{
// export the object
Activatable.exportObject(this, id, 0);
}

public void doImportantStuff() { ... }
}


Registering an Activation Descriptor Without Creating the Object

To register an activatable remote object with the activation system without first creating the object, the programmer can simply register an activation descriptor (an instance of the class ActivationDesc) for the object. An activation descriptor contains all the necessary information so that the activation system can activate the object when needed. An activation descriptor for an instance of the class examples.ServerImpl can be registered in the following manner (exception handling elided):

Server server;
ActivationDesc desc;
CodeSource source = new CodeSource("http://zaphod/source/", null);

MarshalledObject data = new MarshalledObject("some data");

desc = new ActivationDesc( "examples.ServerImpl", source, data);
server = (Server)Activatable.register(desc);

The register call returns a RemoteStub that is the stub for the examples.ServerImpl object and implements the same set of remote interfaces that examples.ServerImpl implements (i.e, the stub implements the remote interface Server). This stub object (above, cast and assigned to server) can be passed as a parameter in any method call expecting an object that implements the examples.Server remote interface.



CONTENTS | PREV | NEXT
Copyright © 1997 Sun Microsystems, Inc. All Rights Reserved.