JBuilder 2007 Sample: A Simple RMI application

Abstract: This sample will guide you through the steps of creating a simple RMI application using JBuilder 2007

    Download:

    Steps to import this sample into JBuilder:

1. Copy the zip file containing this project to your hard drive.

2. Import the project into JBuilder (File | Import | Existing Projects into Workspace | Next | Select Archive File | Browse -- select the .zip file).

    Steps to run this sample:

1. Ensure that the RMIRegistry external tool is configured correctly. (Run | External Tools | External Tools | Program | RMIRegistry), and ensure that the location points to an existing rmiregistry.exe. If you installed JBuilder 2007 to its default location of C:\JBuilder2007, it will already be correctly configured. Otherwise you will need to change the value.

2. Start the RMI registry (Run | External Tools | External Tools | Program | RMIRegistry | Run).

3. Start the server class (Run | Run | Java Application | SimpleRMIServer | Run)

4. Run the client program (Run | Run | Java Appliaction | SimpleRMIClient | Run)

    Detailed steps to create this sample:

    1. Create an interface.

The interface created for this example is com.codegear.samples.rmi.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 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 com.codegear.samples.rmi.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 com.codegear.samples.rmi.SimpleRMIServer.java. In this case, the server is pretty simple. It does two 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 com.codegear.samples.rmi.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.

    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...", then select "RMI / JNI". Check "Generate RMI stub/skeleton", enter "-v1.2" in the Options field, and click OK.

    6. 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 (Run | External Tools | External Tools | Program | RMIRegistry | Run) to start the RMI registry. The console view will show the running RMI registry. You can stop the RMI registry by clicking on the "Terminate" toolbar button.

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.

    7. 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 "Run | Run | Java Application | SimpleRMI Server" and select the "Arguments" tab. 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:${workspace_loc:com.codegear.samples.SimpleRmi/bin}\" and "file:${workspace_loc:com.codegear.samples.SimpleRmi/SimpleRmi.policy" 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.

    8. Run the RMI client program.

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 | Run | Java Application | SimpleRmiClient" and select the "Arguments" tab. Check that the java.security.policy points to the proper location of the security policy file ("file:${workspace_loc:com.codegear.samples.SimpleRmi/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.

    Addendum: RMI and JDK Security:

The JDK allows for fine-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 Security, please take a look at this excellent tutorial at java.sun.com.