Return to the Lecture Notes Index

15-111 Lecture 27 (Wednesday, April 25, 2007)

Introduction to Java's Remote Method Invocation (RMI) Facility

We've talked about objects and classes. We've discussed object-oriented design and modeling a system as a collection of objects interacting by message-passing. We've said that the messages, and their replies, are represented in Java as method invocations and their return values.

Up until today, although conceptually messages, many of you may have viewed method invocations as just a part of the syntax -- just a way to "do something". But today, we're going to see that they are, in fact, real live messages -- and that they can travel through the ether all around the world and beyond.

We're going to discuss you to send an object on another system, perhaps on the other side of the earth a message. And, the very surprising thing is that we'll do ti the very same way we sent messages yesterday -- by invocing methods on the objects. In fact, once we've gotten thing set up, you, yourself, might even forget that the objects are located on different machines.

Java's RMI mechanism is absolutely beautiful and nearly transparent. By the way, that's what we call it when the details of something are so well abstracted that we don't know that they're there -- transparency. It is a distributed systems term.

I've worked with other mechanisms for building distributed systems, including Remote Procedure Calls (RPC), which are popular in C, and the Common Object Request Broker Architecture (CORBA), which is popular in systems composed of many languages. None of them -- and I mean none of them -- are as beautiful as Java's RMI.

In fact, it was Java's RMI that lead me to begining programming in a serious way in Java. Until I used RMI for the first time, I viewed it as a "toy language for the Web". Then, suddenly, I realized that it was a very powerful system for developing distributed systems -- systems with components spread out over significant distance.

In fact, Java was originally developed as part of a project at Sun Microsystems, Inc., which is now known as Jini -- a framework for buidling distributed embedded systems. That is to say computer systems, which are part of physical devices, such as automobiles and appliances, which are connected via a network, such as a wireless LAN, and function cooperatively.

Understanding RMI will place a whole new world at your fingertips. You'll be able to write prograsm for computational resources the size of the Internet -- just as you write those for a single PC.

An Overview of the Client-Server and Peer-to-Peer Architecture

There are many different ways of organizing and classifying the relationship abong objects in a system. Two of the most popular categories are peer-to-peer and client-server.

In peer-to-peer arrangements, no single object is designed to be more of a contributor than the others. Objects might participate in each and every decision communally -- this is a truly distributed system (at least under a definition proposed by a person named Lamport), or they might participate in only some subset of the work. But, the bottom line, is that the loss of one is no more important than the loss of any other. peer-to-peer arrangements are either true team relationships, or just groups of equals.

Another, slightly more common paradigm, is the client-server organization. Under this arrangement, certain objects, servers are special -- they have capabilities or resources unavailable to others and, by design, do work or make decisions, for others, the clients.

Client server systems are more popular, because the coordination among the systems is much more straight-foward -- there is a boss. But, they tend not to scale as well -- since there's only so much any one boss can do.

Regardless, Java's RMI can support both arrangements. But, we're going to focus on the client-server organization.

RMI Capabilities

In addition to what you might expect -- the ability to send a message from one object, to another object, over the network, Java's RMI provides a couple of other important services

Organization of an Application using RMI

An application that uses RMI will look, in many ways, much like any other application -- it will model a system using objects, which will be constructed according to class specifications.

But, there is a bit of a complication -- objects don't usually send messages to each other over a network. They send them by finding the code associated with the method and running it, passing in parameters, as necessary.

We could change this for RMI and have two different methods for objects to communication -- but this is more complicated under-the-hood than it might seem. So, instead, Java makes use of intermediates, known as stubs.

There are two such intermediates: the proxy and the skeleton. Let's consider a remote object. An object on some system other than our own. The objects on our system only know how to send messages to other objects. So, they invoke local methods on the proxy object for the remote object. It then, being specially designed for the purpose, sends network messages to the remote object's system.

Once, on this system, the messages get sent to the remote object's skeleton object. This skeleton object, being specially designed for the purpose, then sends the messages to the "remote" object, which is local on the system. The "remote" object then returns its results to the skeleton, which sends them back over the network to the proxy, which returns them in a normal, local, fashion to the object that originally invoked the remote method.

The stubs, the skeleton and the proxy, perform what is known as marshalling. They package the data so it can be sent over the network as well as unpackage it.

It is important to realize that, although all of this work is going on behind the scenes, the object that made the remote method invocation has no idea what it has done. It is much like going into a store, asking for something, and waiting for the clerk to return from the backroome -- but, unknown to you, while you are waiting, the clerk drives across the city, has someone else make what you need, comes back in through the back door, and hands it to you.

Do We Have To Write The Stubs? That Sounds Like a Lot of Work.

Actually, no. You can provide an interface specification that descibes the features of the classes that you want to expose to the outside work. A Java utility, the RMI compiler, rmic can take these interface specifications and build the skeleton and broxy stubs for you -- automatically.

All you have to do is to make sure that the clients have the proxies and the servers have the stubs. And, to be honest, Java actually has a mechanism by which it can use a Web server to automatically deliver these, on-demand! We won't use that this week, but it is actually there and works!

How Does the Proxy Know How To Find Objects on Other Systems?

Java provides an application called the RMI registery. This is basically a piece of software that keeps track of where objects live. When remote objects are created, they export themselves by registering themselves with a registery. Clients then check with the registry to discover where the object lives.

In the case of client-server architecture, the client will often lookup the server's object by name. And then, send a message to this object -- which really serves as a front door. In many cases, it returns a reference to another object which will do the real work. Sometimes, it creates an additional such object for each client (for those interested, that's called the factory pattern).

RMI Application Design and Implementation Process Overview

A Walk Through the "Hello World" RMI from Sun

This example is taken from http://java.sun.com/j2se/1.3/docs/guide/rmi/getstart.doc.html.

But, please pull down Hello.zip. We've removed the embedded paths and, as discussed earlier, configured it to move the proxy by hand instead of with HTTP (these machines don't run Web servers).

We basically we're doing the same walkthough. The only catch is that the paths on our system to java are broken. Check the path to javac and use the same path, explicitly, for java.

Additionally, as a minor localization, we used a local URL for the applet, not a remote one -- in other words, we just used the HTML file's path and name.