Documentation Contents

# Using Activation: the `Setup` Program

This tutorial describes how to write a program that registers an activation descriptor for a 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.

This tutorial has the following steps:

- Implement the `Setup` program
- Compile the source file
- Start `rmid`, `rmiregistry`, and the `Setup` program

The files needed for this tutorial are:

- `Setup.java` - main `Setup` program
- `setup.policy` - security policy file for the `Setup` program
- `rmid.policy` - security policy file for `rmid`
- `group.policy` - security policy file for the activation group

## Implement the `Setup` program

The `Setup` program, implemented by the class `examples.activation.Setup`, registers an activation descriptor with `rmid` to enable future activation of the object specified by that activation descriptor. This program does not create an instance of a remote object, but instead registers a remote object's stub with an `rmiregistry` so that clients can look it up. This `Setup` program must be run prior to running any of the clients described in the other activation tutorials.

The `Setup` program uses a number of system properties to customize the information that is registered with `rmid` and `rmiregistry`. The program also takes a single command-line argument that specifies the package-qualified name of the implementation class for the activatable remote object being registered. The `Setup` program is run as follows:

    java -cp classpath \
         -Djava.security.policy=setup.policy        \
         -Djava.rmi.server.codebase=codebase         \
         -Dexamples.activation.setup.codebase=setupCodebase  \
         -Dexamples.activation.impl.codebase=implCodebase \
         -Dexamples.activation.name=name             \
         [-Dexamples.activation.file=filename]       \
         [-Dexamples.activation.policy=group.policy] \
         examples.activation.Setup implClass

where:

- classpath is a class path that includes the `Setup` program and the implementation classes
- setup.policy is the security policy file for the `Setup` program
- codebase is the location (URL) of the remote interface class(es)
- setupCodebase is the location (URL) the `Setup` program class (used in granting permissions to the `Setup` program in the setup.policy file)
- implCodebase is the location (URL) of the implementation class(es), used in the activation descriptor and also used in the group policy file as the codebase to grant permissions to
- name is the name for the object's stub to be bound in the registry
- file (optional) is the name of a file containing the object's persistent state which is registered as the data in the object's activation descriptor (no default)
- group.policy (optional) is the security policy file for the activation group (defaults to `group.policy`), and
- implClass is the fully-qualified name of the
- implementation class.

The following is an example policy file for the `Setup` program:

      grant codeBase "${examples.activation.setup.codebase}" {

        // permissions to read system properties required by setup program
        permission java.util.PropertyPermission "examples.activation.impl.codebase","read";
        permission java.util.PropertyPermission "examples.activation.policy","read";
        permission java.util.PropertyPermission "examples.activation.file","read";
        permission java.util.PropertyPermission "examples.activation.name","read";

        // permission to connect to the activation system and the registry
        permission java.net.SocketPermission "*:1098-1099","connect";
    };

The codebase to which permissions are granted is a URL specifying the location of the `Setup` program's implementation class(es). This URL is the value of the `examples.activation.setup.codebase` system property, which is defined when the `Setup` program is run. The `Setup` program needs the following permissions:

- `java.util.PropertyPermission` - to read various system properties required by the `Setup` program
- `java.net.SocketPermission` - to connect to the activation system (port `1098`) to register an activation descriptor, and to connect to the registry (port `1099`) to bind the activatable object's stub to a name

There are several steps to writing this `Setup` program:

- Construct an activation group descriptor
- Register the group descriptor
- Construct an activation descriptor
- Register the activation descriptor, and finally,
- Bind the remote object's stub in an `rmiregistry`

The `Setup` class has a static `main` method that performs all of the above steps. But before doing so, the `main` method sets a `SecurityManager` and obtains the single command line argument that specifies the package-qualified name of the implementation class for the activatable remote object. The rest of the steps are described below. See `Setup.java` for the full source code.

### Construct an activation group descriptor

Before an application registers information about a particular activatable remote object, it first needs to register information about the activation group that the object will be contained in. An activation group is a container virtual machine (VM) for a set of activatable objects. Each activation group manages the execution of one or more activatable objects. An activation group descriptor contains information that the activation system needs to start an activation group's VM. An application can register an activation group descriptor with the activation system `rmid` to obtain an activation group ID to use for the activatable object, or the application can use an activation group ID obtained from a previous group registration.

The activation group descriptor, an instance of the class `java.rmi.activation.ActivationGroupDesc`, can be constructed in several ways. This tutorial uses the two parameter constructor `ActivationGroupDesc(Properties,CommandEnvironment)`. The `Properties` map contains overrides for system properties in the activation group VM. For this tutorial, an activation group VM needs the following system properties defined:

