NetRatServer Implementation Fourth Iteration


NetRatServer Implementation — Third Iteration

The current design of the robot rat server application results in all RMI clients controlling the same instance of a RobotRat. What’s needed is some way to create a new instance of a RobotRat for each RMI client connection. This can easily be done by creating another class on the server side whose job is to create RobotRat objects. We call such a class a factory class. Since our factory class will create RobotRat objects a good name for the class is RobotRatFactory. Table 20-6 presents the design considerations and design decisions that will guide this development iteration.

Table 20-6: Third Iteration Design Considerations and Decisions

Check-Off

Design Consideration

Design Decision

 

Objectives for third iteration server application development activities.

Modify the server design to incorporate a RobotRatFactory class so that RMI clients can manipulate their own RobotRat.

 

RobotRatFactory class

Design a new class named RobotRatFactory. This class will be an RMI class like RobotRat which means a RobotRatFactory interface must also be created. Clients will get an instance of RobotRatFactory and use it to retrieve a RobotRat object from the server.

 

RobotRatFactory interface

The RobotRatFactory interface needs to be created to support the RobotRatFactory class. The name of this interface will be RobotRatFactoryInterface. RobotRatFactoryInterface will extend the java.rmi.remote interface.

 

NetRatServer class

The NetRatServer class will need to be modified to bind an instance of RobotRatFactory to a service name. The name of the service can be Robot_Rat_Factory.

 

RMI_NetRatClient class

The RMI_Client will need to be modified to use the RobotRatFactory.

 

rmic tool

The RobotRatFactory_stub.class file will need to be generated with the rmic tool and deployed to the server side and client side.

Updated Server Application Class Diagram

Figure 20-17 offers the modified version of the robot rat server application class diagram. The NetRatServer class will now have a dependency on the RobotRatFactory class. There is still a dependency between NetRatServer and RobotRat but only because of the earlier test code. There is also a dependency between NetRatServer and RobotRatInterface because of the same test code. All test code can be removed in a later iteration to eliminate unnecessary (residual) dependencies.

image from book
Figure 20-17: Updated Robot Rat Server Application Class Diagram

Third Iteration Code

The following new classes and modified code are the result of third iteration development activities.

Referring to example 20.11 through 20.13 — RobotRatFactoryInterface declares one public method named getRobotRat() which returns a reference to an object of type RobotRatInterface. The RobotRatFactory class implements RobotRatFactoryInterface and provides functionality for the getRobotRat() method. All the getRobotRat() method does is create and return a new instance of RobotRat. This has significant implications for the behavior of the server application — all RMI clients will have their very own rat to move around which is what we desire.

Example 20.11: RobotRatFactoryInterface.java

image from book
 1     import java.rmi.*; 2 3     interface RobotRatFactoryInterface extends Remote { 4       public RobotRatInterface getRobotRat() throws RemoteException; 5     }
image from book

Example 20.12: RobotRatFactory.java

image from book
 1     import java.rmi.*; 2     import java.rmi.server.*; 3 4     public class RobotRatFactory extends UnicastRemoteObject 5                                  implements RobotRatFactoryInterface { 6 7        public RobotRatFactory() throws RemoteException { 8         System.out.println("RobotRatFactoryImplementation object created!"); 9        } 10 11      public RobotRatInterface getRobotRat() throws RemoteException { 12        RobotRatInterface new_rat = null; 13        try{ 14           new_rat = new RobotRat(); 15        }catch(RemoteException re){ 16          System.out.println("getRobotRat(): problem creating new RobotRat object!"); 17          re.printStackTrace(); 18         } 19        return new_rat; 20      } 21    }// end RobotRatFactory class definition
image from book

Example 20.13: NetRatServer.java (mod 2)

