Recall the Remote Proxy Pattern to achieve Distributed Objects on the network
Java's Remote Method Invocation (RMI) implements this pattern
The Proxy is called a ``Stub''
The RealSubject has a ``Skeleton'' that talks across the network to the Stub
Both are automatically produced by the rmic compiler
The RealSuject is named an ``Impl'
Both the Stub and the Impl implement the same interface (e.g. Product)
This guarantees that they have the same methods, hence the same look-and-feel (e.g. get())
The Client has a variable of type Product interface, and makes ordinary calls
But the variable will actually be the instantiation of the Stub
Any call to the Stub will get sent (serialized) across the network to the Skeleton
Skeleton makes actual call on Impl, then returns any (serialized) results to the Stub
The Client thinks it is dealing directly with the Impl, as if it were on the same computer
The registry program is started in the background: rmiregistry &
The Server is started in the background: java ProductServer &
The Server news the Impl, and registers it
This allows many Client programs to interact with the distributed object: java ProductClient
RMI: Class Hierarchy [89]
import java.rmi.* provides a hierarchy of classes
Programmer only provides ProductImpl application and Product interface
Both Stub and Impl implement the same Product interface
Stub and Skeleton are automatically produced: rmic ProductImpl
RMI: Product Application [90]
Next page provides an example Product application
Product interface only has a getDescription() method, which throws an exception
ProductImpl extends UnicastRemoteObject, implements Product
Constructor throws an exception
Stub and Skeleton are automatically produced: rmic ProductImpl
ProductServer news two Impls and registers with Naming.rebind() using a primary key
ProductServer runs in the background
ProductClient locates the Skeleton with Naming.lookup() using URL and primary key
The lookup instantiates the Stub, which the Client uses
Product Application: Sources [91]
// Product.java
import java.rmi.*;
interface Product extends Remote {
public String getDescription() throws RemoteException;
}
// ProductImpl.java
// javac ProductImpl.java
// rmic ProductImpl (=> ProductImpl_Skel.class, ProductImpl_Stub.class)
import java.rmi.*;
import java.rmi.server.*;
public class ProductImpl extends UnicastRemoteObject implements Product {
private String descr;
public ProductImpl(String d) throws RemoteException { descr = d; }
public String getDescription() {
return "I am a " + descr + ". Buy me!";
}
}
//ProductServer.java
//To run: rlogin snazzy (for example)
// rmiregistry & (one time only)
// java ProductServer &
import java.rmi.*;
import java.rmi.server.*;
public class ProductServer {
public static void main(String srgs[]) {
System.setSecurityManager(new RMISecurityManager());
try {
ProductImpl p1 = new ProductImpl("Blackwell Toaster");
ProductImpl p2 = new ProductImpl("ZapXress Microwave Oven");
Naming.rebind("toaster",p1);
Naming.rebind("microwave",p2);
} catch (Exception e) { System.out.println("Error: "+e); }
}
}
// ProductClient.java - run on local machine after starting server
import java.rmi.*;
import java.rmi.server.*;
public class ProductClient {
public static void main(String[] args) {
System.setSecurityManager(new RMISecurityManager());
String url = "rmi://gold/"; // for example
try {
Product c1 = (Product)Naming.lookup(url+"toaster");
Product c2 = (Product)Naming.lookup(url+"microwave");
System.out.println(c1.getDescription());
System.out.println(c2.getDescription());
} catch (Exception e) { System.out.println("Error: "+e); }
}
}
Supplier Application: Deployment [92]
Supplier application should be converted to RMI (see Exercise)
Server X is started in the background
Server creates an Impl, registers with Naming, and has a Skeleton
Client runs, looks up the registered Impl using Naming, gets a Stub
Client uses Stub to mutate, which goes across the network to the Skeleton
Skeleton calls mutate on Impl, which then updates the database/file on disk
Remote/Persistent Objects: Supplier Exercise [93]
Use your Supplier application, with either SQL or Serialize for persistence as usual
Supplier method signatures go into a Supplier interface, which extends Remote
Rename Supplier as SupplierImpl
SupplierImpl extends UnicastRemoteObject (not Observable anymore), implements Supplier
Put exceptions on interface methods and SupplierImpl constructor
Modify ProductServer to be SupplierServer
Modify ProductClient to be SupplierClient
Test:
unix% rmiregistry & unix% java SupplierServer & unix% java SupplierClient msdos% start rmiregistry msdos% start java SupplierServer msdos% java SupplierClient