- `java.security.policy` - the group's security policy file
- `java.class.path` - a dummy class path to prevent an activation group from loading implementation classes from the local class path
- `examples.activation.impl.codebase` - the location of the implementation classes, which the group's policy file uses to grant permissions to
- `examples.activation.file` - a file containg the object's persistent state

The `java.security.policy` property is specified by the `examples.activation.policy` system property, and defaults to the file named `group.policy` which will, in practice, be in the working directory where `rmid` is run. The `java.class.path` property is defined as `no_classpath`. The `examples.activation.impl.codebase` and `examples.activation.file` properties are specified by their current values (respectively), defined when the `Setup` program runs.

The group descriptor is constructed as follows:

    String policy =
        System.getProperty("examples.activation.policy", "group.policy");
    String implCodebase =
        System.getProperty("examples.activation.impl.codebase");
    String filename =
        System.getProperty("examples.activation.file", "");

    Properties props = new Properties();
    props.put("java.security.policy", policy);
    props.put("java.class.path", "no_classpath");
    props.put("examples.activation.impl.codebase", implCodebase);
    if (filename != null && !filename.equals("")) {
        props.put("examples.activation.file", filename);
    }

    ActivationGroupDesc groupDesc = new ActivationGroupDesc(props, null);

The following is an example `group.policy` file that grants the appropriate permissions for the activation examples:

    grant codeBase "${examples.activation.impl.codebase}" {

        // permission to read and write object's file
        permission java.io.FilePermission "${examples.activation.file}","read,write";

        // permission to listen on an anonymous port
        permission java.net.SocketPermission "*:1024-","accept";
    };

The codebase to which permissions are granted is a URL specifying the location of the activatable object's implementation classes. This URL is the value of the `examples.activation.impl.codebase` system property, which will be defined in the activation group's VM. An activatable object in the group needs two permissions:

- `java.io.FilePermission` - to read and write the file containing the activatable object's persistent state
- `java.net.SocketPermission` - to export the activatable object to accept connections an anonymous port

### Register the group descriptor

Next, the `Setup` program must register the activation group descriptor with the activation system to obtain the group's ID, an instance of the class `java.rmi.activation.ActivationGroupID`. The class `java.rmi.activation.ActivationGroup` has a static method `getSystem` for obtaining the stub for the activation system. The `Setup` program calls the activation system's remote method `registerGroup`, passing the group descriptor created above, to register the activation group:

    ActivationGroupID groupID =
        ActivationGroup.getSystem().registerGroup(groupDesc);

### Construct an activation descriptor

Once the activation group ID is obtained, the `Setup` program can register the activation descriptor. The activation descriptor has four basic pieces of information:

- the activation group ID for the group that the object will be contained in
- the implementation's class name
- the location (URL) specifying where the implementation's classes can be loaded from
- a marshalled object containing initialization information for the object

In this example, the activation group ID is the one obtained above; the implementation's class name is the class name, implClass, supplied as the command-line argument to the `Setup` program; the location (URL) is specified by the system property `examples.activation.impl.codebase`; and, the initialization data (which is optional) is a filename specified by the system property `examples.activation.file`.

The activation descriptor is constructed as follows:

    MarshalledObject data = null;
    if (filename != null && !filename.equals("")) {
        data = new MarshalledObject(filename);
    }

    ActivationDesc desc =
        new ActivationDesc(groupID, implClass, implCodebase, data);

### Register the activation descriptor

Next, the `Setup` program must register the activation descriptor with the activation system. The class `Activatable` has a static convenience method, `register`, that registers an activation descriptor with the activation system and returns a stub for the activatable object specified by the descriptor.

    Remote stub = Activatable.register(desc);

Note: The `register` method attempts to load a stub class for the implementation class in order to create a stub instance. If the `register` method is unable to load a pregenerated stub class, it will use an instance of a dynamically-generated proxy class that implements all the interfaces of the implementation class. In the latter case the `register` method needs load the implementation class in order to determine the remote interfaces that the implementation class implements. So, the `register` method has a slight behavioral difference, depending on whether a pregenerated or dynamically-generated stub class is used.

### Bind the remote object's stub in a `rmiregistry`

Finally, the remote object's stub is bound to a name in the registry running on the default port of `1099`. The name is specified by the system property `examples.activation.name`.

    String name = System.getProperty("examples.activation.name");
    LocateRegistry.getRegistry().rebind(name, stub);

## Compile the source file

The source file for this example can be compiled as follows:

    javac -d setupDir Setup.java

where setupDir is the root destination directory to put the class files in.

