Sie sind auf Seite 1von 12

Java RMI

Overview
Remote Method Invocation (RMI) allows object methods calls between Java Virtual Machines (JVMs) [1]. As the state of distributed network system dictate, JVMs can be sited on separate computers. However, one JVM can call methods belonging to an object sited in another JVM. Methods are allowed to pass objects of different type even if the objects have never been encountered before by the remote virtual machine. Classes are allowed to be loaded dynamically and as required. The best scenario in which RMI comes handy is when developer, for example, called (A) writes a service that performs a certain task. He regularly maintains this service, adding new features and improving existing ones. Let us assume that a developer B wants to use the service provided by developer A. Logic will dictate that A should find a convenient way to update the service without B being affected [2]. Java RMI solution relays on its ability to dynamically load new classes. Developer B can let RMI handle updates automatically for him. Developer (A) normally advertises the new classes in a web directory, where RMI can obtain the new updates as they are required.

Figure 1 - client uses RMI

Figure [1] illustrates the connections the client will make when using RMI. Firstly, the client must contact an RMI registry, and request the name of the service [1]. Client won't know where the RMI services are located, but he knows enough to contact Server's registry. This will direct him to the service he wants to use.

In the real world Server's service updates regularly and Client doesn't have a copy of the updated class. This shouldnt be a problem, because the client automatically obtains the new subclass from a web server where the service and client share classes. The new class will be loaded into a memory, and the client will be ready to use them. This happens transparently for client and, from its side, no more code need to be written to obtain the class.

Writing RMI services


This work is based on Exercise (2) is asking us to design a RMI Lottery application. Each time the client program runs -- java LotteryClient n, the server program LotteryServer will generate n sets of Lottery numbers. Here n is a positive integer, representing the money we will spend on Lottery in sterling pounds. Also, we are asked to write this program in a proper engineering manner, i.e. there should be specifications, design (flow chart, FD, or pseudo code), coding, test/debug, and documentation. Tools Window Vista, Jdk1.6.0_21 and Linux Fedora for deployment of the software The pseudo code 1. 2. 3. 4. 5. 6. 7. 8. The lotteryImp registers, or is registered, with the rmiregistry The client requests a reference to a lotteryImp The rmiregistry returns a remote reference to a lotteryImp The client invokes a remote method numberGenerator on the lotteryImp The client ask user t enter money The client will pass money to numberGenerator numberGenerator call Random generator to get num numberGenerator return num

Writing an interface The first step should be taken to write rmiservice is to agree upon an interface. An interface is a description of the methods we will allow remote clients to invoke. In this service interface we will have one method. This method must be implemented by another lotteryImp class. Here's the source code for the service that will generate a set of lottery numbers. public interface lotteryNum

