310 likes | 677 Views
Java RMI. ICS 123 Richard N. Taylor and Eric M. Dashofy* UC Irvine http://www.isr.uci.edu/classes/ics123s02/. * with the usual thanks to David Rosenblum. What Is Java RMI?. Java RMI = Java Remote Method Invocation. A distributed interoperability technology for Java
E N D
Java RMI ICS 123 Richard N. Taylor and Eric M. Dashofy* UC Irvine http://www.isr.uci.edu/classes/ics123s02/ * with the usual thanks to David Rosenblum
What Is Java RMI? Java RMI = Java Remote Method Invocation • A distributed interoperability technology for Java • Packages java.rmi, java.rmi.server and java.rmi.registry • Tools rmic and rmiregistry • Java’s answer to CORBA • Java is the interface definition language • Key limitation: both client and server must be written in Java • Part of Enterprise JavaBeans • Along with JDBC (Java DataBase Connectivity), Java Security, Java Messaging Services, Java Transactions Services, Java IDL, other APIs • like CORBA’s common object services • Detailed documentation is available at http://java.sun.com/
Client/Server Programming with Java RMI (I) • Define an extension of interface java.rmi.Remote • Declare the methods the remote object exports • Declare each such method to throw java.rmi.RemoteException • Define a subclass of java.rmi.server.UnicastRemoteObject that also implements the extension of java.rmi.Remote defined in step 1 • Write a server program that creates an instance of the class defined in step 2 • Use synchronized wherever necessary to make server thread-safe • The server program must register the instance with a registry service • Default registry server is started by running rmiregistry
Client/Server Programming with Java RMI (II) • Compile server program with javac, and then use rmic to generate stub and skeleton classes for the remote object • Stub and skeleton take care of all networking • Limitation of rmic: the remote object class cannot be nested • Write a client program that uses the remote object • The client uses class Naming to obtain a reference to the remote object, using the interface name from step 1 (not the class name) • The client invokes methods on the remote object through this reference • Run the server and then run the client
Client/Server Execution with Java RMI (I) Client Server RegistryServer Server’s machine Client’s machine
Server RemoteObject Client/Server Execution with Java RMI (II) Client RegistryServer Server’s machine Client’s machine
Server RemoteObject Client/Server Execution with Java RMI (III) Client skeleton Naming.rebind(…) RegistryServer Server’s machine Client’s machine
Server RemoteObject Client/Server Execution with Java RMI (IV) Client skeleton stub RegistryServer Naming.lookup(…) Server’s machine Client’s machine
Server RemoteObject Client/Server Execution with Java RMI (V) Remote MethodInvocation Client skeleton stub RegistryServer Server’s machine Client’s machine
Default RMI Registry • Server on machine.com registers object with local RMI registry using some string name Naming.rebind(“remoteObj”, referenceToRemoteObj) • Client refers to objects with URL • Local client: rmi:///remoteObj • Remote client: rmi://machine.com/remoteObj • If client code contains Naming.lookup(“rmi://” + objName) • objName would be “/remoteObj” for local object • objName would be “machine.com/remoteObj” for remote object • Registry is bound to port 1099 by default • Accepts optional port number as argument • Non-default port number must then be added to URL
Example:Air Traffic Control • Air traffic control is divided into several sectors • Each sector is managed by a different controller • Airplanes check in with a controller and then periodically send the controller position reports • The controller analyzes position reports and tells an airplane when its position is too close to other planes
Air Traffic Control:ATC Exception package ATC; public class ATCException extends Exception { public ATCException(String msg) { super(msg); }} • For server-specific exceptions • Different from RemoteException, which is thrown as a result of RMI failure
Air Traffic Control:Position Report Data package ATC; public class PositionReport implements java.io.Serializable { public int Latitude; public int Longitude; public int Heading; public int Airspeed; public PositionReport(int la, int lo, int h, int a) { Latitude = la; Longitude = lo; Heading = h; Airspeed = a; }} • Java objects can be passed in RMIs, as long as they are serializable • Usually accomplished with an implementation of (empty) interface Serializable • Stub and skeleton take care of serialization/deserialization
Air Traffic Control:Remote Controller’s Interface package ATC; import java.rmi.*; public interface ControllerInterface extends Remote { public void CheckIn(int flight) throws RemoteException; public void CurrentPosition(int flight, PositionReport pos) throws RemoteException, ATCException;}
Air Traffic Control:Remote Controller Class (I) package ATC; import java.net.*; // for InetAddressimport java.rmi.*;import java.rmi.server.*; public class Controller extends UnicastRemoteObject implements ControllerInterface { protected String myName; public Controller(String port, String name) throws RemoteException { super(); try { myName = "//" + InetAddress.getLocalHost().getHostName() +":" + port + "/" + name; Naming.rebind(myName, this); } catch (Exception ex) { System.err.println("Exception " + ex); } } …}
Air Traffic Control:Remote Controller Class (II) public class Controller extends UnicastRemoteObject implements ControllerInterface { … public void CheckIn(int flight) throws RemoteException {record existence of new flight } public void CurrentPosition(int flight, PositionReport pos) throws RemoteException, ATCException { if (pos.latitude < -90 || pos.latitude > 90 || pos.longitude < -180 || pos.longitude > 180 || pos.heading < 1 || pos.heading > 360 || pos.airspeed < 50 || pos.airspeed > 700) throw new ATCException("flight " + String.valueOf(flight) + ": invalid position"); else if ( flight is too close to other airplanes ) throw new ATCException("flight " + String.valueOf(flight) + ": dangerous position"); }}
Air Traffic Control:ATC Server package ATC; import java.rmi.*; public class ATCServer { public static void main(String[] args) { try { Controller c = new Controller(args[0], args[1]); } catch (Exception ex) { System.err.println("Exception " + ex); System.err.println("usage: java ATCServer port# controllerName"); } }}
Air Traffic Control:Airplane Client (I) package ATC; import java.rmi.*; public class Airplane { protected int myFlightNumber; protected String myController; protected PositionReport myPosition = new PositionReport(34, -118, 180, 350); public static void main(String[] args) { try { myFlightNumber = Integer.parseInt(args[0]); myController = args[1]; ControllerInterface c = // The interface, not the class! (ControllerInterface)Naming.lookup("rmi://" + myController); c.CheckIn(myFlightNumber); … } … } }
Air Traffic Control:Airplane Client (II) public class Airplane { … public static void main(String[] args) { try { … for (;;) { c.CurrentPosition(myFlightNumber, myPosition); java.lang.Thread.sleep(200);update position } } catch (RemoteException ex) { System.err.println("RemoteException " + ex); } catch (ATCException ex) { System.err.println("ATCException " + ex); } catch (Exception ex) { System.err.println("Exception " + ex); System.err.println("usage: java Airplane flight# controllerName"); } }}
Air Traffic Control:GNUmakefile CLASSFILES=ATC/ATCException.class \ ATC/ATCServer.class \ ATC/Airplane.class \ ATC/Controller.class \ ATC/ControllerInterface.class \ ATC/PositionReport.class REMOTECLASS=ATC/Controller.class RMIFILES=ATC/Controller_Skel.class \ ATC/Controller_Stub.class .SUFFIXES: .java .class all: $(CLASSFILES) $(RMIFILES) $(RMIFILES) : $(REMOTECLASS) rmic ATC.Controller mv -f *.class ATC .java.class : javac $<
Compiling the Example elysees 1332> ls ATC/ GNUmakefile elysees 1333> ls ATC ATCException.java Controller.java ATCServer.java ControllerInterface.java Airplane.java PositionReport.java elysees 1334> gmake all +elysees+ javac ATC/ATCException.java +elysees+ javac ATC/ATCServer.java +elysees+ javac ATC/Airplane.java +elysees+ rmic ATC.Controller +elysees+ mv -f Controller_Skel.class Controller_Stub.class ATC elysees 1335> ls ATC ATCException.class Controller.java ATCException.java ControllerInterface.class ATCServer.class ControllerInterface.java ATCServer.java Controller_Skel.class Airplane.class Controller_Stub.class Airplane.java PositionReport.class Controller.class PositionReport.java elysees 1336>
Running the Example:Local Client and Server Server on elysees (using the default registry port number): elysees 1352> rmiregistry & [1] 5398 elysees 1353> java ATC.ATCServer 1099 LosAngeles & [2] 5407 elysees 1354> Client on elysees: elysees 1355> java ATC.Airplane 100 /LosAngeles ATCException ATC.ATCException: flight 100: invalid position elysees 1356> java ATC.Airplane 100 elysees.ics.uci.edu/LosAngeles ATCException ATC.ATCException: flight 100: invalid position elysees 1357>
Running the Example:Remote Client and Server Server on elysees (using a non-default registry port number): elysees 1352> rmiregistry 1033 & [1] 5398 elysees 1353> java ATC.ATCServer 1033 LosAngeles & [2] 5407 elysees 1354> Client on octavian: octavian 1356> java ATC.Airplane 100 /LosAngeles RemoteException java.rmi.ConnectException: Connection refused to host: [octavian.ics.uci.edu:1099]; nested exception is: java.net.ConnectException: Connection refused octavian 1357> java ATC.Airplane 100 elysees.ics.uci.edu/LosAngeles RemoteException java.rmi.ConnectException: Connection refused to host: [elysees.ics.uci.edu:1099]; nested exception is: java.net.ConnectException: Connection refused octavian 1358> java ATC.Airplane 100 elysees.ics.uci.edu:1033/LosAngeles ATCException ATC.ATCException: flight 100: invalid position octavian 1359>
LegacyProgram ServerProgram RemoteBusinessObject RemoteDataObject RemoteDataObject RemoteBusinessObject Other Possible Architectures • A program or remote object can act as both a client and a server • Example: 3-Tiered Client/Server ClientProgram
Principal SimilaritiesBetween CORBA and RMI • Suitable for distributed, object-oriented, client/server systems • Synchronous interaction via remote procedure call (RPC) • RPC implemented via client stubs and server skeletons, which hide networking and data representation • Objects can be both client and server
Principal Differences Between CORBA and RMI • CORBA • Independent of implementation language • Operation invocations can be formed statically or dynamically • Object implementation binding can be static or dynamic • The CORBA object adapters define various object execution semantics • Many integrated object services are available • RMI • Requires objects to be programmed in Java • Objects are platform independent • Operation invocations are formed statically • Mapping of names to objects is static • Many object services are being defined within Enterprise JavaBeans • Mobile code support
Sidebar Discussion: Dynamic Proxies in Java • Introduced in J2SEv1.3 (JDK1.3) • Created using the java.lang.reflect.Proxy class • Allows dynamic creation of objects that implement an arbitrary interface class without writing code • All methods are called through a single invoke() method, which you implement: • public Object invoke(Object proxy, Method method, Object[] args) throws Throwable • You can get a proxy with a call like this: • ActionListener listener = (ActionListener)Proxy.createProxy(myInvocationHandler, ActionListener.class); • Some detail omitted for clarity
Why are Dynamic Proxies useful? • A generic “listener” for Java events • Consider a generic debugging framework for Swing events that can print every event to the screen • Don’t need to create a new implementation for each type of listener (ActionListener, WindowListener, MouseListener, etc.) • Dynamically create stubs for an RMI-like middleware • This is implemented in a middleware called LJM (Lightweight Java Middleware), which ships with ArchStudio 3 • LJM allows you to do basically what RMI does except without having to use rmic • LJM does not currently support mobile code aspects of RMI
Discussion • How would we extend the example to allow a Controller to give an Airplane instructions for avoiding a dangerous position? • How would we extend the example to allow the Controller to indicate an ATC exception condition outside of a call to CurrentReport()? • How would we extend the example to allow the Controller to tell the Airplane to check in with a different Controller?