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