## Start `rmid`, `rmiregistry`, and the `Setup` program

To run this the `Setup` program, you will need to do the following:

- Start `rmid`
- Start `rmiregistry`
- Run the `Setup` program

### Start `rmid`

To start `rmid`, run the `rmid` command on the server's host. This command should produce no output if it is run with a security policy file as specified below. For more information, see the tools documentation for `rmid` [Solaris, Linux, or Mac OS X, Windows].

For example, in the Solaris Operating System:

    rmid -J-Djava.security.policy=rmid.policy \
         -J-Dexamples.activation.policy=group.policy &

Or, on Windows platforms:

    start rmid -J-Djava.security.policy=rmid.policy \
               -J-Dexamples.activation.policy=group.policy

where:

- rmid.policy is the security policy file for `rmid`
- group.policy is the group policy file, used in `rmid`'s policy file

The security policy file for `rmid` grants permissions for `rmid` to execute specific commands and to use specific command-line options in starting activation group VMs. For example, a user might grant specific permissions to start an activation group VM with one or more system properties or other `java` command-line options. This example allows `rmid` to start activation group VMs that define the system properties `java.security.policy`, `java.class.path`, `examples.activation.impl.codebase`, and `examples.activation.file`. The following example security policy file grants permission to start an activation group VM with these specific properties defined:

    grant {
        // allow activation groups to use certain system properties
        permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=${examples.activation.policy}";
        permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.class.path=no_classpath";
        permission com.sun.rmi.rmid.ExecOptionPermission "-Dexamples.activation.impl.codebase=*";
        permission com.sun.rmi.rmid.ExecOptionPermission "-Dexamples.activation.file=*";
    };

The first `ExecOptionPermission` permission grant restricts the `java.security.policy` system property to be the file specified by the system property `examples.activation.policy`, defined when `rmid` is run. The next permission grant allows a group to define the system property `java.class.path` as `no_classpath`, a dummy class path that prevents the group from having a valid class path. The next permission grant allows the group to define the system property `examples.activation.impl.codebase` to be any value. The final permission grant allows the `examples.activation.file` system property to be any value.

### Start `rmiregistry`

To start the registry, run the `rmiregistry` command on the server's host. This command produces no output (when successful) and is typically run in the background. For more information, see the tools documentation for `rmiregistry` [Solaris, Linux, or Mac OS X, Windows].

For example, in the Solaris Operating System:

    rmiregistry &

Or, on Windows platforms:

    start rmiregistry

By default, the registry runs on TCP port 1099. To start a registry on a different port, specify the port number from the command line. For example, to start the registry on port 2001 on a Windows platform:

    start rmiregistry 2001

Note: Make sure that `rmiregistry` does not have any implementation classes in its class path to prevent it from loading any classes from its local class path.

If the registry will be running on a port other than 1099, you'll need to specify the port number in the calls to `LocateRegistry.getRegistry` in the `Setup` program, as well as any clients that access this registry. For example, if the registry is running on port 2001 in this example, the call to `getRegistry` would be:

    Registry registry = LocateRegistry.getRegistry(2001);

Also note that if you use a registry port other than `1099`, you will also need to modify the `Setup` and client program's policy files to grant permission to connect to the registry's port.

### Run the `Setup` program

To start the `Setup` program, run the `Setup` class using the `java` command as follows:

    java -cp setupDir:implDir \
         -Djava.security.policy=setup.policy        \
         -Djava.rmi.server.codebase=codebase         \
         -Dexamples.activation.setup.codebase=setupCodebase       \
         -Dexamples.activation.impl.codebase=implCodebase \
         -Dexamples.activation.name=name             \
         [-Dexamples.activation.file=file]       \
         [-Dexamples.activation.policy=group.policy] \
         examples.activation.Setup implClass

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
- codebase is the location (URL) of the remote interface class(es)
- setupCodebase is the location (URL) the `Setup` program class (used in granting permissions to the `Setup` program in the setup.policy file)
- implCodebase is the location (URL) of the implementation class(es), used in the activation descriptor and also used in the group policy file as the codebase to grant permissions to
- name is the name for the object's stub to be bound in the registry
- file (optional) is the name of a file containing the object's persistent state which is registered as the `data` in the object's activation descriptor (no default)
- group.policy (optional) is the security policy file for the activation group (defaults to `group.policy`), and
- implClass is the fully-qualified name of the implementation class.

Note: If you use file URLs for any of the codebases listed above, make sure that each file URL has a trailing slash, or the codebase will be invalid.

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

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

Copyright © 1993, 2018, Oracle and/or its affiliates. All rights reserved.
Contact Us