Implementing an Activable Remote Object
The remote interface that will be the base for the examples in this article is named PrinterInterface.java:
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface PrinterInterface extends Remote{
//the remote methods
public void setPrinterJob()throws RemoteException;
public void removePrinterJob()throws RemoteException;
public int getPrinterJobsNumber()throws RemoteException;
}
As the remote methods in this interface suggest, you intend to develop a RMI application that permits users to add and remove jobs from a printer task and to list queued jobs at any given moment. The application is based on an integer value incremented with 1, when the setPrinterJob method is called, and decremented with 1 when the removePrinterJob is called. The getPrinterJobsNumber method is used to determine the number of current printer jobs.
This is how the activation system tries to localize a constructor:
...
public constructor_name(ActivationID id,MarshalledObject data) throws
RemoteException,ClassNotFoundException,java.io.IOException{
...
}
...
rmid automatically calls the constructor with an activation identifier and a serializable object. You then define the constructor in the same class that implements the activable remote object. It's very important for the constructor to call either an Activatable class' activation/reactivation constructor or an Activatable.exportObject method, depending of how you've chosen to implement the activable remote object. This call should contain the activation identifier and the port used for export.
Theoretically, you can implement an activable remote object for the PrinterInterface.java interface, as in Listing 1.
The constructor for a "pre-activated" object is optional (in this article, you will also see an example without this constructor). Only the second one is required. Actually, any other constructors except the required one must call one of the initialization constructors of the Activatable class (or the corresponding Activatable.exportObject method) in order to preserve the reactivation behavior of the activable remote object.
The Setup Program
Normally, you should next implement the RMI server class to run as your server and wait for remote methods calls. But, in the case of activable remote objects, the RMI server class is replaced by a special class called the "setup" class.
The main task of the "setup" class is to initialize rmid and rmiregistry with information about the activable remote objects. So, the "setup" class registers the activable remote objects with the rmid by sharing their information trough the activation descriptor. Setup then registers a remote reference and a name for every activable remote object in the rmiregistry. You can stop setup class' execution withthe System.exit method call (a forced stop).
All the information the activation system needs in order to activate an activable remote object is wrapped in the java.rmi.activation.ActivationDesc class. This class actually represents the activation descriptor specially used by rmid to find out information at the time of activation. Here's a list of the information kept by the ActivationDesc class:
- Group identifier
- The fully name of the class associated with this activable remote object.
- The path to this class (URL).
- The possibility to reactivate an activable remote object when the activator or it activation group is restarted (or the possibility to be activated only on demand)
.
The easiest way to register an activable remote object to the activation system is to create an instance of the class that implements it. In this example, you implement an activable remote object by defining the PrinterImplActivatable class (this class extends the Activatable class). To create an instance of the PrinterImplActivatable class, you must call the public constructor (the optional one):
//this URL represent the path to the corresponding class of the activable remote object
String url="file:///C://Data_Local//RMIServerActivation//";
//creating an activable remote object
PrinterInterface PI=new PrinterImplActivatable(null,url,0);
Calling the PrinterImplActivatable class' public constructor automatically calls one of the Activatable class' initialization constructors (because of the super method). This registers the activable remote object to the activation system and exporting this object to an random port. In this case the Activatable constructor will take care of creating and registering the ActivationDesc corresponding to this object. For finish the registering process you must register the activable remote object to the rmiregistry like this:
//registering the activable remote object to rmiregistry
Naming.rebind("printer",PI);
The complete source code for the setup class for the PrinterImplActivatable class is shown in Listing 2.
Note: In this part of this article, you must make abstractions of the code that refers to the creation of an activation group and the code for setting a security manager. For now, it is sufficient to know that, in this case, the activation group is the default activation group created for the current JVM and setting a security manager is absolutely necessary.
Implementing the setup class is the easiest, but not the most preferable, solution. Generally, RMI applications based on activable remote objects register these kind of objects without creating instances of the classes that implement them. Obviously, this approach is much more powerful, thus demonstrating the power of ROA technology. However, this approach requires that you define the activation descriptor manually.
Obviously, in order to create an ActivationDesc, you should know its constructors. These are four:
public ActivationDesc(ActivationGroupID groupID, String class_name, String source,
MarshalledObject data)
public ActivationDesc(ActivationGroupID gruopID, String class_name, String source,
MarshalledObject data, boolean restart)
public ActivationDesc(String class_name, String source, MarshalledObject data) throws
ActivationException
public ActivationDesc(String class_name, String source, MarshalledObject data, boolean restart)
throws ActivationException
The arguments of these constructors represent:
- groupID: This represents an
ActivationGroupID object and is known as the group identifier. It uniquely identifies an activation group and can be used to determine in which JVM the activable remote object should be activated.
- class_name: This is the full name of the class associated to the activable remote object.
- source: This is the path to
class_name.
- data: This is a
MarshalledObject object used for initialization of the activable remote object.
- restart: If this boolean argument is
true, the activable remote object is automatically reactivated when either the activator, or its activation group, is restarted. If the value is false, the activable remote object is activated only on demand. Remember that even though this argument has a true value, that doesn't mean that a new registered activable remote object will be forced to be activated, because the initial activation faze is "lazy".
In this example, you can create an ActivationDesc object like this:
//the URL to the class representing the activable remote object
String url="file:///C://Data_Local//RMIServerActivation//";
//no initialization data
MarshalledObject data=null;
//create an ActivationDesc
ActivationDesc AD=new ActivationDesc("PrinterImplActivatable",url,data);
After this manual creation of the ActivationDesc object, you must register the activable remote object to the rmid. To do this, you call the register method of the Activatable class. This method gets an argument representing the activation descriptor which is the ActivationDesc object. Here's the syntax of the register method:
public static Remote register(ActivationDesc desc) throws UnknownGroupException,
ActivationException, RemoteException
This static method returns the stub for the activable remote object. Of course, this stub must be converted (via cast conversion) to the remote interface, in this case PrinterInterface:
PrinterInterface stub=(PrinterInterface)Activatable.register(AD);
The last step is to bind the obtained stub to the rmiregistry attach an access URL for the stub:
Naming.rebind("printer",stub);
Because you don't need to create an instance of the class that implements the activable remote object, there is no need to define the "pre-activation" constructor in the PrinterImplActivatable.java source. The PrinterImplActivatable.java source becomes what you see in Listing 3.
As you can see, the only remaining constructor is the required activation/reactivation constructor. Listing 4 shows the resulting "setup" class.
See You In Part II
In Part 2, you will see how to create an activation group, how to define and use a MarshalledObject object, andmost importantlyhow to run an RMI application based on activable remote objects.
| Home / Articles
/ An Introduction to Remote Method Activation (ROA) / 1 / 2 / 3 / 4 / |
New on the Java Boutique:
New Review:
Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling
API boasts simplicity, ease-of-integration, a well-rounded feature
set, and it's free!
New Applet:
Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA
sequences into three useful formats.
Elsewhere on internet.com:
WebDeveloper Java
Lots of Java information on webdeveloper.com
WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.
ScriptSearch Java
Hundreds of free Java code files to download.
jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.