Page #489 (36.2. RMI Basics)

 
[Page 1246 ( continued )]

36.3. Developing RMI Applications

Now that you have a basic understanding of RMI, you are ready to write simple RMI applications. The steps in developing an RMI application are shown in Figure 36.4.


[Page 1247]
Figure 36.4. The steps in developing RMI applications.

1.
Define a server object interface that serves as the contract between the server and its clients , as shown in the following outline:

    public interface   ServerInterface   extends Remote    {   public void   service1(...)   throws   RemoteException;  // Other methods  } 

A server object interface must extend the java.rmi.Remote interface.

2.
Define a class that implements the server object interface, as shown in the following outline:

    public class   ServerInterfaceImpl   extends   UnicastRemoteObject     implements   ServerInterface  {   public void   service1(...)   throws   RemoteException {  // Implement it  }  // Implement other methods  } 

The server implementation class must extend the java.rmi.server.UnicastRemoteObject class. The UnicastRemoteObject class provides support for point-to-point active object references using TCP streams.

3.
Create a server object from the server implementation class and register it with an RMI registry:

 ServerInterface server =   new   ServerInterfaceImpl(...); Registry registry = LocateRegistry.getRegistry(); registry.rebind(   "RemoteObjectName"   , obj); 

4.
Develop a client that locates a remote object and invokes its methods, as shown in the following outline:

 Registry registry = LocateRegistry.getRegistry(host); ServerInterface server = (ServerInterfaceImpl) registry.lookup(   "RemoteObjectName"   ); server.service1(...); 

The example that follows demonstrates the development of an RMI application through these steps.

36.3.1. Example: Retrieving Student Scores from an RMI Server

This example creates a client that retrieves student scores from an RMI server. The client, shown in Figure 36.5, displays the score for the specified name .

Figure 36.5. You can get the score by entering a student name and clicking the Get Score button.
(This item is displayed on page 1248 in the print version)


1.
Create a server interface named StudentServerInterface in Listing 36.1. The interface tells the client how to invoke the server's findScore method to retrieve a student score.


[Page 1248]


Listing 36.1. StudentServerInterface.java
 1   import   java.rmi.  *  ; 2 3    public interface   StudentServerInterface   extends   Remote  { 4  /**  5  * Return the score for the specified name  6  * @param name the student name  7  * @return an double score or -1 if the student is not found  8  */  9    public double   findScore(String name)   throws   RemoteException;  10 } 

Any object that can be used remotely must be defined in an interface that extends the java.rmi.Remote interface (line 3). StudentServerInterface , extending Remote , defines the findScore method that can be remotely invoked by a client to find a student's score. Each method in this interface must declare that it may throw a java.rmi.RemoteException (line 9). Therefore your client code that invokes this method must be prepared to catch this exception in a try-catch block.

2.
Create a server implementation named StudentServerInterfaceImpl (Listing 36.2) that implements StudentServerInterface . The findScore method returns the score for a specified student. It returns “1 if the score is not found.

Listing 36.2. StudentServerInterfaceImpl.java
(This item is displayed on pages 1248 - 1249 in the print version)
 1   import   java.rmi.  *  ; 2   import   java.rmi.server.  *  ; 3   import   java.util.  *  ; 4 5    public clas  s  StudentServerInterfaceImpl   extends   UnicastRemoteObject  6    implements   StudentServerInterface  { 7  // Stores scores in a map indexed by name  8   private   HashMap scores =   new   HashMap(); 9 10   public   StudentServerInterfaceImpl()   throws   RemoteException { 11 initializeStudent(); 12 } 13 14  /** Initialize student information */  15   protected void   initializeStudent() { 16 scores.put(   "John"   ,   new   Double(   90   .   5   )); 17 scores.put(   "Michael"   ,   new   Double(   100   )); 18 scores.put(   "Michelle"   ,   new   Double(   98   .   5   )); 19 } 20 

[Page 1249]
 21  /** Implement the findScore method from the Student interface */  22   public double   findScore(String name)   throws   RemoteException { 23 Double d = (Double)scores.get(name); 24 25   if   (d ==   null   ) { 26 System.out.println(   "Student "   + name +   " is not found "   ); 27   return     -1   ; 28 } 29   else   { 30 System.out.println(   "Student "   + name +   "\'s score is "   31 + d.doubleValue()); 32   return   d.doubleValue(); 33 } 34 } 35 } 

The StudentServerInterfaceImpl class implements StudentServerInterface . This class must also extend the java.rmi.server.RemoteServer class or its subclass. RemoteServer is an abstract class that defines the methods needed to create and export remote objects. Often its subclass java.rmi.server.UnicastRemoteObject is used (line 5). This subclass implements all the abstract methods defined in RemoteServer .

StudentServerInterfaceImpl implements the findScore method (lines 22 “34) defined in StudentServerInterface . For simplicity, three students, John, Michael, and Michelle, and their corresponding scores are stored in an instance of java.util.HashMap named scores . HashMap is a concrete class of the Map interface in the Java Collections Framework, which makes it possible to search and retrieve a value using a key. Both values and keys are of Object type. The findScore method returns the score if the name is in the hash map, and returns -1 if the name is not found (line 27).

3.
Create a server object from the server implementation and register it with the RMI server (Listing 36.3).

Listing 36.3. RegisterWithRMIServer.java
 1   import   java.rmi.registry.*; 2 3   public class   RegisterWithRMIServer { 4  /** Main method */  5   public static void   main(String[] args) { 6   try   { 7  StudentServerInterface obj =   new   StudentServerInterfaceImpl();  8  Registry registry = LocateRegistry.getRegistry();  9  registry.rebind(   "StudentServerInterfaceImpl"   , obj);  10 System.out.println(   "Student server "   + obj +   " registered"   ); 11 } 12   catch   (Exception ex) { 13 ex.printStackTrace(); 14 } 15 } 16 } 

RegisterWithRMIServer contains a main method, which is responsible for starting the server. It performs the following tasks : (1) create a server object (line 7); (2) obtain a reference to the RMI registry (line 8), and (3) register the object in the registry (line 9).

4.
Create a client as an applet named StudentServerInterfaceClient in Listing 36.4. The client locates the server object from the RMI registry and uses it to find the scores.


[Page 1250]
Listing 36.4. StudentServerInterfaceClient.java
(This item is displayed on pages 1250 - 1251 in the print version)
 1   import   java.rmi.  *  ; 2   import   javax.swing.  *  ; 3   import   java.awt.  *  ; 4   import   java.awt.event.  *  ; 5   import   java.rmi.registry.LocateRegistry; 6   import   java.rmi.registry.Registry; 7 8    public class   StudentServerInterfaceClient   extends   JApplet  { 9  // Declare a Student instance  10   private   StudentServerInterface student; 11 12    private boolean   isStandalone;  // Is applet or application   13 14   private   JButton jbtGetScore =   new   JButton(   "Get Score"   ); 15   private   JTextField jtfName =   new   JTextField(); 16   private   JTextField jtfScore =   new   JTextField(); 17 18   public void   init() { 19  // Initialize RMI  20  initializeRMI();  21 22 JPanel jPanel1 =   new   JPanel(); 23 jPanel1.setLayout(   new   GridLayout(   2   ,   2   )); 24 jPanel1.add(   new   JLabel(   "Name"   )); 25 jPanel1.add(jtfName); 26 jPanel1.add(   new   JLabel(   "Score"   )); 27 jPanel1.add(jtfScore); 28 29 add(jbtGetScore, BorderLayout.SOUTH); 30 add(jPanel1, BorderLayout.CENTER); 31 32  jbtGetScore.addActionListener(   new   ActionListener() {  33   public void   actionPerformed(ActionEvent evt) { 34  getScore();  35 } 36 }); 37 } 38 39   private void   getScore() { 40   try   { 41  // Get student score  42    double   score = student.findScore(jtfName.getText().trim());  43 44  // Display the result  45   if   (score <     ) 46 jtfScore.setText(   "Not found"   ); 47   else   48 jtfScore.setText(   new   Double(score).toString()); 49 } 50   catch   (Exception ex) { 51 ex.printStackTrace(); 52 } 53 } 54 55  /** Initialize RMI */  56   protected void   initializeRMI() { 57 String host =   " "   ; 58   if   (!isStandalone) host = getCodeBase().getHost(); 59 

[Page 1251]
 60   try   { 61  Registry registry = LocateRegistry.getRegistry(host);  62  student = (StudentServerInterface)  63  registry.lookup(   "StudentServerInterfaceImpl"   );  64 System.out.println(   "Server object "   + student +   " found"   ); 65 } 66   catch   (Exception ex) { 67 System.out.println(ex); 68 } 69 } 70 71  /** Main method */  72   public static void   main(String[] args) { 73 StudentServerInterfaceClient applet = 74   new   StudentServerInterfaceClient(); 75  applet.isStandalone =   true   ;  76 JFrame frame =   new   JFrame(); 77 frame.setTitle(   "StudentServerInterfaceClient"   ); 78 frame.add(applet, BorderLayout.CENTER); 79 frame.setSize(   250   ,   150   ); 80 applet.init(); 81 frame.setLocationRelativeTo(   null   ); 82 frame.setVisible(   true   ); 83 frame.setDefaultCloseOperation(   3   ); 84 } 85 } 

StudentServerInterfaceClient invokes the findScore method on the server to find the score for a specified student. The key method in StudentServerInterfaceClient is the initializeRMI method (lines 56 “69), which is responsible for locating the server stub.

The initializeRMI() method treats standalone applications differently from applets. The host name should be the name where the applet is downloaded. It can be obtained using the Applet 's getCodeBase().getHost() . For standalone applications, the host name should be specified explicitly.

The lookup(String name) method (line 63) returns the remote object with the specified name. Once a remote object is found, it can be used just like a local object. The stub and the skeleton are used behind the scenes to make the remote method invocation work.

5.
Follow the steps below to run this example.

5.1. Start the RMI Registry by typing " start rmiregistry" at a DOS prompt from the c:\book directory. By default, the port number 1099 is used by rmiregistry. To use a different port number, simply type the command " start rmiregistry portnumber" at a DOS prompt.

5.2. Start the server RegisterWithRMIServer using the following command at c:\book directory:

 C:\book>  java RegisterWithRMIServer  

5.3. Run the client StudentServerInterfaceClient as an application. A sample run of the application is shown in Figure 36.6.

Figure 36.6. To run an RMI program, first start the RMIRegistry, then register the server object with the registry. The client locates it from the registry.
(This item is displayed on page 1252 in the print version)

5.4. Run the client StudentServerInterface.html from the appletviewer. A sample run is shown in Figure 36.5.

Note

You must start rmiregistry from the directory where you will run the RMI server. Otherwise, you will receive the error ClassNotFoundException on StudentServerInterfaceImpl_Stub .



[Page 1252]

Note

Server, registry, and client can be on three different machines. If you run the client and the server on separate machines, you need to place StudentServerInterface on both machines. If you deploy the client as an applet, place all client files on the registry host.


Caution

If you modify the remote object implementation class, you need to restart the server class to reload the object to the RMI registry. In some old versions of rmiregistry, you may have to restart rmiregistry.


 


Introduction to Java Programming-Comprehensive Version
Introduction to Java Programming-Comprehensive Version (6th Edition)
ISBN: B000ONFLUM
EAN: N/A
Year: 2004
Pages: 503

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net