CONTENTS | PREV | NEXT | Java Remote Method Invocation |
In order to make a remote object that can be accessed via an activation identifier over time, a developer needs to:
An activation descriptor (ActivationDesc
) can be registered in one of several ways:
For a specific object, only one of the above methods should be used to register the object for activation. See the section below on "Constructing an Activatable Remote Object" for examples on how to implement activatable objects.
7.3.1 The
ActivationDesc
ClassAnActivationDesc
contains the information necessary to activate an object. It contains the object's activation group identifier, the class name for the object, a codebase path (or URLs) from which the object's code can be loaded, and aMarshalledObject
that may contain object-specific initialization data used during each activation.A descriptor registered with the activation system is consulted (during the activation process) to obtain information in order to re-create or activate an object. The
MarshalledObject
in the object's descriptor is passed as the second argument to the remote object's constructor for the object to use during activation.
package java.rmi.activation;public final class ActivationDesc implements java.io.Serializable { public ActivationDesc(String className, String codebase, java.rmi.MarshalledObject data) throws ActivationException; public ActivationDesc(String className, String codebase, java.rmi.MarshalledObject data, boolean restart) throws ActivationException; public ActivationDesc(ActivationGroupID groupID, String className, String codebase, java.rmi.MarshalledObject data, boolean restart); public ActivationDesc(ActivationGroupID groupID, String className, String codebase, java.rmi.MarshalledObject data); public ActivationGroupID getGroupID(); public String getClassName(); public String getLocation(); public java.rmi.MarshalledObject getData() public boolean getRestartMode(); }
The first constructor forActivationDesc
constructs an object descriptor for an object whose class is className, that can be loaded from codebase path, and whose initialization information, in marshalled form, is data. If this form of the constructor is used, the object's group identifier defaults to the current identifier forActivationGroup
for this JVM. All objects with the sameActivationGroupID
are activated in the same JVM. If the current group is inactive or a default group cannot be created, anActivationException
is thrown. If the groupID isnull
, anIllegalArgumentException
is thrown.
Note - As a side-effect of creating anActivationDesc
, if anActivationGroup
for this JVM is not currently active, a default one is created. The default activation group uses thejava.lang.SecurityManager
as a security manager and upon reactivation will set the properties in the activated group's JVM to be the current set of properties in the JVM. If your application needs to use a different security manager, it must set the group for the JVM before creating a defaultActivationDesc
. See the methodActivationGroup.createGroup
for details on how to create anActivationGroup
for the JVM.
The second constructor forActivationDesc
constructs an object descriptor in the same manner as the first constructor except an additional parameter, restart, must be supplied. If the object requires restart service, meaning that the object will be restarted automatically when the activator is restarted (as opposed to being activated lazily upon demand), restart should betrue
. If restart isfalse
, the object is simply activated upon demand (via a remote method call).The third constructor for
ActivationDesc
constructs an object descriptor for an object whose group identifier is groupID, whose class name is className that can be loaded from the codebase path, and whose initialization information is data. All objects with the same groupID are activated in the same JVM.The fourth constructor for
ActivationDesc
constructs an object descriptor in the same manner as the third constructor, but allows a restart mode to be specified. If an object requires restart service (as defined above), restart should betrue
.The
getGroupID
method returns the group identifier for the object specified by the descriptor. A group provides a way to aggregate objects into a single Java virtual machine.The
getClassName
method returns the class name for the object specified by the activation descriptor.The
getLocation
method returns the codebase path from where the object's class can be downloaded.The
getData
method returns a "marshalled object" containing initialization (activation) data for the object specified by the descriptor.The
getRestartMode
method returnstrue
if the restart mode is enabled for this object, otherwise it returns false.
7.3.2 The
ActivationID
ClassThe activation protocol makes use of activation identifiers to denote remote objects that can be activated over time. An activation identifier (an instance of the classActivationID
) contains several pieces of information needed for activating an object:
An activation identifier for an object can be obtained by registering an object with the activation system. Registration is accomplished in a few ways (also noted above):
package java.rmi.activation;public class ActivationID implements java.io.Serializable { public ActivationID(Activator activator); public Remote activate(boolean force) throws ActivationException, UnknownObjectException, java.rmi.RemoteException; public boolean equals(Object obj); public int hashCode(); }
The constructor forActivationID
takes a single argument, activator, that specifies a remote reference to the activator responsible for activating the object associated with this activation identifier. An instance ofActivationID
is globally unique.The
activate
method activates the object associated with the activation identifier. If the force parameter is true, the activator considers any cached reference for the remote object as stale, thus forcing the activator to contact the group when activating the object. If force is false, then returning the cached value is acceptable. If activation fails,ActivationException
is thrown. If the object identifier is not known to the activator, then the method throwsUnknownObjectException
. If the remote call to the activator fails, thenRemoteException
is thrown.The
equals
method implements content equality. It returnstrue
if all fields are equivalent (either identical or equivalent according to each field'sObject.equals
semantics). If p1 and p2 are instances of the classActivationID
, thehashCode
method will return the same value ifp1.equals(p2)
returnstrue
.
7.3.3 The
Activatable
ClassTheActivatable
class provides support for remote objects that require persistent access over time and that can be activated by the system. The classActivatable
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(String codebase, java.rmi.MarshalledObject data, boolean restart, int port) throws ActivationException, java.rmi.RemoteException; protected Activatable(String codebase, java.rmi.MarshalledObject data, boolean restart, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws ActivationException, java.rmi.RemoteException; protected Activatable(ActivationID id, int port) throws java.rmi.RemoteException; protected Activatable(ActivationID id, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws java.rmi.RemoteException; protected ActivationID getID(); public static Remote register(ActivationDesc desc) throws UnknownGroupException, ActivationException, java.rmi.RemoteException; public static boolean 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, String codebase, MarshalledObject data, boolean restart, int port) throws ActivationException, java.rmi.RemoteException; public static ActivationID exportObject(Remote obj, String codebase, MarshalledObject data, boolean restart, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws ActivationException, java.rmi.RemoteException; public static Remote exportObject(Remote obj, ActivationID id, int port) throws java.rmi.RemoteException; public static Remote exportObject(Remote obj, ActivationID id, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws java.rmi.RemoteException; public static boolean unexportObject(Remote obj, boolean force) throws java.rmi.NoSuchObjectException; }
An implementation for an activatable remote object may or may not extend the classActivatable
. A remote object implementation that does extend theActivatable
class inherits the appropriate definitions of thehashCode
andequals
methods from the superclassjava.rmi.server.RemoteObject
. So, two remote object references that refer to the sameActivatable
remote object will be equivalent (theequals
method will return true). Also, an instance of the classActivatable
will be "equals" to the appropriate stub object for the instance (i.e., theObject.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 theActivatable
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 URL path for downloading its class code is codebase, and its initialization data is data. If restart istrue
, the object will be restarted automatically when the activator is restarted and if the group crashes. If restart isfalse
, the object will be activated on demand (via a remote method call to the object).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 the same as the first
Activatable
constructor but allows the specification of the client and server socket factories used to communicate with this activatable object. See the section in about "RMI Socket Factories" for details.The third constructor is used to activate and export the object (with the
ActivationID
, id) on a specified port. A concrete subclass of theActivatable
class must call this constructor when the object itself is activated via its special "activation" constructor whose parameters must be:
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 throwsRemoteException
if exporting the object to the RMI runtime fails.The fourth constructor is the same as the third constructor, but allows the specification of the client and server socket factories used to communicate with this activatable object.
The
getID
method returns the object's activation identifier. The method is protected so that only subclasses can obtain an 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 theRemote
stub 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 throwsUnknownGroupException
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 known to be active, the object is unexported from the RMI runtime (only if there are no pending or executing calls) so the that it can no longer receive incoming calls. This call also informs this JVM'sActivationGroup
that the object is inactive; the group, in turn, informs itsActivationMonitor
. If the call completes successfully, subsequent activate requests to the activator will cause the object to reactivate. Theinactive
method returnstrue
if the object was successfully unexported (meaning that it had no pending or executing calls at the time) and returnsfalse
if the object could not be unexported due to pending or in-progress calls. The method throwsUnknownObjectException
if the object is not known (it may already be inactive); anActivationException
is thrown if the group is not active; aRemoteException
is thrown if the call informing the monitor fails. The operation may still succeed if the object is considered active but has already unexported itself.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, anUnknownObjectException
is thrown. If the activation system is not running, anActivationException
is thrown. If the remote call to the activation system fails, then aRemoteException
is thrown.The first
exportObject
method may be invoked explicitly by an "activatable" object that does not extend theActivatable
class, in order to both
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 JVM, thenActivationException
is thrown. If the object registration or export fails, thenRemoteException
is thrown.This method does not need to be called if obj extends
Activatable
, since the firstActivatable
constructor calls this method.The second
exportObject
method is the same as the first except it allows the specification of client and server socket factories used to communicate with the activatable object.The third
exportObject
method exports an "activatable" remote object (not necessarily of typeActivatable
) 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 theActivatable
class. There is no need for objects that do extend theActivatable
class to invoke this method directly; this method is called by the third constructor above (which a subclass should invoke from its special activation constructor).This
exportObject
method returns theRemote
stub for the activatable object. If the object export fails, then the method throwsRemoteException
.The fourth
exportObject
method is the same as the third but allows the specification of the client and server socket factories used to communicate with this activatable object.The
unexportObject
method makes the remote object, obj, unavailable for incoming calls. If the force parameter istrue
, the object is forcibly unexported even if there are pending calls to the remote object or the remote object still has calls in progress. If the force parameter isfalse
, the object is only unexported if there are no pending or in progress calls to the object. If the object is successfully unexported, the RMI runtime removes the object from its internal tables. Removing the object from RMI use in this forcible manner may leave clients holding stale remote references to the remote object. This method throwsjava.rmi.NoSuchObjectException
if the object was not previously exported to the RMI runtime.
Constructing an Activatable Remote Object
In order for an object to be activated, the "activatable" object implementation class (whether or not it extends theActivatable
class) must define a special public constructor that takes two arguments, its activation identifier of typeActivationID
, and its activation data, ajava.rmi.MarshalledObject
, supplied in the activation descriptor used during registration. When an activation group activates a remote object inside its JVM, 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 theActivatable.
inactive
method).The first and second constructor forms for
Activatable
are used to both register and export an activatable object on a specified port. This constructor should be used when initially constructing the object; the third form of the constructor is used when re-activating the object.A concrete subclass of
Activatable
must call the first or second 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 codebase and data, and whose activation group is the default group for the JVM. Next, the constructor registers this descriptor with the defaultActivationSystem
. 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 anactiveObject
to the localActivationGroup
. If an error occurs during registration or export, the constructor throwsRemoteException
. Note that the constructor also initializes itsActivationID
(obtained via registration), so that subsequent calls to the protected methodgetID
will return the object's activation identifier.The third constructor form for
Activatable
is used to export the object on a specified port. A concrete subclass ofActivatable
must call the third 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 theActivationGroup
that the object is active, since it is theActivationGroup
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 theActivatable
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(String codebase, MarshalledObject data) throws ActivationException, java.rmi.RemoteException { // register object with activation system, then // export on anonymous port super(codebase, data, false, 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 forActivatable
take care of exporting the object to the RMI runtime with the live reference type of aUnicastRemoteObject
, so the object implementation extendingActivatable
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 classActivatable
, the object must export the object explicitly via a call to one of theActivatable.exportObject
static methods.In the following example,
ServerImpl
does not extendActivatable
, but rather another class, soServerImpl
is responsible for exporting itself during initial construction and activation. The following class definition showsServerImpl
'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(String codebase, MarshalledObject data) throws ActivationException, java.rmi.RemoteException { // register and export the object Activatable.exportObject(this, codebase, data, false, 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 classActivationDesc
) 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 classexamples.ServerImpl
can be registered in the following manner (exception handling elided):
Server server;
ActivationDesc desc;
String codebase = "http://zaphod/codebase/";MarshalledObject data = new MarshalledObject("some data");
desc = new ActivationDesc( "examples.ServerImpl", codebase, data);
server = (Server)Activatable.register(desc);The
register
call returns aRemote
stub that is the stub for theexamples.ServerImpl
object and implements the same set of remote interfaces thatexamples.ServerImpl
implements (i.e, the stub implements the remote interfaceServer
). This stub object (above, cast and assigned to server) can be passed as a parameter in any method call expecting an object that implements theexamples.Server
remote interface.
CONTENTS | PREV | NEXT
Copyright © 1997-2001 Sun Microsystems, Inc. All Rights Reserved.