extends java.rmi.Remote { public String numberGenerator(int money) throws java.rmi.RemoteException; } Our interface extends java.rmi.Remote, which indicates that this is a remote service. Later, a definition will be provided for the method (numberGenerator()) to complete the interface. The next step is to implement the interface, and provide method for the lottery number generators function. Implementing the interface Class lotteryImp implements the numberGenerator of the interface lotteryNum. The declaration of the default constructor here allows the program to throw a java.rmi.RemoteException from its parent constructor in UnicastRemoteObject. public lotteryImp () throws RemoteException { super(); } There are three methods in the lotteryImp class and they are numberGenerator, arrayListToString and searchIt. numberGenerator is the service methods and it will be called by the client later while the others two are utility methods . arrayListToString converts the a list of integers to string and searchIt uses a separate list to check whether the random method generated the same number twice. import java.util.Random; import java.util.ArrayList; public class lotteryImp extends java.rmi.server.UnicastRemoteObject implements lotteryNum { // Implementations must have an explicit constructor // in order to declare the RemoteException exception public lotteryImp() throws java.rmi.RemoteException { super(); }

public String numberGenerator(int money) throws java.rmi.RemoteException { ArrayList rev = new ArrayList(); ArrayList<Integer> items = new ArrayList<Integer>(); while( money > 0){ items.clear(); for( int i = 0 ; i < 7; i++){ Random generator = new Random(); int lotNum = generator.nextInt(46) + 1; int checker = searchIt( items,lotNum); if (checker> 0){ System.out.println(checker); --i; } else{ if(i+1==7){ rev.add("\n"); } else{ items.add(lotNum); rev.add(lotNum); rev.add(" "); } }//end of first if

}//end of for loop

money --; } //end of while loop

String str = arrayListToString(rev); return str; } public static String arrayListToString(ArrayList arraylist) { StringBuilder arraylistTostr = new StringBuilder(); if (arraylist.size() > 0) { arraylistTostr.append(arraylist.get(0)); for (int i=1; i<arraylist.size(); i++) { arraylistTostr.append(arraylist.get(i)); } } return arraylistTostr.toString(); }//end of method arrayListToString public static int searchIt(ArrayList<Integer> arr , int lotNum){ int n = 0; for(int i=0; i<arr.size(); i++) if(arr.get(i)==lotNum) return i; return -1; }//end of search }

Writing a RMI Server


The calling client invokes a method on a remote object by obtaining a reference to the remote object. RMI provides a remote object registry that allows the binding of a URL name service of the form "//host/lotteryService" to the remote object, where lotteryService is any name possible. The RMI registry is a simple mechanism in the server-side to name service. It allows a remote client to get a reference to a remote object. It provides the entry point needed by a client to locate the first remote object. Once the client obtained that first object it will use it to find other objects. For example, the reference can be obtained as a parameter to, or a return value from, another remote method call. Once a remote method is registered or bonded to the server, the client can call the object by name directly to obtain a remote object reference, and then remotely call up methods that implementing the object. For example, the following code binds the name "lotteryService" to a reference for the remote object: Naming.rebind("//localhost:1099/lotteryService",c);

The first parameter represents the location and the name of URL that tells the callers the location of the remote service. Also, notable that the binding does not involves naming a protocol for data transmission. All we need to do is to change the value of the localhost to the IP address of the server machine. The default port number 1099 is not necessary to be stated here for the RMI to complete the running of the process. However, specifying the port number is a must when the registry is not running in a default port. The second parameter is a reference to where the object is implemented and will be used to invoke remote methods. Once an object is sent out, the RMI runtime environment starts a process of replacing a reference to the remote object's stub for the real remote object reference that is defined by the c parameter. When a client links up with a server's registry, the stub will be replaced with the actual implementation of the object and then using the same mechanism it will be returned to the client.

import java.rmi.Naming; public class lotteryServer {

public lotteryServer() { try { lotteryNum c = new lotteryImp(); Naming.rebind("rmi://localhost:1099/lotteryService", c); } catch (Exception e) { System.out.println("Trouble: " + e); } } public static void main(String args[]) { new lotteryServer(); } }

Writing a RMI client


In the real world, writing an RMI client is the easy part. All a client needs to do is link up with the registry to obtain a reference to the remote object, and call its methods. RMI is designed to make the developing of networking applications really easy by hiding the underlying network communication from view. The client receives an instance of the interface we coded, not the actual implementation. On the client side, the RMI Registry will be accessed using the static class Naming object. It allows us to use the method lookup() that a client will uses to search a registry. The URL that define the server name and the name of the requested will be placed in the method lookup(). The method returns a remote reference to the service object.

import javax.swing.JOptionPane; import java.rmi.Naming; import java.rmi.RemoteException;

import java.net.MalformedURLException; import java.rmi.NotBoundException; import java.util.ArrayList; import javax.swing.JTextArea;

public class lotteryClient { public static void main(String[] args){ String money = JOptionPane.showInputDialog("How much you want spent on lottery tickets"); int num = Integer.parseInt(money); try { lotteryNum lottery = (lotteryNum) Naming.lookup("rmi://localhost/lotteryService"); String str = lottery.numberGenerator(num); JOptionPane.showMessageDialog(null,"Here your numbers \n" +str, "Lottery ticket",JOptionPane.PLAIN_MESSAGE); }

catch (MalformedURLException murle) { System.out.println(); System.out.println("MalformedURLException"); System.out.println(murle); } catch (RemoteException re) {

System.out.println(); System.out.println("RemoteException"); System.out.println(re); } catch (NotBoundException nbe) { System.out.println(); System.out.println("NotBoundException"); System.out.println(nbe); } catch (java.lang.ArithmeticException ae) { System.out.println(); System.out.println("java.lang.ArithmeticException"); System.out.println(ae); } }

} Running the client and server Using the jdk1.6.0_21 command prompt you can the program as the following:
1. Compile the interface lotteryNum and its implementation lotteryImp

Javac lotteryNum Javac lotteryImp


2. Create the registry by using rmic as the following: rmic lotteryImp

3.

Start the rmiregistry

start rmiregistry
4. Compile and start the server

Javac lotteryServer and java lotteryServer


5. Compile and start the client

Javac lotteryClient java lotteryClient You can run the client locally, or from a different machine. In either case, you'll need to specify the hostname of the machine where you are running the server. If you're running it locally, use localhost as the hostname. Summary Java RMI is an excellent system for calling up methods of remote objects. RMI methods are allowed to pass objects of different type even if the objects have never been encountered before by the remote virtual machine. RMI allows the code that defines the behaviour and the code that implements the behaviour to remain separate and to run on separate JVMs. This fits nicely with the needs of a distributed system where clients are concerned about the definition of a service and servers are focused on providing the service.

Testing

Reference 1- An Overview of RMI Applications


http://download.oracle.com/javase/tutorial/rmi/overview.html [accessed 16/4/2011]

2- Java RMI

http://www.csc.liv.ac.uk/~konev/COMP212/04-java-rmi.pdf [accessed 16/4/2011]

brimponn@lsbu.ac.uk

Das könnte Ihnen auch gefallen