Learn how to use RMI as an alternative to cookies, CGI scripts, LiveScript, and hidden fields to add state to your Java applets
In the past, developers have used several different techniques โ cookies, CGI scripts, and LiveScript, to name a few โ to create persistence and to perform computing on the server. Unfortunately, each of these methods is lacking in one way or another. Letโs take a brief look at each of these techniques before we go any further.
Cookies
- Cookies are a fairly crude (and not widely supported means) to maintain state on a Web site. A cookie is simply a line of data in a file that is stored on a userโs hard drive. Properly configured Web servers access and update the information stored in this file. Cookies currently cannot be shared. For many applications this is not a problem, but as users begin to create relationships with more than one application, the โselfishnessโ of cookies will present a challenge. Cookies also offer little security and can be stolen by rogue software.
CGI scripts
- CGI scripts are the punch cards of the โ90s โ fixed-format sets of instructions that are difficult to maintain and to extend. CGI is currently used on 40 percent of Web sites to track relationships. Unfortunately, CGI scripts do not support the core concept of object-oriented technology โ the data and the method to manipulate the data are related formally โ and places the work of designing and tracking relationships squarely on the shoulders of the designer.
- As consumer demand for interaction among Web sites increases, CGI eventually will be replaced with an architecture that supports the need to create relationships with a Web site as well as relationships among Web sites. JavaSoftโs JECF framework is an excellent example of this type of architecture. How do I use information from two or three different servers to perform some activity?
LiveScript
- LiveScript supports communications over sockets, but without a bit of fancy programming it is not able to transmit portions of a program while the program is in operation. To do this with LiveScript (and also CGI), you would need to develop a line protocol โ a definition of how the bits and bytes move over the wire โ which is time consuming, error prone, and dangerous from a security perspective.
Introducing RMI
Iโve shown you the alternatives. Let me now take a moment to offer up my reasoning for why a change is in order.
When system designers and developers set out to design Internet/intranet solutions, one key factor they must take into consideration is object passing. The ability to pass around objects without having to develop a line protocol greatly reduces software costs. Remote method invocation (RMI) supports the transparent transmission of objects to other nodes on a network. Once the object has been transmitted, the data is processed by the method you called. For example, suppose you have an object containing some data you need to get to the server. RMI will magically send this object to the server by locating the Java object on the server you wish to have act on this data. This process eliminates the need to develop a line protocol. For example:
DataForServer = new DataForServer("a",1.0,3.14,2.718,new Image(), new URL().... );
.... Some steps here to locate the server
remoteServer.processData( dataForServer );
Try performing the same task with the other methods, and I think the benefits of RMI will be clear. Java 1.1 supports serialization and RMI as part of its core services. Unfortunately, many Web browsers are still months away from supporting the core because they are not written in Java. By learning to use RMI, you will be free of all the thorny capability issues with cookies, LiveScript, ActiveX. plug-ins, and other cumbersome technologies. RMI is an architecture to build on โ the others are implementations with ad-hoc architecture.
To address the lag time between the release of JDK 1.1 from JavaSoft and support of JDK 1.1 in browsers, JavaSoftโs RMI group has provided a plug-in for Netscape that lets Navigator 3.01 serialize and deserialize objects, as well as communicate using the RMI protocol. Sorry Internet Explorer users: Youโll have to wait for Microsoft to support JDK 1.1 (expected in the IE 4.0 release later this year).
In this article, we will:
- Compare two techniques for writing objects to a server โ using sockets and using RMI.
- Examine the reading and writing of objects to implement object-oriented databases.
- Rate the performance of RMI for saving objects.
Before you begin
You may need to do a little preparatory work before we get into our RMI discussion. Use the following table to determine what (if anything) you will need to install in order to support RMI (URLs pointing you to the necessities are listed in the Resources section of this article). Netscape users on Windows 95 should download and follow the instructions provided for configuring the RMI plug-in for Netscape (or the appletviewer on 1.02). Depending on your client environment, there are a number of things you may need to do to support RMI. RMI support requires several additional compiled Java classes and some native method code. Also, we obtained good results on Solaris using Sunโs appletviewer contained in the JDK. Sunโs HotJava browser worked well, too.
| Client | Java VM | Install | Hints |
| Windows 95/NT Netscape 3.01 | 1.0.x | Netscape plug-in | Run installation script |
| Windows 95/NT HotJava 1.0 | 1.1 | No installation required |
| Windows 95/NT appletviewer 1.1.1 | 1.1 | No installation required |
| Solaris Netscape 3.0.1 | 1.0.x | Install RMI libraries for 1.02 | Run installation script |
| Solaris HotJava 1.1 | 1.1 | No installation required |
| Solaris appletviewer 1.1.1 | 1.1 | No installation required |
The situation with Microsoft is dependent on when the following products will suport the 1.1.1 JDK.
- IE 4.0 Suite Platform
- IE Preview for 95/NT 4.0
- IE 3.02 for 95 /NT 4.0
- IE 3.01 for Mac
- IE 3.01 for Win 3.1 /NT 3.51
If you have problems installing the serialization classes on your system, see the Resources section of this article for Sunโs FAQ on RMI and object serialization. This section also contains a collection of mail messages JavaSoft has received on RMI and object serialization. Here are a few tips to help you avoid common errors:
Windows 95 users must set the PATH variable to point to the RMI libraries containing the implementation for compiling only. (This is not required for the plug-in.) This step is necessary if you want to do some development with the appletviewer on Windows 95.
When setting the paths in Unix, donโt forget to export them and verify that you do not have other scripts that reset them.
If you have difficulty compiling files and the compiler cannot find files that are in the directory, make sure youโve set your CLASSPATH variable to the directory containing the sources.
The plug-in requires fewer settings of environment variables because certain locations are assumed. You will not have to set the CLASSPATH, the PATH, or the LD_LIBRARY_PATH as often. For our examples, though, you will have to set these variables. Windows 32-bit users can ignore LD_LIBRARY_PATH โ the Unix version of dynamic link libraries (DLLs).
- Windows 32-bit users must instruct the Java virtual machine (JVM) where to search for DLLs by setting the PATH variable.
Next weโll be looking at several examples of how RMI is used within Navigator, the appletviewer, and HotJava.
Saving objects
In past articles, weโve discussed saving objects to a server using sockets to carry serialized objects. The following section is a brief review of this process to help jog your memory. After youโve been sufficiently refreshed, weโll introduce a new technique that uses RMI to perform the same task. Feel free to skip this discussion if you already know how to serialize an object and pass it to a server.
Writing Java objects to a server using sockets
As you may remember, you can save objects using the serialization classes to create a binary representation of the object, which can then be written to a stream and conversely read back into an object of the appropriate type. This approach requires a server program running on the remote system from which the applet was loaded, and the ability to communicate on a port other than the HTTP port. In this case, the port is 2000.
Our example program, WriteObjectsFromSocket.java, reads an object from a client and saves it on the server in a fixed area. This program requires that a server program be running on the server and that an applet for saving and deleting objects communicates over port 2000. To run this example on your own machine so that you can have both the client and the server running locally (not as interesting as running it on the Internet/intranet โ there are better ways to talk to another program on the same machine), download the source code (found in the Resources section of this article) and launch the Java application on your desktop by issuing the following statement in a command-line window. This is an example of Java being used outside of the browser.
java WriteObjectsFromSocket, (Defaults to port 2000)
WriteObjectsFromSocket starts listening on port 2000 for connections from clients. This simple server represents the communication architecture used for many client/server programs. RMI uses the same mechanism but provides abstractions so we donโt have to program at the socket level. I am starting at the socket level here so you can see how persistence can be used independently of RMI. When you run the program, a file containing a serialized object is created on the server from an applet. At this point, you can run the corresponding client piece, ShowSavingAClassNet.java, using the HTML client side for WriteObjectsFromSocket (ShowSavingAClassNet.html). The console should display messages indicating that the program started and is waiting for data.
Note: This program is only an example. To run such a program at a site where multiple users access the site simultaneously would require quite a bit more code. When designing your future projects/products always consider the concurrency issue of multiple users accessing the system.
You can see a log file of activity on this port on the server here. If the applet fails, it is probably because the server program is not running or your site does not allow access to port 2000.
RMI, as you will soon see, reduces the chance of failure by providing a registry that launches objects as they are needed, as well as by working through firewalls.
Writing objects to a server using RMI
In several previous articles, I have described an implementation of a very simple object-oriented database. The database, which we implemented and used in the hierarchical calendar of the Monitor your Web server series (Calendar.java), was built on the sockets technique we just discussed. The Java class containing all the data points about the system is serialized and written to a well-known server port. This approach has two major drawbacks:
Developing a protocol and/or finding class libraries to perform this task for you is somewhat costly.
- This type of solution does not work in many corporate environments because the firewalls will block the attempt to connect to the known port.
As an applet developer, this last item is a big issue for you. Unfortunately, client/server computing on the Web is greatly hampered by firewalls. Luckily, RMI for both JDK 1.0.2 and JDK 1.1 can detect communication failures caused by a firewall and then use an alternate communication transfer mechanism, such as POST to a CGI script, which will have a bigger probability of success. For example, when a normal user attempts to access a server containing an applet that requires a connection to a port on that system, a firewall often can prevent access. However, if the user has RMI support, the client will make another attempt to connect using POST methods transparently. Of course, this type of functionality requires a CGI script to be installed.
This feature alone provides a wealth of new development possibilities. To demonstrate the broad deployment potential of RMI, we are going to check out an applet running in Netscape Navigator that saves objects on remote servers. Before we do that, though, letโs begin with the simple process of writing a java.util.Date object to a remote server using RMI.
Writing and reading Java objects from a remote server
Your server can be configured to allow users to read and write objects via RMI. The following examples can be compiled with the buildit script, which requires a Korn shell. If you do not have a Korn shell available for your system, modify the script to perform the equivalent operations in the DOS command-line language. Mortice Kern Systems (MKS) sells a bunch of Unix utilities, like Korn shell and Make, which I highly recommend for all advanced Java programmers. Of course, you can also compile these applications with your favorite IDE.
Warning: This application runs only on those browsers that support RMI.
To write an object, run WriteSimpleUsingRMI.html. To read the object back, run ReadSimpleUsingRMI.html.
Now that you understand how to create an object, serialize it, and send it to a server, thereโs only one question left: How do you use it without getting into trouble? RMI isnโt totally free. With every RMI request there are communication costs. What are these communication costs? I hope to answer some of that in the next section.
Performance considerations
When youโre writing objects to a server, performance becomes an issue that warrants a closer look. In this section weโre going to examine some metrics on serialize, transmit, and deserialize times. The ShowWritedouble applet/program, which contains the files shown below, writes twenty-five double objects to a disk file. (A double object is an instance of the class java.lang.Double().) The files with RMI in their name perform reading and writing of serialized objects over the network instead of to a disk file. It is especially interesting to compare the applets so you can get a better understanding of how persistence is used to serialize the object and write it to disk explicitly in the write-to-disk example, while it is implicit in the RMI examples. If you want to get an idea of how long it takes, generally speaking, to save an object, I recommend you modify the applet to write other data types.
The programs and applets used for this example are:
| Applet | Source Code |
| WriteDoubleUsingRMI.html | WriteDoubleUsingRMI.java |
| ReadDoubleUsingRMI.html | ReadDoubleUsingRMI.java |
| WriteDoubleUsingSockets.html | WriteDoubleUsingSockets.java |
The complete source code and HTML are provided in the ShowSavingdouble.java and ShowSavingdouble.html files.
Note: The applet to write on the local system is not usable from the browser for security reasons.
To use this applet on your system, you must modify the write path (found in the HotJava properties window) to allow local applets using the appletviewer to write files in the /tmp hierarchy. In the write path files, enter:
acl.write=/tmp.
The following table provides an indication of relative performance of RMI using three different methods for saving an object:
A file saved to the local system.
A file saved to the remote system.
- A remote server that provides an applet, but does not allow communication on any port other than the HTTP port.
Numbers for JDBC and CORBA implementations are not included. The client I used to obtain these values was a 133MHz Windows 95 Digital HiNote Ultra II; the server was a 167MHz Ultra-1 running Solaris.
| Time in ms |
| Saved to a file on the local file system | 36 |
| Save to remote server on a specified port with a socket connection | 550 |
| Write and read using RMI to transport the object and object serialization to save the object with no firewall preventing communication | 160 (write) 50 ( read) |
Both of the servers produce output data, which you can view on the console or save to a file.
I captured a trace of the reading and writing transactions with snoop; click here to view the file.
Conclusion
Now that weโve thoroughly explored the concept of RMI (not an easy task I might add), I thought it would be helpful to provide you with some key points about the subject at hand:
If you are designing a solution to a business or scientific problem and can use Java for both the client and server, RMI can really help you out. Using RMI, you can forego the creation of yet another line protocol and deal with objects on local servers and remote servers that can easily be moved around the network with little programming required.
You can replace any CGI script by using RMI to implement an object that responds to an RMI requestโs program, which provides more direct processing.
Design classes so method calls contain the minimum required data. This technique allows your applets or programs to be moved to a remote client-server model.
RMI is well suited for providing interfaces to legacy systems with a mechanism that allows you to easily call methods on the remote server that can then call native methods.


