Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Spring Term 2013 Assignment 3: Appendix RMI programming tutorial In this tutorial, we will give an example of a RMI client and server. The server exposes a remote method int addOne(int i) to the clients. With the input arguments i from clients, addOne() simply returns i+1. To create and run the RMI example, the following steps are necessary: 1 Designing a Remote Interface The interface defines the methods that can be invoked from the client. Essentially, the interface defines the client’s view of the remote object. The example.Calculator interface defines the remotely accessible part. Here is the source code: package calculator; import java.rmi.Remote; import java.rmi.RemoteException; public interface Calculator extends Remote { public int addOne(int i) throws RemoteException; } By extending the interface java.rmi.Remote, the Calculator interface identifies itself as an interface whose methods can be invoked from another Java virtual machine. As a member of a remote interface, the addOne(int i) method is a remote method. Therefore, this method must be defined as being capable of throwing a java.rmi.RemoteException. This exception is thrown by the RMI system from a remote method invocation to indicate that either a communication failure or a protocol error has occurred. A RemoteException is a checked exception, so any code invoking a remote method needs to handle this exception by either catching it or declaring it in its throws clause. 2 2.1 Creating a RMI server Implementing a Remote Interface The example.CalculatorImpl class implements the remote interface Calculator. Here is the source code for the CalculatorImpl class: package server; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import calculator.Calculator; public class CalculatorImpl implements Calculator { public CalculatorImpl() throws RemoteException { UnicastRemoteObject.exportObject(this, 0); } public int addOne(int i) throws RemoteException { return i + 1; } } The UnicastRemoteObject.exportObject(this, 0) method 1 exports the Remote object to the RMI runtime, so that it is made available to receive incoming remote invocations from clients. This is only one part of the setup procedure, which • Export one or more remote objects • Register at least one remote object with the RMI registry We still need to register the remote objects with the RMI registry. These two parts of the setup procedure can be either encapsulated in a method of the remote object implementation class itself (like the Hello World example 2 ) or included in another class entirely. In this example, we create a separate server class CalculatorServer.java to do this: package server; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import server.CalculatorImpl; public class CalculatorServer { public static void main(String[] args) { try { String name = "Calculator"; CalculatorImpl c = new CalculatorImpl(); Registry registry = LocateRegistry.getRegistry(); registry.rebind(name, c); System.out.println("CalculatorServer Ready!"); } catch (Exception e) { System.err.println("CalculatorServer exception:"); e.printStackTrace(); } } } The java.rmi.registry.Registry remote interface is the API for binding (or registering) and looking up remote objects in the registry. The java.rmi.registry.LocateRegistry class provides static methods for synthesizing a remote reference to a registry at a particular network address (host and port). Through registry.rebind(name , c), the CalculatorServer class adds the Calculator object with name "Calculator" to the RMI registry running on the server. 1 http://java.sun.com/j2se/1.5.0/docs/api/java/rmi/server/UnicastRemoteObject.html 2 http://java.sun.com/j2se/1.5.0/docs/guide/rmi/hello/hello-world.html 2 3 Creating a RMI client The RMI client constructs a name to look up a Calculator remote object, the same name used by CalculatorServer to bind its remote object. Also, the client uses the LocateRegistry.getRegistry API to synthesize a remote reference to the registry on the server’s host. The value of the first command-line argument, args[0], is the name of the remote host on which the Calculator object runs. The client then invokes the lookup method on the registry to look up the remote object by the name, which is args[1], in the server host’s registry. The value of the third command-line argument, args[2], is the input parameter for the remote method addOne(int i). package client; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import calculator.Calculator; public class CalculatorClient { public static void main(String args[]) { try { Registry registry = LocateRegistry.getRegistry(args[0]); Calculator cal = (Calculator) registry.lookup(args[1]); int input = (new Integer(args[2])).intValue(); int output = cal.addOne(input); System.out.println("The output of addOne(" + input + ")" + " is " + output); } catch (Exception e) { System.err.println("CalculatorClient exception:"); e.printStackTrace(); } } } 4 Compiling and running the example a) Compile .java files: bash$ javac calculator/*.java client/*.java server/*.java b) Start rmiregistry and leave it running in the background, and start the server: bash$ rmiregistry & bash$ java server.CalculatorServer Note: Kill old rmiregistry before starting new one! c) Running the client: bash$ java client.CalculatorClient localhost Calculator 100 d) The result is then displayed: The Output of addOne(100) is 101 e) Remarks: As of the J2SE 5.0 release, by default, rmic does not generate any skeleton classes. Moreover, stub classes for remote objects no longer need to be pregenerated using the rmic stub compiler, unless the remote object needs to support clients running in pre-5.0 VMs. If your 3 application needs to support such clients, you will need to generate stub classes for the remote objects used in the application and deploy those stub classes for clients to download. For details on how to generate stub classes, see the tools documentation for rmic [Solaris3 , Windows4 ]. For details on how to deploy your application along with pregenerated stub classes, see the codebase tutorial 5 . 4.1 Further reading Find a more interesting example of using RMI’s unique capabilities to load and to execute userdefined tasks at runtime here: http://java.sun.com/docs/books/tutorial/rmi/index.html 3 http://java.sun.com/j2se/1.5.0/docs/tooldocs/solaris/rmic.html 4 http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/rmic.html 5 http://java.sun.com/j2se/1.5.0/docs/guide/rmi/codebase.html 4