Using Activation: the Setup Program

Documentation Contents

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

This tutorial has the following steps:

The files needed for this tutorial are:

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:

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:

There are several steps to writing this Setup program:

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:

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:

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:

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 your activatable object needs to support pre-5.0 clients, you will need use rmic to pregenerate a stub class for the implementation class. If your activatable object does not need to support pre-5.0 clients, then there is no need to pregenerate a stub class for the implementation class. 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

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

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

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 2004 Sun Microsystems, Inc. All Rights Reserved.
Please send comments to: rmi-comments@java.sun.com