| # Using Activation: Extending `Activatable` | Documentation Contents

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 JavaTM 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:

- Implement the activatable remote object
- Implement the client
- Compile the source files
- Run the `Setup` program
- Run the client

The files needed for this tutorial are:

- `MyRemoteInterface.java` - a simple remote interface
- `ExtendsActivatable.java` - an "activatable" implementation of the remote interface
- `Client.java` - a client that uses the remote interface
- `client.policy` - the security policy file for the client

## Implement the activatable remote object

> There 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`:

> - Using Activation: the `Setup` program

> 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:

> - The first parameter, `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.
> - The second parameter is a `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.

## Implement the client

> 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:

> - clientDir is the root directory for the client program (its class path),
> - client.policy is the security policy file for this program,
> - clientCodebase is the location (URL) for this program's class (used in granting permissions to this program in the client.policy file)
> - name is the name for the object's stub in the registry
> - host is the server's host

> 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 registry
> - `java.net.SocketPermission` - to connect to the registry, activation system, and remote object's host

## Compile the source files

> The 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.

## Run the `Setup` program

> Once 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:

> - setupDir is the root directory for the `Setup` program's class
> - implDir is the root directory for the implementation's classes
> - setup.policy is the security policy file for the `Setup` program
> - group.policy is the security policy file for the activation group

> Note 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:

> - `setup.policy`
> - `group.policy`

> The output from the `Setup` program should look like this:

> >     Activation group descriptor registered.
> >     Activation descriptor registered.
> >     Stub bound in registry.

## Run the client

> 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:

> - clientDir is the root directory for the client program (its class path),
> - client.policy is the security policy file for this program,
> - name is the name for the object's stub in the registry
> - host is the server's host

> Notes:

> - The client codebase must have a trailing slash.
> - The name must match the name supplied to the `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!

Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. Please send comments to: `rmi-comments@java.sun.com` |