230 likes | 386 Views
Algorithm Programming 2 89-211 Distributed Programming in Java. Bar-Ilan University 2004-2005 תשס"ה by Moshe Fresko. RMI : Remote Method Invocation.
E N D
Algorithm Programming 289-211Distributed Programming in Java Bar-Ilan University 2004-2005 תשס"ה by Moshe Fresko
RMI : Remote Method Invocation • RPC : Remote Procedure Call. Intended to call methods remotely by passing parameters and getting results. The call can be done to programs written in any language and in any environment. • RMI : Allows to write distributed objects in Java, in a simple and direct manner. • Advantageous of RMI: • In RPC only certain Data Types can be passed as parameters. In RMI Parameters and Return Value of a Method call can be Java Objects. • Mobile Behavior: RMI can pass objects between Server and Client, that can be known only to one side. • For security Java’s built in security mechanisms are used. • Existing/Legacy System Connections. • JNI: Java’s Native Method Interface • JDBC: Java Data Base Connection • Distributed Garbage Collection. • RMI is multi-threaded.
RMI • RMI applications: Server Application + Client Application • Server: Creates remote objects, makes them accessible, and waits for the clients to invoke methods • Client: Gets remote references, and invokes methods on them. • RMI provide mechanism for Client and Server to communicate and pass information back and forth. • Distributed Object Application • Locate remote objects • Communicate with remote object • Load class bytecodes for objects that are passed around
Remote Interfaces and Objects • Remote Objects: Objects that have methods that can be called across VMs. • Remote Interface: An interface definition for the methods to be called remotely. • A Remote Interface • Extends the interface java.rmi.Remote • Each method declares java.rmi.RemoteException in its throws definition • A Remote Object is treated differently from regular Objects • It passes a Stub instead of the real Object • Note: Stub is the “Remote Proxy” Design Pattern of RMI • Stub acts as the local representative of the remote reference • A stub implements the same Remote interfaces as the real Object
Creating Distributed Applications • Design and Implement the Components • Define the Remote Interfaces • Implement the Remote objects’ classes • Implement the Clients • Compile Sources and Generate Stubs • javac compiler for compiling source files • rmic compiler to create stubs for the remote objects • Make classes network accessible • To make remote interfaces, stubs, and other classes, accessible via a Web Server • Start the applications • Running RMI remote object registry, the server, and the client
Designing a Remote Interface • // Compute.javapackage compute ;import java.rmi.* ;public interface Compute extends Remote { Object executeTask(Task t) throws RemoteException ;} • // Task.javapackage compute ;import java.io.Serializable ;public interface Task extends Serializable { Object execute() ;} Client Submit task Compute Engine (Server) Return result
Implementing Remote Interface • Implementation Class • Declares the Remote Interface • Defines the Constructor for the remote Object • Provides implementation for each remote method of the Interface • Remote Object creation and install • Create and install a Security Manager • Create one or more instances of Remote object • Register at least one of the Remote objects with the RMI remote registry
Compute Engine example package engine ; import java.rmi.* ; import java.rmi.server.* ; import compute.* ; public class ComputeEngine extends UnicastRemoteObject implements Compute { public ComputeEngine() throws RemoteException { super() ; } public Object executeTask(Task t) { return t.execute() ; } public static void main(String[] args) { if (System.getSecurityManager()==null) System.setSecurityManager(new RMISecurityManager()) ; String name="//host/Compute" ; try { Compute engine = new ComputeEngine() ; Naming.rebind(name,engine) ; System.out.println("ComputeEngine bound") ; } catch (Exception e) { System.err.println("ComputeEngine exception: "+e.getMessage()) ; e.printStackTrace() ; } } }
Declare the Remote Interface • public class ComputeEngine extends UnicastRemoteObject implements Compute • UnicaseRemoteObject • Supplies implementation for some Object methods ( equals, hashCode, toString ) • Includes constructors and static methods used to “export” a remote object and so make the remote object available to receive incoming calls from Client • Instead of UnicastRemoteObject java.rmi.activation.Activatable can be used. It can be used to construct remote objects that can execute on demand. • Remote object can be exported explicitly by calling either UnicastRemoteObject.exportObject or Acrivatable.exportObject
Compute Engine • Define the Constructor • public ComputeEngine() throws RemoteException { super() ; } • Provide implementation for each remote method • public Object executeTask(Task t) { return t.execute() ; }
Passing Objects in RMI • Arguments or Return Values can be almost any type, including … • Primitive Data Types • Passed by Copy • Local Objects (if they are Serializable) • Passed by Copy using serialization • Changes done will not affect the original Object • Remote Objects • Passed by reference. A remote object reference is a stub, which is a client side proxy that implements the complete set of remote interfaces that the remote object implements. • Only Remote Interface methods are available to the Client. • Changes done will affect the Original Object
Creating a Security Manager • Security Manager determines if the Downloaded code has access to the local file system, or can perform any other privileged operations • If there is no Security Manager, RMI will not download classes for objects received as parameters, return values, or exceptions, from places other than the local class path. • RMISecurityManager enforces a similar security policy as the applets. • if (System.getSecurityManager()==null) { System.setSecurityManager ( new RMISecurityManager() ) ;}
Make the Remote Object Available • Compute engine = new ComputeEngine() ; • UnicastRemoteObject ctor exports the newly created object to the RMI runtime. • RMI registry: (Remote object name service) • A particular Remote Object for finding references to Remote Objects. • java.rmi.Naming interface is used as an API for binding, or registering, and looking up remote objects in the registry. • String name=“//host/Compute” ;try { … Naming.rebind(name,engine) ; } catch …
Binding with Naming.rebind() • Naming.rebind(name,engine) : Takes two parameters. First one is a URL-formatted unique name for the object. Second one a reference to the remote object itself. • name=“//host/Compute” • host: The Name or IP-address of the Server Machine. (Default is localhost). • It may include a port number. (Default is 1099). For example: “//host:8080/objectname” • A stub for the “engine” object is created in the server. The Remote Implementation Objects never leave the VM where they are created. • For security reasons, “bind”, “unbind”, “rebind” can be called only to the registry running in the same host. “lookup” can be called from any host. • No thread is needed to keep the Server up, since as long as a remote Object is referenced either by registry or a client, RMI system takes care of keeping it up.
Client Program rmi registry Naming.lookup Client Program ComputePi Naming.rebind comp.execute task ClientEngine Server
Client: ComputePi // ComputePi.java package client ; import java.rmi.* ; import java.math.* ; import compute.* ; public class ComputePi { public static void main(String[] args) { if (System.getSecurityManager()==null) System.setSecurityManager(new RMISecurityManager()) ; try { String name="//"+args[0]+"/Compute" ; Compute comp = (Compute) Naming.lookup(name) ; Pi task = new Pi(Integer.parseInt(args[1])) ; BigDecimal pi = (BigDecimal) (comp.executeTask(task)) ; System.out.println(pi) ; } catch (Exception e) { System.err.println("ComputePi exception: "+e.getMessage()) ; e.printStackTrace() ; } } }
Client: Pi // Pi.java ; package client ; import java.math.* ; import compute.* ; public class Pi implements Task { // Constants used in Pi computation private static final BigDecimal ZERO = BigDecimal.valueOf(0) ; private static final BigDecimal ONE = BigDecimal.valueOf(1) ; private static final BigDecimal FOUR = BigDecimal.valueOf(4) ; // Rounding mode to use during Pi Computation private static final int roundingMode= BigDecimal.ROUND_HALF_EVEN ; private int digits ; // Digits of precision after the decimal Point public Pi(int digits) // Ctor gets the precision { this.digits=digits ; } public Object execute() // Calculates Pi in method of Task interface { return computePi(digits) ; } // Compute the value of Pi // Machin's formula : pi/4 = 4*arctan(1/5)-arctan(1/239) public static BigDecimal computePi(int digits) { int scale = digits+5 ; BigDecimal arctan1_5 = arctan(5,scale) ; BigDecimal arctan1_239 = arctan(239,scale) ; BigDecimal pi = arctan1_5.multiply(FOUR).subtract(arctan1_239).multiply(FOUR) ; return pi.setScale(digits,roundingMode) ; } // … Continues in the next page
Client: Pi // Compute the arctan // arctan(x)=x-(x^3)/3+(x^5)/5-(x^7)/7+... public static BigDecimal arctan(int inverseX, int scale) { BigDecimal term ; BigDecimal invX = BigDecimal.valueOf(inverseX) ; BigDecimal invX2 = BigDecimal.valueOf(inverseX*inverseX) ; BigDecimal numer = ONE.divide(invX,scale,roundingMode) ; BigDecimal result = numer ; int i=1 ; do { numer = numer.divide(invX2,scale,roundingMode) ; int denom = 2*i+1 ; term = numer.divide(BigDecimal.valueOf(denom),scale,roundingMode) ; if ((i%2)!=0) result = result.subtract(term) ; else result = result.add(term) ; i++ ; } while (term.compareTo(ZERO)!=0) ; return result ; } }
Compiling the Program • We have: Package or Directory File Names Includes compute Compute.java interface compute Task.java interface engine ComputeEngine.java server appl. client ComputePi.java client appl. client Pi.java client appl. • Scenario • Developer will build a Jar file of Compute and Task interfaces • Developer will write implementation of Compute interface and put a Service on a machine. • Clients will use the Compute and Task interfaces to develop a task and a Client program that uses this Service
Compiling the Program • Build the JAR Files for Interfaces • javac compute\Compute.javajavac compute\Task.javajar cf compute.jar compute\*.class • Note: These compiled files must be put into a public folder that a Web server can access via HTTP-URL protocol • Build the Server Classes • javac engine\ComputeEngine.javarmic –d . engine.ComputeEngine • rmic creates files : • ComputeEngine_Stub.classComputeEngine_Skel.class • These files also need to be placed in a Web Server accessible folder. • Compiling the Client • javac client\ComputePi.javajavac client\Pi.java • The Pi.class must be placed in a Web Server accessible folder.
Running the Program • Write a General Policy File for • Connect or accept connections on unprivileged ports on any host (port>1024) • Connect to port 80 (HTTP) • File: java.policy grant { permission java.net.SocketPermission "*:1024-65535", "connect,accept"; permission java.net.SocketPermission "*:80", "connect";}; • Start registry on the Server • In Command Prompt write: rmiregistry • By default it starts on port 1099 • It runs in the background, and doesn’t produce any output
Running the Program • To run the Server • java –Djava.rmi.server.codebase=file:/E:\Trials\JavaRMI\Count –Djava.rmi.server.hostname=localhost –Djava.security.policy=java.policy engine.ComputeEngine • To run the Client • java –Djava.rmi.server.codebase=file:/E:\Trials\JavaRMI\Count –Djava.security.policy=java.policy client.ComputePi localhost 40 • Output: 3.1415926535897932384626433832795028841972
Running the Program Client’s Host: LocalHost Server’s Host: LocalHost ComputePi Compute Engine rmi registry ComputeEngine_Stub ComputeEngine_Stub Compute Task Pi Web Server Web Server