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.
|