next up previous contents
Next: About this document ... Up: Case Study Previous: Observable/Persistent Objects   Contents

Remote(RMI)/Persistent Objects [88]




\begin{picture}(540,180)(50,560)\thicklines
\put(100,680){\line( 3, 1){ 60}}
...
...(260,670){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twlrm net}}}
\end{picture}



$\bullet$ Recall the Remote Proxy Pattern to achieve Distributed Objects on the network

$\bullet$ Java's Remote Method Invocation (RMI) implements this pattern

$\bullet$ The Proxy is called a ``Stub''

$\bullet$ The RealSubject has a ``Skeleton'' that talks across the network to the Stub

$\bullet$ Both are automatically produced by the rmic compiler

$\bullet$ The RealSuject is named an ``Impl'

$\bullet$ Both the Stub and the Impl implement the same interface (e.g. Product)

$\bullet$ This guarantees that they have the same methods, hence the same look-and-feel (e.g. get())

$\bullet$ The Client has a variable of type Product interface, and makes ordinary calls

$\bullet$ But the variable will actually be the instantiation of the Stub

$\bullet$ Any call to the Stub will get sent (serialized) across the network to the Skeleton

$\bullet$ Skeleton makes actual call on Impl, then returns any (serialized) results to the Stub

$\bullet$ The Client thinks it is dealing directly with the Impl, as if it were on the same computer

$\bullet$ The registry program is started in the background: rmiregistry &

$\bullet$ The Server is started in the background: java ProductServer &

$\bullet$ The Server news the Impl, and registers it

$\bullet$ This allows many Client programs to interact with the distributed object: java ProductClient



RMI: Class Hierarchy [89]




\begin{picture}(470,360)(15,435)\thicklines
\put( 15,515){\framebox (130,40){...
...\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twlrm $<<$Class$>>$}}}
\end{picture}



$\bullet$ import java.rmi.* provides a hierarchy of classes

$\bullet$ Programmer only provides ProductImpl application and Product interface

$\bullet$ Both Stub and Impl implement the same Product interface

$\bullet$ Stub and Skeleton are automatically produced: rmic ProductImpl



RMI: Product Application [90]



$\bullet$ Next page provides an example Product application

$\bullet$ Product interface only has a getDescription() method, which throws an exception

$\bullet$ ProductImpl extends UnicastRemoteObject, implements Product

$\bullet$ Constructor throws an exception

$\bullet$ Stub and Skeleton are automatically produced: rmic ProductImpl

$\bullet$ ProductServer news two Impls and registers with Naming.rebind() using a primary key

$\bullet$ ProductServer runs in the background

$\bullet$ ProductClient locates the Skeleton with Naming.lookup() using URL and primary key

$\bullet$ 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]


\begin{picture}(480,475)(60,364)\thicklines
\put(380,410){\oval(42,22)}
\put(...
...715){\makebox(0,0)[lb]{\raisebox{0pt}[0pt][0pt]{\twlrm Client C}}}
\end{picture}



$\bullet$ Supplier application should be converted to RMI (see Exercise)

$\bullet$ Server X is started in the background

$\bullet$ Server creates an Impl, registers with Naming, and has a Skeleton

$\bullet$ Client runs, looks up the registered Impl using Naming, gets a Stub

$\bullet$ Client uses Stub to mutate, which goes across the network to the Skeleton

$\bullet$ Skeleton calls mutate on Impl, which then updates the database/file on disk



Remote/Persistent Objects: Supplier Exercise [93]



$\bullet$ Use your Supplier application, with either SQL or Serialize for persistence as usual

$\bullet$ Supplier method signatures go into a Supplier interface, which extends Remote

$\bullet$ Rename Supplier as SupplierImpl

$\bullet$ SupplierImpl extends UnicastRemoteObject (not Observable anymore), implements Supplier

$\bullet$ Put exceptions on interface methods and SupplierImpl constructor

$\bullet$ Modify ProductServer to be SupplierServer

$\bullet$ Modify ProductClient to be SupplierClient

$\bullet$ Test:

  unix% rmiregistry &
  unix% java SupplierServer &
  unix% java SupplierClient

  msdos% start rmiregistry
  msdos% start java SupplierServer
  msdos% java SupplierClient


next up previous contents
Next: About this document ... Up: Case Study Previous: Observable/Persistent Objects   Contents
Ted Billard 2006-09-26