Before using the RMI server, you must write your service according to the RMI specifications. The following example shows how to do that.

First, use an interface to encapsulate the functionality you want to expose through RMI. For example, say that you want to make a bank account component that allows someone to adjust the balance. You might design the BankBalance interface to look like this:

import java.rmi.*;
public interface BankBalance extends Remote
    public void adjustBalance (double amount) throws RemoteException;
    public double getCurrentBalance () throws RemoteException;

Remember that you do not have to put your service’s complete functionality in this interface—just the parts that you want to make accessible remotely. And remember that the interface must extend java.rmi.Remote, and every method must declare that it throws java.rmi.RemoteException.

After you finish writing the remote interface, write the actual implementation of that interface. For example:

import java.rmi.*;
public class BankBalanceImpl
extends atg.nucleus.GenericRMIService
implements BankBalance
  double balance;
  public BankBalanceImpl () throws RemoteException {}

  public void adjustBalance (double amount) throws RemoteException
  { balance += amount; }
  public double getCurrentBalance () throws RemoteException
  { return balance; }

This implementation can have any methods you wish, as long as it implements your remote interface. It can even implement multiple remote interfaces. However, it must include the functionality of java.rmi.UnicastRemoteObject and also implement atg.naming.NameContextElement. Dynamo provides a convenient base class that does both, called atg.nucleus.GenericRMIService. This class extends GenericService and adds the RMI capabilities provided by UnicastRemoteObject.

Now compile the BankBalance and BankBalanceImpl classes using any Java compiler. For example:


In order for Java to use these classes remotely through RMI, it must have stub and skeleton classes corresponding to your implementation. The JSDK comes with a command line utility called rmic, which automatically generates the stub and skeleton classes. When you run rmic, you should use as an argument the full class name of the implementation class (not the remote interface class). For example:

rmic BankBalanceImpl

You should see two new class files appear: BankBalanceImpl_Skel.class, and BankBalanceImpl_Stub.class.

Your classes are now ready for use with the RmiServer. But first you must define an instance of your BankBalance object in Nucleus. For example, the following might go into a file:


Exporting an RMI Service

After you create your RMI service, you can use the atg.server.rmi.RmiServer class to make that service available to remote clients through the RMI interface.

To export a service, add its Nucleus name to the exportedServices property of the RmiServer. Dynamo comes with an RmiServer instance already configured at /atg/dynamo/server/RmiServer. You might export your BankBalance component by adding this property setting to your RmiServer component:


You can export as many services as you wish, separating their names with commas. The names must be full Nucleus names—that is, , they must start with a forward slash (/). The next time Nucleus starts after making these changes, your services are available for use through RMI.

Making an RMI Client

After you export your RMI service, you can test it by creating an RMI client. Accessing a remote object from a Java client requires a single RMI call, and the URL to the remote object. The URL for a remote object in Dynamo is formed like this:

rmi://{dynamo host}:{rmi port}{object's Nucleus name}

The standard RMI port for Dynamo is 8860, so a typical URL might look like this:


The following program demonstrates you can access an object using this URL:

import java.rmi.*;
public class BankBalanceClient {
  public static void main (String [] args)
       throws RemoteException, NotBoundException, IOException {
    BankBalance bb = (BankBalance)
      Naming.lookup ("rmi://myhost:8860/yourcomponents/BankBalance");
    System.out.println ("current balance = " + bb.getCurrentBalance ());
    System.out.println ("adding $8.23");
    bb.adjustBalance (8.23);

After starting Nucleus, you can run this program a few times (with the URL changed to match your particular configuration) to prove to yourself that you are accessing the Nucleus object remotely.

loading table of contents...