Project Notes


Project: RMI: A Simple RMI Application
Author: JBuilder Team
Company: borland.com
Description:
This sample will guide you through the steps of creating a simple RMI application using JBuilder

Steps to creation of an RMI application in JBuilder:

Step summary:

  1. Create an interface (SimpleRMIInterface.java).
  2. Create a class that implements the interface (SimpleRMIImpl.java).
  3. Create a server that creates an instance of this class (SimpleRMIServer.java).
  4. Create a client that connects to the server object using Naming.lookup() (SimpleRMIClient.java).
  5. Set the RMI compiler options on the RMI implementation file (right-click, Properties... | check "Generate RMI stub/skeleton" | enter "-v1.2" in "Options").
  6. Compile the project (Project | Rebuild project "SimpleRMI.jpr").
  7. Start the RMI registry (Tools | RMIRegistry).
  8. Start the server class (check VM java.rmi.server.codebase and java.rmi.server.policy settings, Run | Run project).
  9. Run the client program (right-click SimpleRMIClient.java, select Run).
Detailed steps:
  1. Create an interface.
    The interface created for this example is SimpleRMIInterface.java. It contains only one method; the method takes no arguments and returns an object of type java.util.Date. Note two things about this interface:
    1. It extends the java.rmi.Remote interface (all interfaces used in RMI must do this).
    2. The method throws a java.rmi.RemoteException (every method in a remote object's interface must specify this exception in its "throws" clause; this exception is a superclass of all RMI exceptions that can be thrown. See the JDK 1.1 final docs (in the java.rmi section) for a complete list of exceptions that can be thrown.

  2. Create a class that implements the interface.
    In this example, the implementation is found in SimpleRMIImpl.java. This class must extend java.rmi.UnicastRemoteObject and must implement the interface you created in step 1. In this example, the only method that needs to be implemented is getDate(), which returns the current date and time on the system. Note 2 things about the constructor:
    1. The call to super().
    2. The call to Naming.rebind(name, this). This call informs the RMI registry that this object is available with the name given in "String name".
    Other than that, this object simply implements all the methods declared in the interface.

  3. Create a server that creates an instance of the "impl" class.
    In this example, the server class is SimpleRMIServer.java. In this case, the server is pretty simple. It does 2 things:
    1. Installs a new RMISecurityManager (Note that RMI uses a different security manager from the security manager used for applets).
    2. Creates an instance of the SimpleRMIImpl class, and gives it the name "SimpleRMIImpl instance". The SimpleRMIImpl object takes care of registering the object with the RMI registry. After this code is run, the object will be available to remote clients as "//<your server here>/SimpleRMIImpl instance". (and in fact, this is how the client connects to it in step 4).

  4. Create a client that connects to the server object using Naming.lookup().
    In this example, the client class is SimpleRMIClient.java. The client first installs a new RMI Security Manager (see previous step), then uses the static method Naming.lookup() to get a reference to the remote object. Note that the client is using the interface to hold the reference and make method calls. You should make sure you've created your interface before you try to build the client, or you'll get "class not found" errors when you try to compile your client.

  5. Set the compile options on the RMI implementation file.
    In the IDE, Right-click the SimpleRMIImpl.java file in the navigator pane and choose "Properties..." In the properties dialog, check "Generate RMI stub/skeleton", enter "-v1.2" in the Options field, and click OK.

  6. Compile the project by selecting Project | Rebuild project "SimpleRMI.jpr" from the menu.
  7. Start the RMI registry.
    Okay. You're done with development at this point; you've built all the code you need to run this example. Now you're setting up the environment so that you can run it. From within JBuilder, you can select Tools | RMIRegistry to start the RMI registry. The next time you look at the tools menu, you will notice there is a check next to this menu option. This is your clue that the registry is running. Selecting it again will close the RMI registry.

    Alternatively, you can start the RMI registry from the command-line. The name of the executable varies by platform, but typically begins with "rmiregistry" and resides in the jre/bin directory of your JDK installation.

    Note: The RMI registry must be started before you can start your server.

  8. Start the RMI server program.
    Beginning with JDK 1.2, it is necessary to grant an RMI server special security rights in order for it to listen for and accept client RMI requests over a network. Typically, these rights are specified in a java security policy file defined by a special property (java.security.policy) passed via a command-line argument to the VM of the server. Similarly, a property specifying the location of classes used by the server (java.rmi.server.codebase) is also passed to the server's VM via a command-line argument.

    Before running the server, select Project | Project properties... and select the "Run" tab of the dialog to inspect the parameters passed to the server's VM. Check that the java.security.policy and java.rmi.server.codebase properties point to the proper locations of the security policy file and server classes for your JBuilder installation ("file:/usr/local/jbuilder/samples/RMI/SimpleRMI.policy" and "file:/usr/local/jbuilder/samples/RMI/classes/" by default, respectively).

    Next, select "Run | Run project" from the menu to start the rmi server. When the message "SimpleRMIImpl ready" appears, the server is ready to accept client requests. A message like "connection refused" indicates that either your rmiregistry is not running, or the java.security.policy parameter does not point to the proper location of the SimpleRMI.policy file.

    For more information about the JDK 1.2 RMI and security model, refer to the special notes at the end of this document.

  9. Run the RMI client program.
    Beginning with JDK 1.2, it is necessary to grant an RMI client special security rights in order for it to connect to an RMI server over a network. Typically, these rights are specified in a java security policy file defined by a special property (java.security.policy) passed via a command-line argument to the VM of the client.

    Before running the client, select Run | Configurations... | "Run SimpleRMI Client" | <Edit> to inspect the parameters passed to the client's VM. Check that the java.security.policy points to the proper location of the security policy file ("file:/usr/local/jbuilder/samples/RMI/SimpleRMI.policy" by default).

    Next, to run the client, either right-click on SimpleRMIClient.java in the project pane and select "Run" from the menu, or click on the small arrow next to the "Run project" button on the toolbar and select the "Run SimpleRMI client" run configuration.

    SimpleRMIClient asks the RMI registry to lookup a reference to the rmi object named "SimpleRMIImpl instance" created by SimpleRMIServer. After SimpleRMIClient then uses this reference to invoke the method declared in the SimpleRMIInterface interface just as if the object were a local object.
    It receives a java.util.Date object from the server (indicating the current time on the server) and displays its contents.

After the RMI application has been created, you probably want to deploy the client and server to separate locations. To accomplish this, first use the Archive Builder to create separate jars for the client files and for the server files.

Set up the client deployment

  1. Wizards | Archive Builder...
  2. Set the Archive type to 'Basic' then Next
  3. Set the Name and the File (e.g., "/opt/jbuilder4/samples/RMI/deploy/RMIClient.jar") then Next
  4. Set "Include required classes and known resources"
  5. Click "Add File..." and select SimpleRMI.policy from the RMI project directory
  6. Click "Add Class..." and select SimpleRMIClient, SimpleRMIInterface, and SimpleRMIImpl_Stub from com.borland.samples.rmi
  7. Click Finish.
Set up the server deployment

Repeat the previous steps, this time deploying the following files to a jar for the server (e.g., "/opt/jbuilder4/samples/RMI/deploy/RMIServer.jar"):

Next, follow the directions below to run the RMI client and server programs on separate computers over a TCP/IP network.

  1. Start an rmiregistry process (on the server), if you haven't already, by selecting Tools | RMIRegistry from the menu.
  2. Start the server application by selecting Run | Run Project. The message "SimpleRMIImpl ready" indicates the server is ready to accept client requests.
  3. Copy the previously deployed client directory to another machine that has either JBuilder or JDK 1.2 (or above) installed properly to run java applications.
  4. Start the client on the client machine by typing "java -cp [jar file for client] -Djava.security.policy=jar:file:[jar file for client]!/SimpleRMI.policy com.borland.samples.rmi.SimpleRMIClient [server_hostname or IP address]". The client will receive a java.util.Date object from the server (indicating the current time on the server) display its contents.

Addendum: RMI and JDK 1.2 Security

The JDK 1.2 security model is more sophisticated than the model used for JDK 1.1. JDK 1.2 contains enhancements for finer-grained security and requires code to be granted specific permissions to be allowed to perform certain operations.

RMI uses sockets to communicate between the processes, however if the RMI application uses the RMISecurityManager, then you need to modify the security policy so that the application is allowed to accept and connect to the other RMI application through the sockets.

The easiest way to setup the security mechanism to enable RMI is to modify the java.policy file under the java\jre\lib\security directory of your JDK installation directory. Open it with a text editor and modify the line that says:

permission java.net.SocketPermission "localhost:1024-", "listen";

to

permission java.net.SocketPermission "localhost:1024-", "listen, accept, connect";

This should allow you to run the server application and the client application on a local machine.

Please note that java.policy file controls the overall Java security policy. Alternatively you can create a file named '.java.policy' that resides in the user's home directory. On the Windows platform, the user's home directory typically translates to the Windows installation directory, while on Unix the user's home directory refers to the actual user's home directory.

For a more thorough explanation on JDK 1.2 Security, please take a look at this excellent tutorial at JavaSoft's site.