Activatable Jini services, Part 1: Implement RMI activation

The RMI activation framework can produce self-sufficient, flexible Jini services

1 2 3 Page 3
Page 3 of 3

rmid's log directory provides this persistence. When rmid initiates, it reconstitutes these mappings from its log files. Thus, an activatable object does not need to reregister when the activation system restarts. Any services that were previously registered with rmid remain available for activation after rmid restarts. Since many Jini services in the Jini Starter Kit come as activatable objects, you do not need to manually restart these services. For instance, the Jini lookup service, once registered with rmid, will restart automatically when rmid returns after a machine reboot. Therefore, it is not wise to delete rmid's log directory, especially in a production system, because hundreds of objects' registrations could be destroyed. As such, these objects could not handle remote method calls unless explicitly reregistered with the activation system -- by running their setup program, for instance.

Specify rmid's log directory with a command line such as:

      rmid -log LOG_DIR

In addition, rmid should be shut down as shown below to allow it to save in a persistent state:

      rmid -stop

The activation constructor

An activatable object must provide a special constructor to assist with activation. The activation system will call this constructor to instantiate the object. Activatable objects are easiest to implement as subclasses of java.rmi.activation.Activatable, another RemoteServer type. One of Activatable's constructors also manages the registering and exporting of the object. Thus, we will subclass the activatable LoanServiceImpl class from Activatable and equip it with an activation constructor:

public class LoanServiceImpl extends java.rmi.activation.Activatable
      implements RemoteLoanService 
{
  //Object that makes the decision about the loan
  Bank decisionSystem;
  //activation constructor
  public LoanServiceImpl(ActivationID id, MarshalledObject data)
            throws RemoteException 
  {
        super(id, 0);
        String path = (String)data.get();
        decisionSystem = initBank(path);
  }
        ....
              
  //implementation of LoanService
  public LoanApproval requestLoan(LoanRequest request)
             throws RemoteException 
  {
             //perform work here
             return decisionSystem.decide(request);
  }
  //load Bank object 
  private Bank initBank(String filePath)
  {
             //read property file from disk, initialize Bank object
             ....
  }
  ...

Persistent references

In addition to managing computational resources on object servers, activation also offers long-term maintenance of remote object references. When the client generates the method call to the remote service implementation, it assumes that the reference contained in the stub is valid; if it is not, the method call will result in a RemoteException. Without activation, the client application may retry the operation (hoping that it will succeed), reobtain the service proxy from the lookup service, or simply inform the user that the server connection is dead.

With an activatable service implementation, the stub will try to contact the object via a live remote reference, just as it would with a nonactivatable implementation. If the reference is not valid, the stub will use a second reference, this time to the activation system running on the remote object's host. This activation system is stored in the stub as an internal RMI reference. If it receives a request to activate an object, the stub will return to the caller -- the Jini client, in our case -- a live reference to the remote object. Thus, this second remote call will return a valid service reference to our applet. This is called a faulting remote reference, since it allows the activation system to "fault in" the object on demand. This process is transparent to the client and is solely an implementation issue of the service.

The following scenario illustrates the benefit of maintaining persistent references:

  1. Start the activatable service. It will register with rmid and Jini lookup services.
  2. Initiate the client. It will obtain the service object from a lookup service and use the object to make remote method calls to the service implementation.
  3. Suppose a system administrator reboots the machine that runs the remote service implementation, destroying the remote object and its Java VM in the process. If a client attempts to generate a method call to the server, it will receive a RemoteException, meaning the service is not available. A few minutes later, the remote object server returns. Since the system administrator configured rmid to fire up when the machine comes back (e.g., via the Unix init mechanism or as an NT service), rmid starts up, reads its log files, and reinitializes its state. Then if the client, which has been running continuously while the server was rebooted, makes a remote method call to the server, it will discover no live reference to the remote object. It will then consult the server's activation system, which will activate the object and return to the client a live reference to the object. Provided that the object can be activated, the method call will succeed.

Deactivating the service

I started out by saying that activation's greatest benefit is its management of system resources in long-running object servers. We also saw how the activation system executes objects on demand. The activation system will not deactivate objects automatically, though.

There is no standard way to measure whether an object is "heavily" or "lightly" used; it depends on the situation. As well, even if objects are rarely used but the server they're running on has a light load, it would make no sense to deactivate these objects. These are decisions a programmer or system administrator must make. For example, a service might have a separate thread running to measure use. When this thread determines that the object is idle, it calls Activatable.inactive(activationID) to inform the object's activation group. If no pending method calls to the object remain, the activation group will unexport the object, and inactive() will return true. If there are pending calls, the method will not be unexported. If the object is the only one running in the activation group, the activation system might shut down the group's VM as well.

If we want a service to discontinue its availability to the activation system, we can unregister it with a call to:

      Activatable.unregister(activationID)

Unlike an inactive object, an unregistered object will not activate when it receives remote method calls. A service's administrative functions should allow an administrator to unregister an object when shutting it down.

While you were asleep...

Now that our loan service is activatable, it is better able to manage its resources, to delegate its startup and shutdown to rmid, and to maintain persistent references over object incarnations. However, activation introduces a new set of issues that we must deal with.

Recall that registering the activatable service with the activation system returned a remote stub to the service without firing up an instance of the object. We used this stub to register the activatable service with the lookup service. The activatable service will need to renew its leases, even while inactive. Good Jini citizenship also requires that the activatable service discover and join new lookup services. Finally, the activatable service might be interested in events while it is inactive. If the service activated just to handle these responsibilities, it would be a waste of resources. These duties should be delegated to third-party services. The Jini Helper Utilities and Services Specification introduces a lease renewal service, a lookup discovery service, and an event mailbox service. Part 2 of this article will discuss how activatable Jini services can take advantage of these tools.

Frank Sommers is the founder and CEO of Autospaces, a startup focused on bringing Jini technology to the automotive software market. He has served as VP of technology at Nowcom Corporation, a company providing business infrastructure to the finance and insurance industries, since 1996. He has been programming in Java since 1995, after attending the first public demonstration of the language on the Sun Microsystems campus in November of that year. His interests include parallel and distributed computing, the discovery and representation of knowledge in databases, and the philosophical foundations of computing. When not thinking about computers, he composes and plays piano, studies the symphonies of Gustav Mahler, and explores the writings of Aristotle and Ayn Rand. Sommers would like to thank John McClain of Sun Microsystems for his valuable comments on this article.

Learn more about this topic

  • Sun's John McClain posted "The Process Architecture of the JSK and JSTK" to the Jini-users list. It presents a clear explanation of the role of RMI activation in Sun's implementation of the services that come with the JSK
  • Manifestations of a service-oriented computing landscape

1 2 3 Page 3
Page 3 of 3