You may notice that while the client code is included, it is not
discussed in a step-by-step manner, like the implementation and setup
classes. The reason for this omission, is that the client code for
activatable objects is no different than the RMI client code for
accessing non-activatable remote objects. Activation is strictly a
server-side implementation decision.
For all of the source code used in the activation tutorials, you may choose
from these formats:
The job of the "setup" class is to create all the information
necessary for the activatable class, without necessarily creating an
instance of the remote object. For this example the setup class
will be examples.activation.Setup
.
Step 1:
Make the appropriate imports in the setup class
import java.rmi.*;
import java.rmi.activation.*
import java.util.Properties;
Step 2:
Install a SecurityManager
System.setSecurityManager(new RMISecurityManager());
Step 3:
Create an ActivationGroup
instance
Note: In this example, for simplicity, we will use a policy file that gives global permission to
anyone from anywhere. Do not use this policy file in a production
environment. For more information on how to properly open up
permissions using a java.security.policy
file, please
refer to to the following documents:
In the setup application, the job of the activation group descriptor
is to provide all the information that rmid
will require
to contact the appropriate existing JVM or spawn a new JVM for the
activatable object.
Note: In order to run this code on your system, you'll
need to change the policy file location to be the absolute path to
where you've installed the example policy file that came with the
source code.
// Because of the Java 2 security model, a security policy should
// be specified for the ActivationGroup VM. The first argument
// to the Properties put method, inherited from Hashtable, is
// the key and the second is the value
//
Properties props = new Properties();
props.put("java.security.policy",
"/home/rmi_tutorial/activation/policy");
ActivationGroupDesc.CommandEnvironment ace = null;
ActivationGroupDesc exampleGroup = new ActivationGroupDesc(props, ace);
// Once the ActivationGroupDesc has been created, register it
// with the activation system to obtain its ID
//
ActivationGroupID agi =
ActivationGroup.getSystem().registerGroup(exampleGroup);
Step 4:
Create an ActivationDesc
instance
The job of the activation descriptor is to provide all the
information that rmid
will require to create a new
instance of the implementation class.
Note: In order to run this code on your system, you'll
need to change the file URL location to be the location of the
directory on your system, where you've installed the example source
code.
// The "location" String specifies a URL from where the class
// definition will come when this object is requested (activated).
// Don't forget the trailing slash at the end of the URL
// or your classes won't be found.
//
String location = "file:/home/rmi_tutorial/activation/";
// Create the rest of the parameters that will be passed to
// the ActivationDesc constructor
//
MarshalledObject data = null;
// The second argument to the ActivationDesc constructor will be used
// to uniquely identify this class; it's location is relative to the
// URL-formatted String, location.
//
ActivationDesc desc = new ActivationDesc
("examples.activation.ActivatableImplementation", location, data);
Step 5:
Declare an instance of your remote interface and register
the activation descriptor with rmid
MyRemoteInterface mri = (MyRemoteInterface)Activatable.register(desc);
System.out.println("Got the stub for the ActivatableImplementation");
Step 6:
Bind the stub, that was returned by the Activatable.register
method, to a name in the rmiregistry
Naming.rebind("ActivatableImplementation", mri);
System.out.println("Exported ActivatableImplementation");
Step 7:
Quit the setup application
System.exit(0);
Compile and run the code
There are six steps to compile and run the code:
- Compile the remote interface, implementation,
client, and setup classes
- Run
rmic
on the implementation class
- Start the
rmiregistry
- Start the activation daemon,
rmid
- Run the setup program
- Run the client
Step 1:
Compile the remote interface, implementation, client
and setup classes
% javac -d . MyRemoteInterface.java
% javac -d . ActivatableImplementation.java
% javac -d . Client.java
% javac -d . Setup.java
Step 2:
Run rmic
on the implementation class
% rmic -d . examples.activation.ActivatableImplementation
Step 3:
Start the rmiregistry
% rmiregistry &
Note: Before you start
the rmiregistry, you must make sure that the shell or window in which
you will run the registry
, either has no CLASSPATH
set or has a CLASSPATH that does not include the path to any classes
that you want downloaded to your client, including the stubs for your
remote object implementation classes.
If you start the rmiregistry
, and it
can find your stub classes in its CLASSPATH, it will ignore the
server's java.rmi.server.codebase
property, and as
a result, your client(s) will not be able to download the stub code for
your remote object.
Step 4:
Start the activation daemon, rmid
% rmid -J-Djava.security.policy=rmid.policy &
Where rmid.policy
is the name of the security policy file for rmid
.
Note: By default, rmid
now requires a security
policy file, that is used to verify whether or not the information in
each ActivationGroupDescriptor
is allowed to be used to
launch a JVM for an activation group. For complete details, please
refer to the rmid
man
page for the Solaris operating environment and the rmid
man
page for the Microsoft Windows platform.
Step 5:
Run the setup program
Run the setup, setting the codebase property to be the location of
the implementation stubs. There are four things that need to go on the
same command line:
- The "
java
" command
- A property name=value pair that specifies the
location of the security policy file
- A property to specify where the stub code lives (no spaces
from the "-D" all the way though the last "/")
- The fully-qualified package name of the setup program.
There should be one space just after the word "java
",
one between the two properties, and a third one just before the word
"examples
" (which is very hard to see when you view this
as text, in a browser, or on paper).
% java -Djava.security.policy=/home/rmi_tutorial/activation/policy
-Djava.rmi.server.codebase=file:/home/rmi_tutorial/activation/ examples.activation.Setup
The codebase property will be resolved to a URL, so it must have the
form of "http://aHost/somesource/
" or
"file:/myDirectory/location/
" or, due to the requirements
of some operating systems, "file:///myDirectory/location/
"
(three slashes after the "file:
").
While a file:
URL is sometimes easier to use for
running example code, using the file:
URL will mean that
the only clients that will be able to access the server are those that
can access the same files system as the server (either by virtue of
running on the same machine as the server or by using a shared
filesystem, such as NFS). If you wish to use an HTTP server, but don't
have one available to you, please feel free to download
our HTTP server.
Please note that each of these sample URL strings has a trailing
"/". The trailing slash is a requirement for the URL set by the
java.rmi.server.codebase
property, so the implementation
can resolve (find) your class definition(s) properly. For more
information on setting the java.rmi.server.codebase
property from the command line, please take a look at our tutorial on
dynamic code downloading using the
java.rmi.server.codebase
property.
If you forget the trailing slash on the property, or if the class
files can't be located at the source (they aren't really being made
available for download) or if you misspell the property name, you'll
get thrown a java.lang.ClassNotFoundException.
This
exception will be thrown when you try to bind your remote object to the
rmiregistry
, or when the first client attempts to access
that object's stub. If the latter case occurs, you have another problem
as well because the rmiregistry
was finding the stubs in its CLASSPATH.
The server output should look like this:
Got the stub for the ActivatableImplementation
Exported ActivatableImplementation
Step 6:
Run the client
The argument to the examples.activation.Client
program is the
hostname of the implementation server, in this case, "vector
".
% java -Djava.security.policy=/home/rmi_tutorial/activation/policy
examples.activation.Client vector
The client output should look like this:
Got a remote reference to the object that extends Activatable.
Making remote call to the server
Returned from remote call
Result: Success
*As used on this web site, the terms "Java virtual machine" or "JVM"
mean a virtual machine for the Java platform.