Lab 5: Remote Method Invocation
(Summer 2004)

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

I'd like you to think back, just for a minute, to the first day of lab. I know I told you not to take notes, and that it was okay if you didn't "get it" -- it still is. I'll remind you and go over it again.

We talked about objects and classes. We discussed object-oriented design and modeling a system as a collection of objects interacting by message-passing. We 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

  • It provides a mechanism, known as the registry for locating objects.
  • It provides (or makes use of existing Java) mechanisms for replicating and transporting objects -- this is essential, since many messages will be composed of objects.

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

  • Design your classes -- as always
  • Define interfaces for all remote objects
  • Implement, compile, and test each class.
  • Use the RMI compiler, rmic, to create the skeletons and proxies.
  • Start those components that are independent programs, e.g. have a main(), and let the system run.

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.

Bank Account

This assignment is derived from a presentation by Dr. Andrew Ireland in the Distributed SYstems course at Heriot Watt University in the United Kingdom.

We've provided you with the skeleton of a an RMI based server to manage a bank account, as well as a really much of a simple client program. To get it, download Account.zip.

Please complete each in a manner consistent with the description, then, if you have time, please add a GUI, and then convert it into an Applet.

Next Lab

Next lab will be implementing a Chat room using RMI. We've going to use Dattaraj Rao's Chat room example as our reference implementation. We'll provide you with the interface files next week.

ChatClient is the client application and ChatServer is the server daemon. Each should be strarted just as before. Please don't forget about the policy files.


GMK