UnicastRemoteObject
to an activatable object, by extending java.rmi.activation.Activatable
.
This page is just for developers who wish to change an existing class from
being a sub-class of UnicastRemoteObject
to being a sub-class
of java.rmi.activation.Activatable.
If you are interested in finding
out about Creating an Activatable Object
or Activating an object that does not extend
java.rmi.activation.Activatable, these are also available as tutorials.
Prior to the release of the JDK1.2, an instance of a UnicastRemoteObject
could be accessed from a server program that (1) created an instance of
the remote object, and (2) ran all the time. Now with the introduction
of the class java.rmi.activation.Activatable
and the RMI daemon,
rmid
, programs can be written to register information about remote
object implementations that should be created and execute "on demand",
rather than running all the time. The RMI daemon, rmid
, provides
a JVM from which other JVM instances may be spawned.
Note: For the remainder of this tutorial, the terms
"activatable object implementation", "activatable object," and "implementation"
may be used interchangeably to refer to the class, examples.activation.MyRemoteInterfaceImpl
,
which implements a remote interface and is activatable.
This tutorial is organized as follows:
Client2.java
, the class which
will invoke a method on an activatable objectMyRemoteInterface.java
,
the interface that extends java.rmi.Remote
, implemented by:MyRemoteInterfaceImpl.java
,
the class which will be activatedSetup2.java
, the class which registers
information about the activatableFor the source code used in all of the activation tutorials, click here.
For this example, the implementation class will be examples.activation.MyRemoteInterfaceImpl.
There are four steps to migrate an existing implementation class that
extends from UnicastRemoteObject
:
java.rmi.activation.Activatable
import java.rmi.*;
import java.rmi.activation.*;
Step 2:
Modify the class declaration so that the class now
extends from java.rmi.activation.Activatable
public class MyRemoteInterfaceImpl extends Activatable
implements examples.activation.MyRemoteInterface {
// public MyRemoteInterfaceImpl() throws RemoteException
// {
// }
Step 4:
Declare a two-argument constructor in the implementation
class
public MyRemoteInterfaceImpl(ActivationID id, MarshalledObject data)
throws RemoteException {
// Register the object with the activation
system
// then export it on an anonymous port
super(id, 0);
}
Unlike the RMI server class that must stay alive as long as the implementation
needs to be made available, 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.Setup2
.
The setup class passes information about the activatable class to rmid
,
registers a remote reference (an instance of the activatable class's stub
class) and an identifier (name) with the rmiregistry
, and then
the setup class may exit. There are six steps to create a setup class:
SecurityManager
ActivationDesc
instancermid
rmiregistry
import java.rmi.*;
import java.rmi.activation.*;
import java.security.CodeSource;
import java.util.Properties;
System.setSecurityManager(new RMISecurityManager());
Step 3:
Create an ActivationDesc
instance
In the setup application, create a Properties
instance, an
ActivationGroupID
instance, a CodeSource
instance and
a MarshalledObject
instance, as these will be needed for the constructor
of the ActivationDesc
. 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" URL specifies where the class definition
// will come from 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.
//
java.net.URL location = new
java.net.URL("file:/home/rmi-tutorial/activation/");
// The second parameter to the CodeSource constructor
// is an object that implements java.security.PublicKey
//
CodeSource source = new CodeSource(location, null);
Properties props = (Properties)System.getProperties().clone();
ActivationGroupID agi = ActivationGroup.getSystem().registerGroup(
new ActivationGroupDesc(props));
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
referenced by the CodeSource
//
ActivationDesc desc = new ActivationDesc
(agi, "examples.activation.MyRemoteInterfaceImpl",
source, data);
Step 4:
Remove the reference to the implementation class creation,
declare an instance of your remote interface, and register the activation
descriptor with rmid
// MyRemoteInterfaceImpl mri = new MyRemoteInterfaceImpl();
// the above line is replaced with the following:
//
MyRemoteInterface mri = (MyRemoteInterface)Activatable.register(desc);
System.out.println("Got the stub for the MyRemoteInterfaceImpl");
Step 5:
Bind the stub, that was returned by the Activatable.register
method, to a name in the rmiregistry
Naming.rebind("MyRemoteInterfaceImpl", mri);
System.out.println("Exported MyRemoteInterfaceImpl");
Step 6:
Quit the setup application
System.exit(0);
There are six steps to compile and run the code:
rmic
on the implementation classrmiregistry
rmid
Step 1:
Compile the remote interface, implementation, client
and setup classes
% javac -d . MyRemoteInterface.java
% javac -d . MyRemoteInterfaceImpl.java
% javac -d . Client2.java
% javac -d . Setup2.java
Step 2:
Run rmic
on the implementation class
% rmic -d . examples.activation.MyRemoteInterfaceImpl
java
" command, followed by the property
name=value pair (no spaces from the "-D" all the way thought
the last "/") and then the fully-qualified package name of the setup program.
There should be a space just after the word "java
" and 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.rmi.server.codebase=file:/home/rmi-tutorial/activation/
examples.activation.Setup2
The codebase property will be resolved to a URL, so it must have the
form of "http://somesource/
" or "file:/myDirectory/location/
"
or, due to the requirements of some operating systems, "file:///myDirectory/location/
"
(three slashes after the "file:
").
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.
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
.
The server output should look like this:
Got the stub for the MyRemoteInterfaceImpl
Exported MyRemoteInterfaceImpl
The argument to the client program is the hostname of the implementation
server, in this case, "vector
".
% java examples.activation.Client2 vector
The client output should look like this:
Got a remote reference to the newly-Activatable object
Returned from remote call
Result: Successful execution of callMeRemotely() in MyRemoteInterfaceImpl