image from book
 1     import javax.swing.*; 2     import java.awt.*; 3     import java.awt.event.*; 4     import java.rmi.*; 5     import java.rmi.registry.*; 6     import java.net.*; 7 8     public class NetRatServer extends JFrame implements ActionListener { 9 10      private JButton button1 = null; 11      private RobotRatInterface _r1 = null; 12      private RobotRatInterface _r2 = null; 13 14      public NetRatServer(){ 15        try{ 16        _r1 = new RobotRat(); 17        _r2 = new RobotRat(); 18        catch(Exception ignored){ ignored.printStackTrace(); } 19        button1 =  new JButton("move"); 20        button1.addActionListener(this); 21        this.getContentPane().add(button1); 22        this.setSize(100, 100); 23        this.setLocation(300, 300); 24        this.show(); 25      } 26 27      public void actionPerformed(ActionEvent ae){ 28        if(ae.getActionCommand().equals("move")){ 29          try{ 30          _r1.moveEast(); 31          _r2.moveSouthEast(); 32          }catch(Exception ignored){ } 33        } 34      } 35 36      public static void main(String[] args){ 37        System.out.println("NetRatServer Lives!!"); 38        new NetRatServer(); 39        try{ 40        System.out.println("Starting registry..."); 41        LocateRegistry.createRegistry(1099); 42        System.out.println("Registry started on port 1099."); 43        System.out.println("Binding service name to remote object..."); 44        Naming.bind("Robot_Rat_Factory", new RobotRatFactory()); 45        System.out.println("Bind successful."); 46        System.out.println("Ready for remote method invocation."); 47        }catch(Exception e){ 48          e.printStackTrace(); 49        } 50     }  // end main() method 51    }// end NetRatServer class
image from book

The NetRatServer class is modified on line 44 to bind an instance of RobotRatFactory with the Robot_Rat_Factory service name.

After these classes are compiled the rmic tool must be run to generate the RobotRatFactory_stub.class file. The RMI_NetRatClient application will now need four server-side class files to operate properly. These include image from book RobotRatInterface.class, RobotRat_stub.class, image from book RobotRatFactoryInterface.class, and RobotRatFactory_stub.class.

Testing The Third Iteration Code

Compile the code and generate the necessary stub files with the rmic tool. You can now crank up the robot rat server application to see if everything works. However, to fully test the server application you must make a modification to the RMI_NetRatClient application so that it can utilize a RobotRatFactory to get an instance of a RobotRat. The modified client application is given in example 20.14.

Example 20.14: RMI_NetRatClient.java (mod 1)

image from book
 1     import java.rmi.*; 2     import java.awt.*; 3     import java.awt.event.*; 4     import javax.swing.*; 5 6     public class RMI_NetRatClient extends JFrame implements ActionListener { 7 8       private JButton _button1 = null; 9       private JButton _button2 = null; 10      private JButton _button3 = null; 11      private JButton _button4 = null; 12      private JButton _button5 = null; 13      private JButton _button6 = null; 14      private JButton _button7 = null; 15      private JButton _button8 = null; 16      private JButton _button9 = null; 17      private RobotRatInterface _robot_rat = null; 18      private RobotRatFactoryInterface _robot_rat_factory = null; 19 20 21      public RMI_NetRatClient(String host){ 22        super("Robot Rat Control Panel"); 23 24      try{ 25         _robot_rat_factory = (RobotRatFactoryInterface)Naming.lookup("rmi://" + host + 26                                                                      "/Robot_Rat_Factory"); 27         _robot_rat = _robot_rat_factory.getRobotRat(); 28 29         }catch(Exception e){ 30          e.printStackTrace(); 31         } 32        this.setUpGui(); 33      } 34 35      public void actionPerformed(ActionEvent ae){ 36       try{ 37       if(ae.getActionCommand().equals("N")){ 38          _robot_rat.moveNorth(); 39       } else if(ae.getActionCommand().equals("NE")){ 40          _robot_rat.moveNorthEast(); 41       } else if(ae.getActionCommand().equals("E")){ 42          _robot_rat.moveEast(); 43       } else if(ae.getActionCommand().equals("SE")){ 44         _robot_rat.moveSouthEast(); 45       } else if(ae.getActionCommand().equals("S")){ 46          _robot_rat.moveSouth(); 47       } else if(ae.getActionCommand().equals("SW")){ 48          _robot_rat.moveSouthWest(); 49       } else if(ae.getActionCommand().equals("W")){ 50          _robot_rat.moveWest(); 51       } else if(ae.getActionCommand().equals("NW")){ 52         _robot_rat.moveNorthWest(); 53       } 54 55      }catch(RemoteException re){ 56        System.out.println("actionPerformed(): problem calling remote robot_rat method."); 57        re.printStackTrace(); 58       } 59 60      } 61 62      public void setUpGui(){ 63       _button1 = new JButton("NW"); 64       _button1.addActionListener(this); 65 66       _button2 = new JButton("N"); 67       _button2.addActionListener(this); 68 69       _button3 = new JButton("NE"); 70       _button3.addActionListener(this); 71 72       _button4 = new JButton("W"); 73       _button4.addActionListener(this); 74 75       _button5 = new JButton(""); 76       _button5.addActionListener(this); 77 78       _button6 = new JButton("E"); 79       _button6.addActionListener(this); 80 81       _button7 = new JButton("SW"); 82       _button7.addActionListener(this); 83 84       _button8 = new JButton("S"); 85       _button8.addActionListener(this); 86 87       _button9 = new JButton("SE"); 88       _button9.addActionListener(this); 89 90       this.getContentPane().setLayout(new GridLayout(3,3,0,0)); 91       this.getContentPane().add(_button1); 92       this.getContentPane().add(_button2); 93       this.getContentPane().add(_button3); 94       this.getContentPane().add(_button4); 95       this.getContentPane().add(_button5); 96       this.getContentPane().add(_button6); 97       this.getContentPane().add(_button7); 98       this.getContentPane().add(_button8); 99       this.getContentPane().add(_button9); 100      this.setSize(200, 200); 101      this.setLocation(300, 300); 102      this.pack(); 103      this.show(); 104     } // end setUpGui() method 105 106     public static void main(String[] args){ 107        try{ 108          new RMI_NetRatClient(args[0]); 109        }catch(ArrayIndexOutOfBoundsException e1){ 110           System.out.println("Usage: java NetRatClient <host>"); 111         } 112         catch(Exception e2){ 113           e2.printStackTrace(); 114         } 115     }// end main() 116 117   }// end NetRatClient class definition
image from book

Referring to example 20.14 — the RMI_NetRatClient application must now retrieve a RobotRatFactory object from the server and use it to get a reference to a RobotRat object. RobotRatInterface and RobotRatFactoryInterface are used on lines 17 and 18 to declare the references _robot_rat and _robot_rat_factory respectively. On lines 25 and 26 a RobotRatFactory reference is retrieved from the server and assigned to the reference variable _robot_rat_factory. On line 27 the getRobotRat() method is called via the _robot_rat_factory reference to retrieve a RobotRat reference. Method calls to the server-side RobotRat object are made via the _robot_rat reference variable as before.

Testing Multiple RMI Client Applications

Now that the necessary modifications have been made to the server and client applications multiple RMI client connections can be tested. Start-up the NetRatServer application and use its move button to move the two server-controlled robot rats out of the way. Figure 20-18 shows the floor after the server-controlled robot rats have been moved out of the way.

image from book
Figure 20-18: The Floor After Approximately 15 Clicks of the Server-Side move Button

Referring to figure 20-18 — notice now that only the two server-side test robot rats are drawn on the floor when the NetRatServer application starts up.

With the server running, launch the modified version of the RMI_NetRatClient application. Figure 20-19 shows the server floor after one client has been started and has moved its robot rat several clicks south. Now start-up another instance of the RMI_NetRatClient application. Figure 20-20 shows the server floor now populated with two RMI-client-controlled and two server-controlled robot rats. To fully test the application(s) up to this point deploy the server and client on separate computers and test remotely. It’s time now to implement the last bit of client-server functionality.

image from book
Figure 20-19: Server Floor After RMI-Client-Controlled Robot Rat Moves South Several Clicks

image from book
Figure 20-20: Server Floor After Second RMI-Client-Controlled Robot Rat Appears

Quick Review

The RMI runtime manages client access to RMI server-side objects. In cases where RMI-based clients must have access to dedicated server-side remote objects a factory class can be employed to create the dedicated remote objects as required. RMI-based clients must first get a reference to the server-side factory object and use it to create the dedicated remote object it requires. This solves the dedicated remote object problem but raises the level of application complexity. Now, in addition to the dedicated remote object interface and stub classes, the factory interface and stub classes must also be deployed with the server and client applications.




Java For Artists(c) The Art, Philosophy, and Science of Object-Oriented Programming
Java For Artists: The Art, Philosophy, And Science Of Object-Oriented Programming
ISBN: 1932504052
EAN: 2147483647
Year: 2007
Pages: 452

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