JMU
Remote Method Invocation
An Introduction


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu


Motivation
Motivation (cont.)

Marshalling/Unmarshalling

images/marshaling.gif
Motivation (cont.)
A Design for Remote Method Invocation
A Design for Remote Method Invocation (cont.)

Stubs and Skeletons

images/stubs_skeletons.gif
A Design for Remote Method Invocation (cont.)
An Example of RMI

The Core Classes/Interfaces

javaexamples/remoteobjects/Course.java
import java.io.Serializable;


/**
 * A Course 
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class Course implements Serializable
{
    private int    number;
    private String department, title;

    /**
     * Explicit Value Constructor
     *
     * @param department  The department code
     * @param number      The course number
     * @param title       The course title
     */
    public Course(String department, int number, String title)
    {
        this.department = department;
        this.number     = number;
        this.title      = title;
    }

    /**
     * Get the course designation
     *
     * @return  The course designation
     */
    public String getDesignation()
    {
        return department+number;
    }

    /**
     * Get the course title
     *
     * @return  The course title
     */
    public String getTitle()
    {
        return title;
    }
}
        
An Example of RMI (cont.)

The Core Classes/Interfaces (cont.)

javaexamples/remoteobjects/CourseDatabase.java
/**
 * Methods that must be implemented by a database of Course objects
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public interface CourseDatabase
{
    /**
     * Add a Course
     *
     * @param course   The Course to add
     */
    public void add(Course course);


    /**
     * Get a Course
     *
     * @param course   The Course to add
     */
    public Course get(String department, int number);


    /**
     * Remove a Course
     *
     *
     * @param department   The department code
     * @param number       The course number
     */
    public void remove(String department, int number);

}
        
An Example of RMI (cont.)

The Core Classes/Interfaces (cont.)

javaexamples/remoteobjects/CourseDatabaseImpl.java
import java.util.*;


/**
 * The implementation of a database of Course objects
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class CourseDatabaseImpl implements CourseDatabase
{
    private HashMap<String, Course>     db;


    /**
     * Default Constructor
     */
    public CourseDatabaseImpl()
    {
        db = new HashMap<String, Course>();
    }

    /**
     * Add a Course
     *
     * @param course   The Course to add
     */
    public void add(Course course)
    {
        db.put(course.getDesignation(), course);
    }

    /**
     * Get a Course
     *
     * @param course   The Course to get
     */
    public Course get(String department, int number)
    {
        return db.get(department+number);
    }

    /**
     * Remove a Course
     *
     * @param department   The department code
     * @param number       The course number
     */
    public void remove(String department, int number)
    {
        db.remove(department+number);
    }
}
        
An Example of RMI (cont.)

The Stub

javaexamples/remoteobjects/CourseDatabaseStub.java
import java.io.*;
import java.net.*;



/**
 * A simple stub for a remote database of Course objects
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class CourseDatabaseStub implements CourseDatabase
{
    private ObjectOutputStream    out;
    private ObjectInputStream     in;
    private Socket                s;


    /**
     * Constructor
     */
    public CourseDatabaseStub(String host, int port)
    {
       try 
       {
          s = new Socket(host, port);
            
          out = new ObjectOutputStream(s.getOutputStream());
          in  = new ObjectInputStream(s.getInputStream());
       } 
       catch (IOException ioe) 
       {
          ioe.printStackTrace();
       }
    }

    /**
     * Add a Course
     *
     * @param course   The Course to add
     */
    public void add(Course course)
    {
       try 
       {
          out.writeObject("add");
          out.writeObject(course);
          out.flush();
       } 
       catch (IOException ioe) 
       {
          ioe.printStackTrace();
       }
    }

    /**
     * Get a Course
     *
     * @param course   The Course to add
     */
    public Course get(String department, int number)
    {
       Course       course;

       course = null;

       try 
       {
          out.writeObject("get");
          out.writeObject(department);
          out.writeInt(number);
          out.flush();
            
          course = (Course)in.readObject();
       } 
       catch (IOException ioe) 
       {
          ioe.printStackTrace();
       } 
       catch (ClassNotFoundException cnfe) 
       {
          cnfe.printStackTrace();
       }
        
       return course;
    }

    /**
     * Remove a Course
     *
     * @param department   The department code
     * @param number       The course number
     */
    public void remove(String department, int number)
    {
       try 
       {
          out.writeObject("remove");
          out.writeObject(department);
          out.writeInt(number);
          out.flush();
       } 
       catch (IOException ioe) 
       {
          ioe.printStackTrace();
       }
    }

}
        
An Example of RMI (cont.)

The Skeleton

javaexamples/remoteobjects/CourseDatabaseSkeleton.java
import java.io.*;
import java.net.*;
import java.util.*;


