Activatable
This tutorial describes how to implement an activatable remote
object by extending the class
java.rmi.activation.Activatable
. This tutorial uses a
Setup
program (described in the tutorial Using Activation: the Setup
Program)
that registers information about an activatable remote object with
the Java Remote Method
Invocation (Java RMI) activation system daemon (rmid
)
and then binds a stub for that remote object in an
rmiregistry
so that clients can look it up. You may
want to read that tutorial before this one.
This tutorial has the following steps:
Setup
programThe files needed for this tutorial are:
MyRemoteInterface.java
- a simple remote interfaceExtendsActivatable.java
- an "activatable" implementation of the remote
interfaceClient.java
- a
client that uses the remote interfaceclient.policy
-
the security policy file for the clientThere are a few basic ways to implement an activatable remote
object. This tutorial describes how to implement an activatable
remote object by extending the class
java.rmi.activation.Activatable
which exports an
activatable remote object during construction.
A remote object is activated when a client invokes a remote
method on a stub for an activatable remote object. A stub for an
activatable remote object contains the remote object's activation
ID and information on how to contact the Java RMI activation system
daemon (rmid
) for the remote object. If the stub
cannot connect to the last-known address (i.e., host/port) for the
remote object, the stub will contact the remote object's activator
(rmid
) to activate the object. When rmid
receives an activation request, it starts the remote object's
activation group (or container) VM if the group is not already
executing, and then rmid
asks the group to make an
instance of the remote object. Once the group constructs the remote
object, it returns the remote object's stub to rmid
which, in turn, returns the actual stub to the initiating stub so
that the initiating stub can update its information on how to
contact the remote object in the future.
Before any of this activation can take place, an application
must register information about the activatable remote objects it
needs to use. The following separate tutorial describes the
information needed to activatate a remote object and how to
register this information with rmid
:
In this example, the activatable remote object implements the
following remote interface
examples.activation.MyRemoteInterface
:
package examples.activation; import java.rmi.*; public interface MyRemoteInterface extends Remote { Object remoteMethod(Object obj) throws RemoteException; }
The implementation class,
examples.activation.ExtendsActivatable
, for the
activatable remote object is as follows:
package examples.activation; import java.rmi.*; import java.rmi.activation.*; public class ExtendsActivatable extends Activatable implements MyRemoteInterface { public ExtendsActivatable(ActivationID id, MarshalledObject data) throws RemoteException { super(id, 0); } public Object remoteMethod(Object obj) { return obj; } }
The class ExtendsActivatable
extends the class
Activatable
and implements the remote interface
MyRemoteInterface
.
The class ExtendsActivatable
declares a special
"activation" constructor that an activation group calls
to construct an instance during the activation process. This
special constructor takes two parameters:
ActivationID
, is an
identifier for the activatable remote object. When an application
registers an activation descriptor with rmid
,
rmid
assigns it an activation ID, which refers to the
information associated with the descriptor. This same activation ID
(also contained in the remote object's stub) is passed to this
constructor when the remote object is activated.MarshalledObject
that
contains initialization data pre-registered with rmid
.
This initialization data may be a filename for the object's
persistent state, for example. This example does not require any
initialization data to construct the remote object.The constructor simply calls a constructor in the superclass
(Activatable
) to export the object on an anoymous
port.
Finally, the class implements the remote interface's single
method, remoteMethod
to return the object passed as an
argument.
The Client
program looks up a remote object's stub
(one that implements the remote interface
MyRemoteInterface
) in the registry on the host
supplied as the optional first argument, and then invokes the
stub's remoteMethod
method. When this client invokes a
remote method on the stub acquired from the registry, the remote
object will activate if not already active.
The source for the program is as follows:
package examples.activation; import java.rmi.*; import java.rmi.registry.*; public class Client { public static void main(String args[]) throws Exception { String hostname = "localhost"; if (args.length < 1) { System.err.println( "usage: java [options] examples.activation.Client <hostname>"); System.exit(1); } else { hostname = args[0]; } if (System.getSecurityManager() == null) { System.setSecurityManager(new SecurityManager()); } String name = System.getProperty("examples.activation.name"); Registry registry = LocateRegistry.getRegistry(hostname); MyRemoteInterface stub = (MyRemoteInterface) registry.lookup(name); System.err.println("Obtained stub from the registry."); System.err.println("Invoking remote method..."); String result = (String) stub.remoteMethod("hello there!"); System.err.println("Returned from remote call."); System.err.println("Result: " + result); } }
This program should be run as follows:
java -cp clientDir \ -Djava.security.policy=client.policy \ -Dexamples.activation.client.codebase=clientCodebase \ -Dexamples.activation.name=name \ examples.activation.Client [host]
where:
Note: rmid
must be running on its default port, and
rmiregistry
must be running on its default port (both
on the remote host) prior to running this program.
The following is an example client.policy
file that
grants the appropriate permissions for the activation examples:
grant codeBase "${examples.activation.client.codebase}" { // permissions to read system properties required by the client permission java.util.PropertyPermission "examples.activation.name","read"; // permission to connect to the registry, activation system, and remote host permission java.net.SocketPermission "*:1024-","connect"; };
The codebase to which permissions are granted is a file URL
specifying the location of the client's classes. This file URL is
the value of the examples.activation.client.codebase
system property, defined when the client program is run. The client
needs two permissions:
java.util.PropertyPermission
- to read the system
property examples.activation.name
that specifies the
name for the stub in the registryjava.net.SocketPermission
- to connect to the
registry, activation system, and remote object's hostThe source files for this example can be compiled as follows:
javac -d implDir MyRemoteInterface.java ExtendsActivatable.java javac -d clientDir MyRemoteInterface.java Client.java
where implDir is the destination directory to put the implementation's class files the class files in, and clientDir is the destination directory to put the client's class files in.
Setup
programOnce your implementation phase is complete, you need to register
information about the activatable object so a client can use it.
The Setup
program, described by the tutorial Using Activation: the Setup
Program,
registers an activation descriptor for an activatable object with
rmid
, and then binds the remote object's stub in an
rmiregistry
so that clients can look it up.
To run the Setup
program for this example, see the
section Start rmid
,
rmiregistry
, and the Setup
program in
the setup program tutorial, which describes how to start
rmid
, rmiregistry
, and the
Setup
program itself.
After you run rmid
and rmiregistry
as
instructed in the Setup
tutorial, you will need to run
the Setup
program to register an activation descriptor
for an activatable object that implements the class
examples.activation.ExtendsActivatable
. The following
command line runs the Setup
program, supplying an
appropriate file URL for each codebase used:
java -cp setupDir:implDir \ -Djava.security.policy=setup.policy \ -Djava.rmi.server.codebase=file:/implDir/ \ -Dexamples.activation.setup.codebase=file:/setupDir/ \ -Dexamples.activation.impl.codebase=file:/impDir/ \ -Dexamples.activation.name=examples.activation.MyRemoteInterface \ -Dexamples.activation.policy=group.policy \ examples.activation.Setup examples.activation.ExtendsActivatable
where:
Setup
program's classSetup
programNote that the examples.activation.file
system
property does not need to be specified, because the
ExtendsActivatable
implementation class does not use
it. Also note that each file URL above has the required trailing
slash. Examples of group and setup policy files, suitable for this
tutorial, are described in the setup tutorial, and are also listed
below:
The output from the Setup
program should look like
this:
Activation group descriptor registered. Activation descriptor registered. Stub bound in registry.
Once you have successfully registered an activation descriptor
for an ExtendsActivatable
implementation, you can run
the client program, which, during its first execution, will cause
the activatable object to activate.
The following command line illustrates how to run the client program, specifying a file URL for the client codebase:
java -cp clientDir \ -Djava.security.policy=client.policy \ -Dexamples.activation.client.codebase=file:/clientDir/ \ -Dexamples.activation.name=examples.activation.MyRemoteInterface \ examples.activation.Client [host]
where:
Notes:
Setup
program. In this example, we used the name
examples.activation.MyRemoteInterface
.rmid
and rmiregistry
must be running
on the server's host. If the server's host is not the local host,
the host argument must specify the remote host that
they are running on.The output from the client should look like this:
Obtained stub from the registry. Invoking remote method... Returned from remote call. Result: hello there!