Now that we have defined our RMI code, the next step in the process
is to set it up as an RMI Service. This can be accomplished two ways:
editing the appropriate xinetd/inetd configuration files
directly, or using a GUI editor that is used for manipulating the
configuration files, which is typically supplied along with the OS. The
GUI tool that is bundled along is dependent on the flavor of Unix or
Linux in use. In this particular case, we will be using YaST,
which is bundled with Novell's SuSE Linux.
Figure 3 shows the SuSE Linux Control Center, and we are interested in
Network Services.

Figure 3. YaST Control Center GUI
Opening "Network Services" will result in the configuration screen
shown in Figures 4 and 5, which enables you to add, edit, or delete
network services, as well as turn services on or off individually.

Figure 4. YaST list of services

Figure 5. Editing a service in YaST
We add our RMI Service by providing details for the following
fields.
Service name - The name of a valid service.
Socket type - The choices are stream,
dgram, raw, rdm (reliably
delivered message), or seqpacket (sequenced packet
socket).
Protocol - A protocol listed in /etc/protocols, which is
some type of network protocol such as IP, ICMP, TCP, and UDP.
Flags - wait/nowait - Wait applies to
datagram sockets only. All other socket types should have the "nowait"
option in this entry. Nowait entries are used for multithreaded servers
that free their sockets after each request so they can continue receiving
more requests on the same socket.
User - The name of the user the server will run as.
Group - Specify the group so that the server can run with a
different group ID than the one specified in the password file for that
user.
Server - The path and name of the program to be
executed.
Server Arguments - Command-line arguments for the
server program that is being run.
Comment - Any relevant comment that describes what this
service does.
After entering appropriate data and clicking the Accept button, a
file called rmi-date-server will be created in the
/etc/xinetd.d directory. The content of this file looks
like:
#RMI Date Server service rmi-date-server
{
socket_type = stream
protocol = tcp
wait = no
user = root
group = users
server = /opt/jdk1.5.0_01/bin/java
server_args = -Djava.rmi.server.hostname=192.168.0.2
-classpath /home/Article/RMI/bin
com.article.jn.service.DateServer
}
Next, the rmi-date-server needs to be listed as a
service in the /etc/services configuration file. This is
accomplished by editing (using any text editor) the file to add the
following entry. Note that editing this file will require root
access. The format is:
rmi-date-server <port>/<protocol>,
In this entry, port is the port number for the service's
local registry.
Now that the configuration of xinetd has been modified,
the service needs to be restarted to read the new configuration changes.
To do this, send the HUP (hangup) signal to the
xinetd/inetd process. This is accomplished by determining
the process ID with following command:
$ ps -ef | grep xinetd
root 2332 1 0 Jun 30 ? 0:02 /usr/sbin/xinetd -s
In this case, the process ID for xinetd is 2332. Now, to
send the hangup signal for the xinetd process, issue the
following command:
$su root
$ kill -HUP 2332
Now xinetd is all set to launch the Java 5 RMI service
when a client attempts to connect to the port configured in the
/etc/services file. To test this out, we can run a simple
client that does the following:
Registry registry =
LocateRegistry.getRegistry(host, port);
DateService proxy = (DateService)
registry.lookup("ServiceInterface");
System.out.println("received message from proxy: "
+ proxy.getDate());
This will result in an output to the client's standard out. As Figure
6 confirms, a java process is spawned by xinetd, which
listens in on a specified port (9900 in this case) for client
connections.

Figure 6. Active listening ports
Stubless RMI
One of the best features of the new Java 5.0 RMI is that static
generation of stubs using rmic is not required
anymore. This feat is accomplished by the dynamic generation of stub
classes at runtime. However, if the client is not running Java 5.0, then
rmic must still be used to pre-generate stub classes for
remote objects. Dynamic stub generation is made possible by two
different changes that were part of previous JDK releases. First, the
revision of the JRMP protocol in Java 2 enabled RMI to work without
skeletons. Second, the introduction of Dynamic Proxies in Java 1.3
obviated the need for client-side stubs.
The JDK
release notes provide the following explanation for stubless RMI:
When an application exports a remote object (using the constructors or
the static exportObject methods of the classes
java.rmi.server.UnicastRemoteObject or
java.rmi.activation.Activatable) and a pre-generated stub
class for the remote object's class cannot be loaded, the remote
object's stub will be a java.lang.reflect.Proxy instance
(whose class is dynamically generated) with a
java.rmi.server.RemoteObjectInvocationHandler as its
invocation handler. An existing application can be deployed to use
dynamically generated stub classes whether or not pre-generated stub
classes exist by setting the system property
java.rmi.server.ignoreStubClasses to "true".
If this property is set to "true," then pre-generated stub classes are never
used.
Conclusion
We zipped through the three most important and powerful features of
RMI in Java 5.0. SSL security makes RMI client-server communication
truly secure; the stubless RMI makes deployment a breeze; and the
ability to expose RMI applications as a Unix service allows RMI services
to be launched on demand.
Over a period of ten years, RMI has evolved incrementally to become
a robust distributed computing technology. These additions will
push forth RMI as the de facto solution when there is a need for
developing distributed, loosely-coupled, object-oriented
applications.