Transcript Lecture 10

Internet Software
Development
Remote Method Invocation
Paul Krause
Lecture 10 - RMI
 Introduction
to RMI
 Simple Example - “DivideServer”
 Demo of this example
 Review a more complex example “StudentEnrollment”
What is RMI?
 A high-level
networking technology for
distributed Java applications
 Allows a Java object executing on one
machine to remotely invoke methods in an
object executing on a second machine
 Such method calls have the appearance of
operating on objects in the same program
Skeletons and Stubs
Client Machine
C
Client
Stub
Java Virtual Machine
and RMI System
Server Machine
S
Server
Skeleton
Java Virtual Machine
and RMI System
Stub
 Presents
same interfaces as remote object
 Works with JVM and RMI to serialise
arguments in the remote method call
 Receives results from the remote method call
and returns them to the client object
Skeleton
 Receives
the remote method call and
associated arguments
 Works with JVM and RMI to deserialize
arguments in the remote method call
 Invokes appropriate methods in the remote
object
 Receives return value (if any) from the method
call, serializes it and returns it to the client
 No longer needed in Java 2
Referencing remote objects

A Registry object maintains a mapping from Server
names to remote object references


We will use the example “DivideServer”
The remote object is named via a URL using the RMI
protocol:





rmi://host:port/server
host - IP address or name of server machine
port - optional port number of the Registry on above
server - name of the remote server
e.g. rmi://127.0.0.1/DivideServer
Key Classes and Interfaces
 Remote
Interface
 Naming Class
 RemoteObject Class
 RemoteServer Class
 UnicastRemoteObject Class
 RemoteException Class
Remote Interface
 In
the java.rmi package
 Contains no constants or methods
 It is used to designate which interfaces are
remote 

remote interfaces must extend java.rmi.Remote
remote objects must implement a remote interface
Naming Class
 In
the java.rmi package
 Three methods to associate names with
remote objects (used at the Server side):



static void bind(String name, Remote robj)
static void rebind(String name, Remote robj)
static void unbind(String name)
 One
method to obtain a name for a remote
object (used at the Client side):

static Remote lookup(String url)
Remote Objects

RemoteObject


RemoteServer


extends java.lang.Object to provide correct behaviour for
remote objects
an abstract class that extends RemoteObject. Defines the
methods needed to create and export remote objects
UnicastRemoteObject

a concrete subclass of RemoteServer. Extend this class to
make a remote object
Simple Client/Server Application
 Client


program takes three arguments:
IP address or name of remote server
two numbers
 The
two numbers are passed to the server
 The server divides one into the other and
returns the result
 From: JavaBeans Programming from the
Ground Up, Joseph O’Neil and Herb Schildt
DivideServer.java
import java.rmi.*;
public interface DivideServer extends Remote {
double divide(double d1, double d2) throws
RemoteException;
}
Remote Interfaces

The remote interface must extend Remote
 Remote methods can throw a RemoteException
 We now require a server that implements the
interface
 By convention, we name the implementation of
DivideServer


DivideServerImpl
Remote objects must extend UnicastRemoteObject
DivideServerImpl.java
import java.rmi.*;
import java.rmi.server.*;
public class DivideServerImpl
extends UnicastRemoteObject implements DivideServer {
public DivideServerImpl( )
throws RemoteException {
}
public double divide(double d1, double d2)
throws RemoteException {
return d1/d2;
}
}
DivideServerApp.java
 This
is the main program for the server side
 Its primary function is to bind the name
“DivideServer” to an instance of
DivideServerImpl
 Note that we need to start this server program
running before the client program is invoked
DivideServerApp.java

Core part is:
DivideServerImpl divideServerImpl;
divideServerImpl = new DivideServerImpl();
Naming.rebind("DivideServer", divideServerImpl);
DivideServerApp.java
import java.net.*;
import java.rmi.*;
public class DivideServerApp {
public static void main(String args[]) {
try {
DivideServerImpl divideServerImpl;
divideServerImpl = new DivideServerImpl();
Naming.rebind("DivideServer", divideServerImpl);
}
catch(Exception ex) {
ex.printStackTrace();
}
}
}
DivideClient.java
 Looks
up the object that is bound to the RMI
URL
 The lookup method of the Naming class
returns an object of type Remote
 This must then be cast to a DivideServer in
order to be able to access the divide method
DivideClient.java
DivideServer divideServer;
divideServer =
(DivideServer)Naming.lookup(divideServerURL);
// Invoke remote method and display results
double result = divideServer.divide(d1, d2);
System.out.println("The result is: " + result);
DivideClient.java
import java.rmi.*;
public class DivideClient {
public static void main(String args[]) {
try {
// Make rmi URL to name DivideServer
String divideServerURL;
divideServerURL = "rmi://" + args[0] + "/DivideServer";
// Obtain reference to that remote object
DivideServer divideServer;
divideServer = (DivideServer)Naming.lookup(divideServerURL);
DivideClient.java
// Display numbers
System.out.println("The first number is: " + args[1]);
double d1 = Double.valueOf(args[1]).doubleValue();
System.out.println("The second number is: " + args[2]);
double d2 = Double.valueOf(args[2]).doubleValue();
// Invoke remote method and display results
double result = divideServer.divide(d1, d2);
System.out.println("The result is: " + result);
}
catch(Exception ex) {
ex.printStackTrace();
}
}
}
Executing the Application
 Use
javac to compile all files
 Open a command prompt and change to the
working directory
 Use the rmic compiler to produce a stub class
for the remote server class:

rmic -v1.2 DivideServerImpl
 Copy

all files to the client machine
exercise: You don’t need all of them on the client.
Which ones do you need
Executing the Application

open a command prompt on the server and start the
RMI registry:


open a second command prompt on the server
machine and run the server application to bind the
remote server object to the registry


rmiregistry
java DivideApp
Start the client (again, use a command prompt):

java DivideClient server1 8 2
The result
You should get the following output at the client’s
command prompt:
The first number is: 8
The second number is: 2
The result is: 4.0
 Notes:



Use IP address 127.0.0.1 if experimenting on a single
machine
On Windows 2000 you can find out the IP address of a
machine using hostname and ipconfig/all