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:
The files needed for this tutorial are:
Client2.java,
the class which will invoke a method on an activatable object
MyRemoteInterface.java
, the interface that extends java.rmi.Remote,
implemented by:
MyRemoteInterfaceImpl.java
, the class which will be activated
Setup2.java,
the class which registers information about the activatable
class with the registry and the RMI daemon
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:
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
Step 1:
Make the appropriate imports in the implementation classimport java.rmi.*; import java.rmi.activation.*;Step 2:
Modify the class declaration so that the class now extends from java.rmi.activation.Activatablepublic class MyRemoteInterfaceImpl extends Activatable implements examples.activation.MyRemoteInterface {Step 3:
Remove or comment out the old no-argument constructor// public MyRemoteInterfaceImpl() throws RemoteException // { // }Step 4:
Declare a two-argument constructor in the implementation classpublic 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
seven steps to create a setup class:
SecurityManager
ActivationGroup
instance
ActivationDesc instance
rmid
rmiregistry
Step 1:
Make the appropriate imports in the setup classimport java.rmi.*; import java.rmi.activation.* import java.util.Properties;Step 2:
Install aSecurityManagerSystem.setSecurityManager(new RMISecurityManager());Step 3:
Create anActivationGroupinstanceNote: 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.policyfile, please refer to to the following documents:
http://java.sun.com/products/jdk/1.2/docs/guide/security/PolicyFiles.htmlhttp://java.sun.com/products/jdk/1.2/docs/guide/security/permissions.htmlIn the setup application,the job of the activation group descriptor is to provide all the information that
rmidwill require to contact the appropriate existing VM or spawn a new VM 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.
// After JDK1.2Beta4, ActivationGroups are no longer created // implicitly as a side-effect of creating or registering the // first Activatable object // // Because of the 1.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); // Now explicitly create the group // ActivationGroup.createGroup(agi, exampleGroup, 0);Step 4:
Create anActivationDescinstanceIn the setup application, the job of the activation descriptor is to provide all the information that
rmidwill 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.
// 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.MyRemoteInterfaceImpl", location, data);
Step 5:
Remove the reference to the implementation class creation, declare an instance of your remote interface, and register the activation descriptor withrmid// 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 6:
Bind the stub, that was returned by theActivatable.registermethod, to a name in thermiregistryNaming.rebind("MyRemoteInterfaceImpl", mri); System.out.println("Exported MyRemoteInterfaceImpl");
Step 7:
Quit the setup applicationSystem.exit(0);
There are six steps to compile and run the code:
rmic on the implementation class
rmiregistry
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.javaStep 2:
Runrmicon the implementation class
% rmic -d . examples.activation.MyRemoteInterfaceImpl% 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'sjava.rmi.server.codebaseproperty, 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 &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.Setup2The 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:").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.codebaseproperty, 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. This exception will be thrown when you try to bind your remote object to thermiregistry, or when the first client attempts to access that object's stub. If the latter case occurs, you have another problem as well because thermiregistrywas finding the stubs in its CLASSPATH.The server output should look like this:
Got the stub for the MyRemoteInterfaceImpl Exported MyRemoteInterfaceImplStep 6:
Run the clientThe argument to the client program is the hostname of the implementation server, in this case, "
vector".% java examples.activation.Client2 vectorThe 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
Copyright © 1998 Sun Microsystems, Inc. All Rights Reserved.
![]() |