CS 696 Emerging Technologies: Java Distributed Computing Spring Semester, 1999 Remote Object Activation |
||
---|---|---|
© 1999, All Rights Reserved, SDSU & Roger Whitney San Diego State University -- This page last updated 02-Mar-99 |
Remote Object Activation
Activation allows objects to begin execution on an as-needed basis
Active object
Information Needed to Activate an Object
Object initialization data
Activator
The entity that supervises activation by being:
rmid [-port port] [-log dir]If –port is not given, it uses 1098
Activation Group
The activation group is the entity in a JVM which:
ActivationGroupDesc
Constructors ActivationGroupDesc(Properties overrides, ActivationGroupDesc.CommandEnvironment cmd)Overrides
ActivationGroupDesc(String className, String location, MarshalledObject data, Properties overrides, ActivationGroupDesc.CommandEnvironment cmd)Specifies an alternate ActivationGroup implementation (className, location, data) and execution environment to be used for the group. The className, location, and data are used to create the ActivationGroup. The className is the name of the subclass of ActivationGroup to be used. Location is the location of this class. Data is the initialization data that the class may need. This form of the constructor is for advanced uses.
Example – No Initialization Data
Remote Interface package whitney.rmi.examples.activation; public interface Hello extends java.rmi.Remote { String sayHello() throws java.rmi.RemoteException; }Implementation
The second argument in super( id, 0 ) is the port number to export the remote object on. Using 0 results in a random port being used.
package whitney.rmi.examples.activation; import java.net.InetAddress; import java.rmi.*; import java.rmi.activation.*; public class HelloServer extends Activatable implements Hello { public HelloServer(ActivationID id, MarshalledObject data) throws RemoteException { super( id, 0 ); System.out.println( "HelloServer object created"); } public String sayHello() { return "Hello World from " + getHostName(); } protected static String getHostName() { try { return InetAddress.getLocalHost().getHostName(); } catch (java.net.UnknownHostException who) { return "Unknown"; } } }
Setup Class
package whitney.rmi.examples.activation; import java.rmi.*; import java.rmi.activation.*; import java.util.Properties; public class RegisterHelloServer { public static void main(String[] args) throws Exception { System.setSecurityManager(new RMISecurityManager()); Properties policyFileLocation = new Properties(); policyFileLocation.put("java.security.policy", "/export/home/whitney/.java.policy"); ActivationGroupDesc.CommandEnvironment ace = null; ActivationGroupDesc exampleGroup = new ActivationGroupDesc(policyFileLocation, ace); ActivationSystem localActivationSystem = ActivationGroup.getSystem(); ActivationGroupID agi = localActivationSystem.registerGroup(exampleGroup); ActivationGroup.createGroup(agi, exampleGroup, 0); String classLocation = "file:/export/home/whitney/java/classes/"; String serverClass = "whitney.rmi.examples.activation.HelloServer"; MarshalledObject data = null; ActivationDesc desc = new ActivationDesc(serverClass, classLocation, data); Hello mri = (Hello)Activatable.register(desc); System.out.println("Got the stub for the HelloServer"); Naming.rebind("HelloServer", mri); System.out.println("Exported HelloServer"); System.exit(0); } }
Setup Class Explained
Security manager is needed
System.setSecurityManager(new RMISecurityManager());We need to create the ActivationGroup.
Properties policyFileLocation = new Properties(); policyFileLocation.put("java.security.policy", "/export/home/whitney/.java.policy");
ActivationGroupDesc.CommandEnvironment ace = null; ActivationGroupDesc exampleGroup = new ActivationGroupDesc(policyFileLocation, ace);
ActivationSystem localActivationSystem = ActivationGroup.getSystem(); ActivationGroupID agi = localActivationSystem.registerGroup(exampleGroup);
ActivationGroup.createGroup(agi, exampleGroup, 0);Now we need to create the ActivationDesc for the activatable object
String classLocation = "file:/export/home/whitney/java/classes/"; String serverClass = "whitney.rmi.examples.activation.HelloServer";
MarshalledObject data = null; ActivationDesc objectDescriptor = new ActivationDesc(serverClass, classLocation, data);
Hello helloStub = (Hello)Activatable.register(objectDescriptor ); System.out.println("Got the stub for the HelloServer");
Naming.rebind("HelloServer", helloStub ); System.out.println("Exported HelloServer");We are done, so can exit
System.exit(0); } }
A sample Client
package whitney.rmi.examples.activation; import java.rmi.registry.Registry; import java.rmi.RemoteException; import whitney.rmi.tools.ServerTester; public class HelloClient extends ServerTester { public void test() throws RemoteException, InterruptedException { Hello myServer = (Hello) serverObject; System.out.println( myServer.sayHello() ); } }ServerTester is on Doc 9 slide 2 at: http://www.eli.sdsu.edu/courses/spring99/cs696/notes/roaming/roaming.html#Heading4
Running The Example
Compile client, server, etc.
Generate stubs and skeletons using rmic on server class
Start the rmiregistry
Start the activation daemon rmid
Run the setup program
Run the client
Note you can stop the rmid using:
rmid –stopWhen you resume rmid, you can still connect to the server object.
Example With Initialization Data
In this example a counter object will save is state in a file. When the object is restarted, it will read the file for the last value of the count.
Counter Interface package whitney.rmi.examples.activation; import java.rmi.Remote; import java.rmi.RemoteException; public interface Counter extends Remote { public abstract void reset() throws RemoteException; public abstract int increase() throws RemoteException; public abstract int decrease() throws RemoteException; public abstract int count() throws RemoteException; }
Counter Implementation
package whitney.rmi.examples.activation; import sdsu.io.SimpleFile; import java.rmi.activation.*; import java.rmi.*; import java.io.IOException; public class PersistentCounter extends Activatable implements Counter { private SimpleFile previousStateFile; private int count = 0; public PersistentCounter( ActivationID id, MarshalledObject data) throws RemoteException, ClassNotFoundException, IOException { super(id, 0); previousStateFile = (SimpleFile)data.get(); if (previousStateFile.exists()) this.restoreState(); } private void restoreState() throws IOException { String previousState = previousStateFile.getContents(); count = Integer.parseInt( previousState ); } private void saveState() throws RemoteException { try { previousStateFile.setContents( String.valueOf( count )); } catch (IOException writeProblem ) { throw new RemoteException( "Problem saving count" ); } }
PersistentCounter Continued public void reset() throws RemoteException { count = 0; saveState(); } public int increase() throws RemoteException { ++count; saveState(); return count; } public int decrease() throws RemoteException { --count; saveState(); return count; } public int count() { return count; } }
The Counter Setup
package whitney.rmi.examples.activation; import java.rmi.*; import java.rmi.activation.*; import java.util.Properties; import sdsu.io.SimpleFile; public class RegisterPersistentCounter { public static void main(String[] args) throws Exception { System.setSecurityManager(new RMISecurityManager()); Properties policyFileLocation = new Properties(); policyFileLocation.put("java.security.policy", "/export/home/whitney/.java.policy"); ActivationGroupDesc.CommandEnvironment ace = null; ActivationGroupDesc exampleGroup = new ActivationGroupDesc(policyFileLocation, ace); ActivationGroupID agi = ActivationGroup.getSystem().registerGroup(exampleGroup); ActivationGroup.createGroup(agi, exampleGroup, 0); String classLocation = "file:/export/home/whitney/java/classes/"; String serverClass = "whitney.rmi.examples.activation.PersistentCounter"; String countFileName = "/export/home/whitney/java/whitney/rmi/examples/activation/CountFile"; SimpleFile countDataFile = new SimpleFile( countFileName ); MarshalledObject data = new MarshalledObject( countDataFile ); ActivationDesc desc = new ActivationDesc(serverClass, classLocation, data); Counter mri = (Counter)Activatable.register(desc); System.out.println("Got the stub for the PersistentCounter"); Naming.rebind("Counter", mri); System.out.println("Exported Counter"); System.exit(0); } }
What is New in the Setup
The counter needs to know the location of data file containing its previous state. When a passive object is activated it will use this information to reset its state.
String classLocation = "file:/export/home/whitney/java/classes/"; String serverClass = "whitney.rmi.examples.activation.PersistentCounter";Create the file object to the data file
String countFileName = "/export/home/whitney/java/whitney/rmi/examples/activation/CountFile"; SimpleFile countDataFile = new SimpleFile( countFileName );Wrap the file object, so it can be delivered to the counter
MarshalledObject data = new MarshalledObject( countDataFile ); ActivationDesc desc = new ActivationDesc(serverClass, classLocation, data);
Lazy Activation vs. Activation on Startup
The default behavior is to activate passive object when first requested. One can set it so that when the rmid is restarted a passive object is activated. ActivationDesc has a constructor that contains a restart flag.
public ActivationDesc(String className, String location, MarshalledObject data, boolean restart) throws ActivationException
Constructs an object descriptor for an object whose class name is className, that can be loaded from the code location and whose initialization information is data. If this form of the constructor is used, the groupID defaults to the current id for ActivationGroup for this VM. All objects with the same ActivationGroupID are activated in the same VM.
This constructor will throw ActivationException if there is no current activation group for this VM. To create an ActivationGroup use the ActivationGroup.createGroup method.
Parameters: