Java News Brief
March 2000 Issue
Headlines:
Java Technical
Insight of the Month -
Remote Method
Invocation
Visit The Java News Brief
Archive for past issues of the JNB.
OCI Educational
Services
Java
Technical Insight of the Month
Remote
Method Invocation
By Jeff Brown, Senior
Software Engineer, Object Computing, Inc.
Overview
Remote Method Invocation (RMI) is a technology that is used to implement pure Java distributed systems. This article will present a mid to high level overview of what RMI is, how it relates to some other similar technologies, and will touch on some of the technical details involved in implementing a system built using RMI. While some technical coding details will be discussed, they will be discussed for the most part at a high level, and some working sample code will be covered.
RMI allows Java applications to access "remote" objects across a distributed system. Clients and servers in an RMI application can be distributed over a network, or can reside in virtual machines running on the same physical machine. For the most part, the clients and servers are not necessarily concerned with exactly where their distributed counterparts reside. Typically a client needs some bootstrap mechanism to connect to a distributed server. Once connected, the client can gain references to remote objects and doesn't really need to be concerned with the details about exactly where the remote objects actually exist. That is, a server may give a client a reference to an object that actually exists on a third machine somewhere on the network and the client doesn't know or care about this detail. The client need only be aware that it has a reference to a remote object. Once a client has a reference to a remote object, the object can be manipulated in much the same way that a local object may be manipulated. There are some additional error conditions that the client needs to consider, but outside of that the client may not need to make a distinction between local objects and remote objects.
RMI is certainly not the only technology that can be used to implement a distributed system in Java. There are a number of other ways to accomplish some of the same goals.
A system could be implemented using TCP sockets to allow distributed components of the system to communicate with each other. While the Java networking API greatly simplifies this type of socket communication compared to writing BSD type socket code in a language like C, the application developer is still left to implement custom application protocols for the components to use and this method does not really provide an object oriented way to access objects distributed across the network.
Another approach might be some sort of Remote Procedure Call (RPC) library. RPCs may greatly simplify the burden of marshaling parameters back and forth compared to writing lower level socket communication. However, RPC is not well suited for a truly object-oriented distributed system. RPC leads to a more procedural approach. Both TCP sockets and RPC allow distributed components to communicate with each other, but there is no notion of a reference to a remote object.
For a truly object-oriented distributed system, one technology that might be considered is the Common Object Request Broker Architecture (CORBA). In many ways CORBA is similar to RMI but there are some critical differences. RMI is limited to Java-to-Java systems. If a requirement is for a Java client to communicate with a C++ server for example, RMI doesn't meet the need. If however the system is going to be all Java, there may be compelling reasons that RMI is the better choice. One issue is simplicity. Writing a distributed system using RMI does not require the use of any special interface language. Everything is written in Java. Writing a distributed system using CORBA requires the use of at least one other language known as the Interface Definition Language (IDL). IDL is used to define the distributed API. In RMI this is written in Java like any other Java interface. Another issue to consider may be cost. Everything that is needed to implement an RMI system is available free as part of the standard Java Development Kit. While there are freely available CORBA implementations, many implementations can be very expensive.
The Registry
The registry is a simple server
that acts as a place from which distributed objects are dispatched. In order for
an object to be available for remote access, the object must be registered with
a registry. You can write your own registry and integrate registry
services directly into your own application, or you can use the RMI registry
that comes with the Java Development Kit (rmiregistry).
The Server
A server that is going to export an
object is responsible for registering the remote object with the registry.
The registry must be running on the same physical machine where the server is
running. In order for an object to be registered with the registry, the
object must either extend UnicastRemoteObject or it must be exported with
UnicastRemoteObject.exportObject(). A server may export as many objects as
it likes. There is no need to have a separate server for each remote
object. An object might be registered with the registry like this...
Naming.rebind("MyRemoteObject", ro);
System.setSecurityManager(new RMISecurityManager());
The Client
A client may get a reference to a
remote object from a registry anywhere on the network. The registry may be
on the same machine as the client, but does not need to be. Once a client
gets a reference to a remote object, the client can manipulate that object as if
it were a local object. There are ways for a client to query the registry
to find out what objects are registered there (Naming.list()). Once the
client knows the name of the remote object (either by the fact that the object
has a well known name, or the client has queried the registry) the client may
request a reference to the object like this.
RemoteClock clock = (RemoteClock)Naming.lookup("rmi://hostname:1099/MyRemoteClock");
RemoteClock clock = (RemoteClock)Naming.lookup("rmi://hostname:1099/MyRemoteClock");
...is effectively the same as...
RemoteClock clock = (RemoteClock)Naming.lookup("MyRemoteClock");
The Remote Object
In order for an object to be
accessed via RMI the object must be registered with the registry. In order
for an object to be registered with the registry the object must either extend
UnicastRemoteObject or it must be exported with a call to
UnicastRemoteObject.exportObject(). In either case, the object needs to
implement a Remote interface that defines the methods that will be exposed
remotely. Every remote method must declare that it throws RemoteException.
The RMIC Compiler
The RMI compiler (rmic) is
used to generate stubs and skeletons for remote objects. The stub is the
client side proxy to the remote object and the skeleton is the server side proxy
to the remote object. These two objects handle all of the data marshaling.
rmic will generate RemoteObjectName_Stub and RemoteObjectName_Skel where
RemoteObjectName is the name of the remote object. Your code never
references either the skeleton or the stub classes.
Parameters And Return Types
Once a client has a
reference to a remote object, it can call any method on the object defined in
its Remote interface. If the method returns an Object, that Object must be
Serializable. If the method takes any Object parameters, then those
parameters must also be Serializable. Note that as Objects are passed back
and forth like this, they are all being passed by value, not by reference.
A remote method can return a reference to another remote object in which case it
is essentially passed by reference.
RemoteClock
A remote interface that defines a
single method.
// RemoteClock.java
import java.rmi.*;
public interface RemoteClock extends Remote {
public String getCurrentTime() throws RemoteException;
}
RemoteClockImpl
A class to implement
RemoteClock. This is the remote object.
// RemoteClockImpl.java
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
public class RemoteClockImpl extends UnicastRemoteObject
implements RemoteClock {
public RemoteClockImpl() throws RemoteException {
}
public String getCurrentTime() throws RemoteException {
return new Date().toString();
}
}
MyServer
A simple server to provide an instance
of RemoteClockImpl.
// MyServer.java
import java.rmi.*;
public class MyServer {
public static void main(String[] args) {
System.setSecurityManager(new RMISecurityManager());
try {
RemoteClockImpl clock = new RemoteClockImpl();
Naming.rebind("MyRemoteClock", clock);
} catch (Exception exc) {
exc.printStackTrace();
System.exit(1);
}
}
}
MyClient
A client to access the RemoteClock
contained in MyServer.
// MyClient.java
import java.rmi.*;
public class MyClient {
public static void main(String[] args) {
try {
RemoteClock clock = (RemoteClock)Naming.lookup("MyRemoteClock");
if(clock == null) {
System.err.println("There was a problem locating the remote clock.");
} else {
String time = clock.getCurrentTime();
System.out.println("current time on server is: " + time);
}
} catch (Exception exc) {
exc.printStackTrace();
System.exit(1);
}
}
}
The Policy File
For the sake of simplifying the
example we will use a very liberal security policy. This is probably not
appropriate for a production environment. Our policy file looks like this.
grant {
// Allow everything for now
permission java.security.AllPermission;
};
Compiling the files
Each of the .java files
will need to be compiled.
javac MyClient.java MyServer.java RemoteClock.java RemoteClockImpl.java
rmic RemoteClockImplThis should generate RemoteClockImpl_Stub.class and RemoteClockImpl_Skel.class. Note that if the remote class is in a package, the fully qualified class name must be passed to rmic.
Running The Example
To run the example
three things have to be done. The registry must be started, the server
must be run to export the remote object and a client must be run to access the
remote object. To start the rmiregistry on Unix:
rmiregistry &
start rmiregistry
java -Djava.security.policy=/devel/testing/policy MyServer
java MyClient
current time on server is: Sun Mar 19 14:37:46 CST 2000
OCI Educational Services
OCI has one of the most comprehensive OO training curriculums in the country. Clients contract group training that is either taught at the client site or at an OCI Education Center in Tempe, AZ or St. Louis, MO. We encourage you to check our our Object-Oriented Technology Curriculum shown below: (click on course titles for online descriptions)
![]() |
For more information or to register, email
training.
Object Computing, Inc. is a Sun Authorized Java Center in St. Louis and a Member of the Object Management Group, OMG. OCI specializes in distributed computing using object-oriented and web-enabled technologies and provides Consulting, Education, and Product Development services to clients nation-wide. For more information contact us at 314-579-0066 or email info.
For Information on Employment
Opportunities
Click here OCI CAREER
OPPORTUNITIES
or call 1-888-962-4624
or email hr
The
Java News Brief is a monthly newsletter. The
purpose and intent of this publication is to advance Java, provide technical
value, and to announce available OCI Java services. If you would prefer to
not receive this newsletter or would like to subscribe please email JNB and enter SUBSCRIBE or
UNSUBSCRIBE within the Subject line.
Copyright (c)
2000. Object Computing, Inc. All rights reserved. Java and
all Java-based marks are trademarks or registered trademarks of Sun
Microsystems, Inc. in the United States and other countries. Object
Computing, Inc. is independent of Sun Microsystems,
Inc.