/**
 * A simple skeleton for a database of Course objects.
 *
 * Note: This approach does not use a registry.
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class CourseDatabaseSkeleton implements Runnable
{
    private int                     port;
    private Thread                  controlThread;
    private CourseDatabase          implementation;
    private ObjectInputStream       in;
    private ObjectOutputStream      out;

    /**
     * Constructor
     */
    public CourseDatabaseSkeleton(CourseDatabase  implementation,
                                  int             port)
    {
       this.implementation = implementation;
       this.port = port;
    }

    /**
     * Add a Course
     */
    public void add() throws ClassNotFoundException, IOException
    {
       Course    course;

       // Get arguments from the stub
       course = (Course)in.readObject();

       // Make the call to the implementation
       implementation.add(course);
    }

    /**
     * Get a Course
     */
    public void get()  throws ClassNotFoundException, IOException
    {
       Course     course;
       int        number;
       String     department;


       // Get arguments from the stub
       department = (String)in.readObject();
       number     = in.readInt();

       // Make the call to the implementation
       course = implementation.get(department, number);

       // Return course to the stub
       out.writeObject(course);
       out.flush();
    }

    /**
     * Read a method invocation from the stub
     */
    public void readFromStub()
    {
       String    method;

       try 
       {
          method = (String)in.readObject();
          if (method.equals("add"))         add();
          else if (method.equals("get"))    get();
          else if (method.equals("remove")) remove();

       } 
       catch (IOException ioe) 
       {
          // Ignore
       } 
       catch (ClassNotFoundException cnfe) 
       {
          // Ignore
       }
    }

    /**
     * Remove a Course
     */
    public void remove()  throws ClassNotFoundException, IOException
    {
       int        number;
       String     department;

       // Get arguments from the stub
       department = (String)in.readObject();
       number     = in.readInt();

       // Make the call to the implementation
       implementation.remove(department, number);
    }


    /**
     * Entry point for the thread
     */
    public void run()
    {
       ServerSocket      ss;
       Socket            s;


       try 
       {
          ss = new ServerSocket(port);
          s = ss.accept();

          in  = new ObjectInputStream(s.getInputStream());
          out = new ObjectOutputStream(s.getOutputStream());

          while (true) 
          {
             readFromStub();
          }
       } 
       catch (IOException ioe) 
       {
          ioe.printStackTrace();
       }
    }

    /**
     * Start this skeleton.
     */
    public void start()
    {
        if (controlThread == null)
        {
            controlThread = new Thread(this);
            controlThread.start();
        }
    }
    
}
        
An Example of RMI (cont.)

The Factory

javaexamples/remoteobjects/CourseDatabaseFactory.java
import java.io.*;

/**
 * A factory that can be used to create objects that implement the
 * CourseDatabase interface
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class CourseDatabaseFactory
{

    public static final int    port = 9100;
    public static final String host = "localhost";
    
    /**
     * Create a CourseDatabase
     */
    public static CourseDatabase createCourseDatabase()
    {
        return (new CourseDatabaseImpl());
    }

    /**
     * Create a stub that can access a remote CourseDatabase 
     * server
     */
    public static CourseDatabase createCourseDatabaseStub()
                                 throws IOException
    {
        return (new CourseDatabaseStub(host, port));
    }
}
        
An Example of RMI (cont.)

The Client Driver

javaexamples/remoteobjects/ClientDriver.java
/**
 * The client in a homegrown example of remote method invocation
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class ClientDriver
{

    /**
     * The entry point
     *
     * @param args  The command line arguments
     */
    public static void main(String[] args)
    {
        Course               course;
        CourseDatabase       db;


        try {

            db = CourseDatabaseFactory.createCourseDatabaseStub();

            db.add(new Course("CS",139,"Algorithm Development"));
            db.add(new Course("CS",240,"Data Structures and Algorithms"));
            db.add(new Course("CS",349,"Developing Multimedia Content"));
            db.add(new Course("CS",462,"Network Applications Development"));

            course = db.get("CS",462);
            System.out.println(course.getDesignation()+"\t"+
                               course.getTitle());

            System.out.flush();

        } catch (Exception ex) {

            ex.printStackTrace();
        }
    }
}
        
An Example of RMI (cont.)

The Server Driver

javaexamples/remoteobjects/ServerDriver.java
/**
 * A server that uses a homegrown version of remote method invocation
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class ServerDriver
{

    /**
     * The entry point
     *
     * @param args  The command line arguments
     */
    public static void main(String[] args)
    {
       CourseDatabase             implementation;
       CourseDatabaseSkeleton     skeleton;

       try 
       {
          implementation = new CourseDatabaseImpl();
          skeleton       = new CourseDatabaseSkeleton(implementation, 
                                                   CourseDatabaseFactory.port);
          skeleton.start();
       } 
       catch (Exception ex) 
       {
          ex.printStackTrace();
       }
    }
}
        
Implementation of Stubs and Skeletons
Object Location Management
Object Location Management (cont.)

One Possible Design

images/rmi.gif
Object Location Management (cont.)