Remote Method Invocation
An Introduction |
Prof. David Bernstein |
Computer Science Department |
bernstdh@jmu.edu |
Marshalling/Unmarshalling
Stubs and Skeletons
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; } }
/** * 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); }
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); } }
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(); } } }
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(); } } }
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)); } }
/** * 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(); } } }
/** * 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(); } } }
One Possible Design