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:
- Create an interface (SimpleRMIInterface.java).
- Create a class that implements the interface (SimpleRMIImpl.java).
- Create a server that creates an instance of this class (SimpleRMIServer.java).
- Create a client that connects to the server object using Naming.lookup() (SimpleRMIClient.java).
- Set the RMI compiler options on the RMI implementation file (right-click, Properties... | check "Generate RMI stub/skeleton" | enter "-v1.2" in "Options").
- Compile the project (Project | Rebuild project "SimpleRMI.jpr").
- Start the RMI registry (Tools | RMIRegistry).
- Start the server class (check VM java.rmi.server.codebase and java.rmi.server.policy settings, Run | Run project).
- Run the client program (right-click SimpleRMIClient.java, select Run).
Detailed steps:
- 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:
- It extends the java.rmi.Remote interface (all
interfaces used in RMI must do this).
- 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.
- 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:
- The call to super().
- 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.
- 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:
- Installs a new RMISecurityManager (Note that RMI
uses a different security manager from the security manager used for applets).
- 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).
- 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.
- 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.
- Compile the project by selecting Project | Rebuild project "SimpleRMI.jpr" from the menu.
- 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.
- 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.
- 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
- Wizards | Archive Builder...
- Set the Archive type to 'Basic' then Next
- Set the Name and the File (e.g., "/opt/jbuilder4/samples/RMI/deploy/RMIClient.jar") then Next
- Set "Include required classes and known resources"
- Click "Add File..." and select SimpleRMI.policy from the RMI project directory
- Click "Add Class..." and select SimpleRMIClient, SimpleRMIInterface, and SimpleRMIImpl_Stub from com.borland.samples.rmi
- 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"):
- SimpleRMIServer, SimpleRMIInterface, SimpleRMIImpl, and SimpleRMIImpl_Stub class files, and the SimpleRMI.policy file
Next, follow the directions below to run the RMI client and server programs on separate computers over a TCP/IP network.
- Start an rmiregistry process (on the server), if you haven't already, by selecting Tools | RMIRegistry from the menu.
- Start the server application by selecting Run | Run Project. The message "SimpleRMIImpl ready" indicates
the server is ready to accept client requests.
- 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.
- 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.