1 / 70

Chapter 13: Remote Method Invocation

Chapter 13: Remote Method Invocation.

kaycee
Download Presentation

Chapter 13: Remote Method Invocation

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapter 13: Remote Method Invocation Outline13.1 Introduction13.2 Case Study: Creating a Distributed System with RMI13.3 Defining the Remote Interface13.4 Implementing the Remote Interface13.5 Compiling and Executing the Server and the Client13.6 Case Study: Deitel Messenger with Activatable Server 13.6.1 Activatable Deitel Messenger ChatServer 13.6.2 Deitel Messenger Client Architecture and Implementation 13.6.3 Running the Deitel Messenger Server and Client Applications13.7 Internet and World Wide Web Resources

  2. 13.1 Introduction • Remote Procedure Calls (RPCs) • Call functions residing on another computer • Communicate over a network • Marshal of data • Limited data types • Lean interface definition language (IDL) • Remote Method Invocation (RMI) • Java’s implementation of RPC • Handle the marshaling of data across the network • Transfer Java objects • No IDL is required

  3. 13.2 Case Study: Creating a Distributed System with RMI • Creating a distributed system with RMI • Define a remote interface • Define the remove object implementation • Define the client application • Compile and execute the remove object and the client

  4. 13.3 Defining the Remote Interface • Remote interface • Describes the remote methods • Extends interface java.rmi.Remote

  5. Interface WeatherService extends interface Remote. Declares method getWeatherInformation, which clients can invoke to retrieve weather information from the remote object. 1 // WeatherService.java 2 // WeatherService interface declares a method for obtaining 3 // wether information. 4 package com.deitel.advjhtp1.rmi.weather; 5 6 // Java core packages 7 import java.rmi.*; 8 import java.util.*; 9 10 public interface WeatherService extends Remote { 11 12 // obtain List of WeatherBean objects from server 13 public List getWeatherInformation() throws RemoteException; 14 15 } Fig. 13.1 WeatherService interface.Line 10Line 13

  6. 13.4 Implementing the Remote Interface • Remote object implementation • WeatherServiceImpl

  7. Invokes the default constructor for class UnicastRemoteObject. Create a URL object for the Traveler’s Forecast Web page. Extends class UnicastRemoteObject to obtain basic functionality required for all remote objects and implements interface WeatherService. 1 // WeatherServiceImpl.java 2 // WeatherServiceImpl implements the WeatherService remote 3 // interface to provide a WeatherService remote object. 4 package com.deitel.advjhtp1.rmi.weather; 5 6 // Java core packages 7 import java.io.*; 8 import java.net.URL; 9 import java.rmi.*; 10 import java.rmi.server.*; 11 import java.util.*; 12 13 public class WeatherServiceImpl extends UnicastRemoteObject 14 implements WeatherService { 15 16 private List weatherInformation; // WeatherBean object List 17 18 // initialize server 19 public WeatherServiceImpl() throws RemoteException 20 { 21 super(); 22 updateWeatherConditions(); 23 } 24 25 // get weather information from NWS 26 private void updateWeatherConditions() 27 { 28 try { 29 System.out.println( "Update weather information..." ); 30 31 // National Weather Service Traveler’s Forecast page 32 URL url = new URL( 33 "http://iwin.nws.noaa.gov/iwin/us/traveler.html" ); 34 Fig. 13.2 WeatherServiceImpl class implements remote interface WeatherService.Lines 13-14Line 21Lines 32-33

  8. Read next line from the Web page. Read through the Traveler’s Forecast Web page until reaching the sentinel. 35 // create BufferedReader for reading Web page contents 36 BufferedReader in = new BufferedReader( 37 new InputStreamReader( url.openStream() ) ); 38 39 // separator for starting point of data on Web page 40 String separator = "TAV12"; 41 42 // locate separator string in Web page 43 while ( !in.readLine().startsWith( separator ) ) 44 ; // do nothing 45 46 // strings representing headers on Traveler’s Forecast 47 // Web page for daytime and nighttime weather 48 String dayHeader = 49 "CITY WEA HI/LO WEA HI/LO"; 50 String nightHeader = 51 "CITY WEA LO/HI WEA LO/HI"; 52 53 String inputLine = ""; 54 55 // locate header that begins weather information 56 do { 57 inputLine = in.readLine(); 58 } while ( !inputLine.equals( dayHeader ) && 59 !inputLine.equals( nightHeader ) ); 60 61 weatherInformation = new ArrayList(); // create List 62 63 // create WeatherBeans containing weather data and 64 // store in weatherInformation List 65 inputLine = in.readLine(); // get first city's info 66 Fig. 13.2 WeatherServiceImpl class implements remote interface WeatherService.Line 42-43Line 57

  9. Construct a WeatherBean object for the current city. Adds the WeatherBean object to the List. Closes the BufferedReader and its associated InputStream. Read each city’s weather information and place this information in WeatherBean objects. 67 // The portion of inputLine containing relevant data is 68 // 28 characters long. If the line length is not at 69 // least 28 characters long, done processing data. 70 while ( inputLine.length() > 28 ) { 71 72 // Create WeatherBean object for city. First 16 73 // characters are city name. Next, six characters 74 // are weather description. Next six characters 75 // are HI/LO or LO/HI temperature. 76 WeatherBean weather = new WeatherBean( 77 inputLine.substring( 0, 16 ), 78 inputLine.substring( 16, 22 ), 79 inputLine.substring( 23, 29 ) ); 80 81 // add WeatherBean to List 82 weatherInformation.add( weather ); 83 84 inputLine = in.readLine(); // get next city's info 85 } 86 87 in.close(); // close connection to NWS Web server 88 89 System.out.println( "Weather information updated." ); 90 91 } // end method updateWeatherConditions 92 93 // handle exception connecting to National Weather Service 94 catch( java.net.ConnectException connectException ) { 95 connectException.printStackTrace(); 96 System.exit( 1 ); 97 } 98 Fig. 13.2 WeatherServiceImpl class implements remote interface WeatherService.Lines 70-85Lines 76-79Line 82Line 87

  10. Defines the URL that a client can use to obtain a remote reference to the server object. Implementing method defined in interface to respond to remote request. Invokes static method rebind of class Naming to bind the remote WeatherServiceImpl object service to the RMI registry with the specified URL. 99 // process other exceptions 100 catch( Exception exception ) { 101 exception.printStackTrace(); 102 System.exit( 1 ); 103 } 104 } 105 106 // implementation for WeatherService interface remote method 107 public List getWeatherInformation() throws RemoteException 108 { 109 return weatherInformation; 110 } 111 112 // launch WeatherService remote object 113 public static void main( String args[] ) throws Exception 114 { 115 System.out.println( "Initializing WeatherService..." ); 116 117 // create remote object 118 WeatherService service = new WeatherServiceImpl(); 119 120 // specify remote object name 121 String serverObjectName = "rmi://localhost/WeatherService"; 122 123 // bind WeatherService remote object in RMI registry 124 Naming.rebind( serverObjectName, service ); 125 126 System.out.println( "WeatherService running." ); 127 } 128 } Fig. 13.2 WeatherServiceImpl class implements remote interface WeatherService.Lines 107-110Line 121Line 124

  11. Load a property file that contains image names for displaying the weather information. 1 // WeatherBean.java 2 // WeatherBean maintains weather information for one city. 3 package com.deitel.advjhtp1.rmi.weather; 4 5 // Java core packages 6 import java.awt.*; 7 import java.io.*; 8 import java.net.*; 9 import java.util.*; 10 11 // Java extension packages 12 import javax.swing.*; 13 14 public class WeatherBean implements Serializable { 15 16 private String cityName; // name of city 17 private String temperature; // city's temperature 18 private String description; // weather description 19 private ImageIcon image; // weather image 20 21 private static Properties imageNames; 22 23 // initialize imageNames when class WeatherBean 24 // is loaded into memory 25 static { 26 imageNames = new Properties(); // create properties table 27 28 // load weather descriptions and image names from 29 // properties file 30 try { 31 32 // obtain URL for properties file 33 URL url = WeatherBean.class.getResource( 34 "imagenames.properties" ); 35 Fig. 13.3 WeatherBean stores weather forecast for one city.Lines 25-45

  12. 36 // load properties file contents 37 imageNames.load( new FileInputStream( url.getFile() ) ); 38 } 39 40 // process exceptions from opening file 41 catch ( IOException ioException ) { 42 ioException.printStackTrace(); 43 } 44 45 } // end static block 46 47 // WeatherBean constructor 48 public WeatherBean( String city, String weatherDescription, 49 String cityTemperature ) 50 { 51 cityName = city; 52 temperature = cityTemperature; 53 description = weatherDescription.trim(); 54 55 URL url = WeatherBean.class.getResource( "images/" + 56 imageNames.getProperty( description, "noinfo.jpg" ) ); 57 58 // get weather image name or noinfo.jpg if weather 59 // description not found 60 image = new ImageIcon( url ); 61 } 62 63 // get city name 64 public String getCityName() 65 { 66 return cityName; 67 } 68 Fig. 13.3 WeatherBean stores weather forecast for one city.

  13. 69 // get temperature 70 public String getTemperature() 71 { 72 return temperature; 73 } 74 75 // get weather description 76 public String getDescription() 77 { 78 return description; 79 } 80 81 // get weather image 82 public ImageIcon getImage() 83 { 84 return image; 85 } 86 } Fig. 13.3 WeatherBean stores weather forecast for one city.

  14. Creates a String that contains the URL for this remote object. Invoke Naming’s static method lookup to obtain a remote reference to the WeatherService remote object at the specified URL. Invoke remote method getWeatherInformation on the weatherService remote reference. 1 // WeatherServiceClient.java 2 // WeatherServiceClient uses the WeatherService remote object 3 // to retrieve weather information. 4 package com.deitel.advjhtp1.rmi.weather; 5 6 // Java core packages 7 import java.rmi.*; 8 import java.util.*; 9 10 // Java extension packages 11 import javax.swing.*; 12 13 publicclass WeatherServiceClient extends JFrame 14 { 15 // WeatherServiceClient constructor 16 public WeatherServiceClient( String server ) 17 { 18 super( "RMI WeatherService Client" ); 19 20 // connect to server and get weather information 21 try { 22 23 // name of remote server object bound to rmi registry 24 String remoteName = "rmi://" + server + "/WeatherService"; 25 26 // lookup WeatherServiceImpl remote object 27 WeatherService weatherService = 28 ( WeatherService ) Naming.lookup( remoteName ); 29 30 // get weather information from server 31 List weatherInformation = 32 weatherService.getWeatherInformation(); 33 Fig. 13.4 WeatherServiceClient client for WeatherService remote object.Line 24Lines 27-28Lines 31-32

  15. Sets a ListCellRenderer for the JList. Create a WeatherListModel to facilitate displaying the weather information in a JList. Creates a new WeatherServiceClient that connects to an RMI registry running on localhost. 34 // create WeatherListModel for weather information 35 ListModel weatherListModel = 36 new WeatherListModel( weatherInformation ); 37 38 // create JList, set ListCellRenderer and add to layout 39 JList weatherJList = new JList( weatherListModel ); 40 weatherJList.setCellRenderer( new WeatherCellRenderer()); 41 getContentPane().add( new JScrollPane( weatherJList ) ); 42 43 } // end try 44 45 // handle exception connecting to remote server 46 catch ( ConnectException connectionException ) { 47 System.err.println( "Connection to server failed. " + 48 "Server may be temporarily unavailable." ); 49 50 connectionException.printStackTrace(); 51 } 52 53 // handle exceptions communicating with remote object 54 catch ( Exception exception ) { 55 exception.printStackTrace(); 56 } 57 58 } // end WeatherServiceClient constructor 59 60 // execute WeatherServiceClient 61 publicstaticvoid main( String args[] ) 62 { 63 WeatherServiceClient client = null; 64 65 // if no sever IP address or host name specified, 66 // use "localhost"; otherwise use specified host 67 if ( args.length == 0 ) 68 client = new WeatherServiceClient( "localhost" ); Fig. 13.4 WeatherServiceClient client for WeatherService remote object.Lines 35-36Line 40Line 68

  16. 69 else 70 client = new WeatherServiceClient( args[ 0 ] ); 71 72 // configure and display application window 73 client.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 74 client.pack(); 75 client.setResizable( false ); 76 client.setVisible( true ); 77 } 78 } Fig. 13.4 WeatherServiceClient client for WeatherService remote object.

  17. 1 // WeatherListModel.java 2 // WeatherListModel extends AbstractListModel to provide a 3 // ListModel for storing a List of WeatherBeans. 4 package com.deitel.advjhtp1.rmi.weather; 5 6 // Java core packages 7 import java.util.*; 8 9 // Java extension packages 10 import javax.swing.AbstractListModel; 11 12 publicclass WeatherListModel extends AbstractListModel { 13 14 // List of elements in ListModel 15 private List list; 16 17 // no-argument WeatherListModel constructor 18 public WeatherListModel() 19 { 20 // create new List for WeatherBeans 21 list = new ArrayList(); 22 } 23 24 // WeatherListModel constructor 25 public WeatherListModel( List elementList ) 26 { 27 list = elementList; 28 } 29 30 // get size of List 31 publicint getSize() 32 { 33 return list.size(); 34 } 35 Fig. 13.5 WeatherListModel is a ListModel implementation for storing weather information.

  18. 36 // get Object reference to element at given index 37 public Object getElementAt( int index ) 38 { 39 return list.get( index ); 40 } 41 42 // add element to WeatherListModel 43 publicvoid add( Object element ) 44 { 45 list.add( element ); 46 fireIntervalAdded( this, list.size(), list.size() ); 47 } 48 49 // remove element from WeatherListModel 50 publicvoid remove( Object element ) 51 { 52 int index = list.indexOf( element ); 53 54 if ( index != -1 ) { 55 list.remove( element ); 56 fireIntervalRemoved( this, index, index ); 57 } 58 59 } // end method remove 60 61 // remove all elements from WeatherListModel 62 publicvoid clear() 63 { 64 // get original size of List 65 int size = list.size(); 66 67 // clear all elements from List 68 list.clear(); 69 Fig. 13.5 WeatherListModel is a ListModel implementation for storing weather information.

  19. 70 // notify listeners that content changed 71 fireContentsChanged( this, 0, size ); 72 } 73 } Fig. 13.5 WeatherListModel is a ListModel implementation for storing weather information.

  20. 1 // WeatherCellRenderer.java 2 // WeatherCellRenderer is a custom ListCellRenderer for 3 // WeatherBeans in a JList. 4 package com.deitel.advjhtp1.rmi.weather; 5 6 // Java core packages 7 import java.awt.*; 8 9 // Java extension packages 10 import javax.swing.*; 11 12 publicclass WeatherCellRenderer extends DefaultListCellRenderer { 13 14 // returns a WeatherItem object that displays city's weather 15 public Component getListCellRendererComponent( JList list, 16 Object value, int index, boolean isSelected, boolean focus ) 17 { 18 returnnew WeatherItem( ( WeatherBean ) value ); 19 } 20 } Fig. 13.6 WeatherCellRenderer is a custom ListCellRenderer for displaying WeatherBeans in a JList.

  21. The static block loads the ImageIconbackgroundImage into memory when the virtual machine loads the WeatherItem class itself. 1 // WeatherItem.java 2 // WeatherItem displays a city's weather information in a JPanel. 3 package com.deitel.advjhtp1.rmi.weather; 4 5 // Java core packages 6 import java.awt.*; 7 import java.net.*; 8 import java.util.*; 9 10 // Java extension packages 11 import javax.swing.*; 12 13 public class WeatherItem extends JPanel { 14 15 private WeatherBean weatherBean; // weather information 16 17 // background ImageIcon 18 private static ImageIcon backgroundImage; 19 20 // static initializer block loads background image when class 21 // WeatherItem is loaded into memory 22 static { 23 24 // get URL for background image 25 URL url = WeatherItem.class.getResource( "images/back.jpg" ); 26 27 // background image for each city's weather info 28 backgroundImage = new ImageIcon( url ); 29 } 30 31 // initialize a WeatherItem 32 public WeatherItem( WeatherBean bean ) 33 { 34 weatherBean = bean; 35 } Fig. 13.7 WeatherItem displays weather information for one city.Lines 22-29

  22. Draws the backgroundImage, the city name, the temperature and the WeatherBean’s ImageIcon. 36 37 // display information for city's weather 38 publicvoid paintComponent( Graphics g ) 39 { 40 super.paintComponent( g ); 41 42 // draw background 43 backgroundImage.paintIcon( this, g, 0, 0 ); 44 45 // set font and drawing color, 46 // then display city name and temperature 47 Font font = new Font( "SansSerif", Font.BOLD, 12 ); 48 g.setFont( font ); 49 g.setColor( Color.white ); 50 g.drawString( weatherBean.getCityName(), 10, 19 ); 51 g.drawString( weatherBean.getTemperature(), 130, 19 ); 52 53 // display weather image 54 weatherBean.getImage().paintIcon( this, g, 253, 1 ); 55 56 } // end method paintComponent 57 58 // make WeatherItem's preferred size the width and height of 59 // the background image 60 public Dimension getPreferredSize() 61 { 62 return new Dimension( backgroundImage.getIconWidth(), 63 backgroundImage.getIconHeight() ); 64 } 65 } Fig. 13.7 WeatherItem displays weather information for one city.Lines 38-56

  23. 13.5 Compiling and Executing the Server and the Client • Compile the remote object class • Generate a stub class using rmic compiler • Start the RMI registry • Run the WeatherServiceImpl application • Run the WeatherServiceClient application

  24. 13.5 Compiling and Executing the Server Client (Cont.) Fig. 13.10 WeatherServiceClient application window.

  25. 13.6 Case Study: Deitel Messenger with Activatable Server • Standard RMI objects • Run continuously on the server • Activatable RMI objects • Invoked by client • Persistent • RMI activation daemon (rmid)

  26. 13.6 Case Study: Deitel Messenger with Activatable Sever (Cont.)

  27. 13.6.1 Activatable Deitel Messenger ChatServer • Remote interface • Activatable remote object implementation • Utility program for registering and unregistering remote object

  28. Enables clients to post new messages to the chat session. Enables a ChartClient to register with the ChatServer and take part in the chat session. Enables clients to remove themselves from the chat session. Declares that interface ChatServer extends interface Remote, which RMI requires for all remote interface. 1 // ChatServer.java 2 // ChatServer is a remote interface that defines how a client 3 // registers for a chat, leaves a chat and posts chat messages. 4 package com.deitel.messenger.rmi.server; 5 6 // Java core packages 7 import java.rmi.*; 8 9 // Deitel packages 10 import com.deitel.messenger.rmi.ChatMessage; 11 import com.deitel.messenger.rmi.client.ChatClient; 12 13 publicinterface ChatServer extends Remote { 14 15 // register new ChatClient with ChatServer 16 publicvoid registerClient( ChatClient client ) 17 throws RemoteException; 18 19 // unregister ChatClient with ChatServer 20 publicvoid unregisterClient( ChatClient client ) 21 throws RemoteException; 22 23 // post new message to ChatServer 24 publicvoid postMessage( ChatMessage message ) 25 throws RemoteException; 26 } Fig. 13.12 ChatServer remote interface for Deitel Messenger chat server.Line 13Lines 16-17Lines 20-21Lines 24-25

  29. 1 // StoppableChatServer.java 2 // StoppableChatServer is a remote interface that provides a 3 // mechansim to terminate the chat server. 4 package com.deitel.messenger.rmi.server; 5 6 // Java core packages 7 import java.rmi.*; 8 9 publicinterface StoppableChatServer extends Remote { 10 11 // stop ChatServer 12 publicvoid stopServer() throws RemoteException; 13 } Fig. 13.13 StoppableChatServer remote interface for stopping a ChatServer remote object.

  30. Invokes the superclass constructor to complete activation. Creates a Set for maintaining remote references to registered ChatClients. 1 // ChatServerImpl.java 2 // ChatServerImpl implements the ChatServer remote interface 3 // to provide an RMI-based chat server. 4 package com.deitel.messenger.rmi.server; 5 6 // Java core packages 7 import java.io.*; 8 import java.net.*; 9 import java.rmi.*; 10 import java.rmi.activation.*; 11 import java.rmi.server.*; 12 import java.rmi.registry.*; 13 import java.util.*; 14 15 // Deitel packages 16 import com.deitel.messenger.rmi.ChatMessage; 17 import com.deitel.messenger.rmi.client.ChatClient; 18 19 publicclass ChatServerImpl extends Activatable 20 implements ChatServer, StoppableChatServer { 21 22 // Set of ChatClient references 23 private Set clients = new HashSet(); 24 25 // server object's name 26 private String serverObjectName; 27 28 // ChatServerImpl constructor 29 public ChatServerImpl( ActivationID id, MarshalledObject data ) 30 throws RemoteException { 31 32 // register activatable object and export on anonymous port 33 super( id, 0 ); 34 } 35 Fig. 13.14 ChatServerImpl implementation of remote interfaces ChatServer and StoppableChatServer as Activatable remote objects.Line 23Line 33

  31. Throw an IllegalArgumentException if the provided name for the remote object is null. Invokes method rebind of class Registry to bind the activatable object to the Registry. Use static method createRegistry of class LocateRegistry to create a new Registry on the local machine at port 1099. Invokes static method rebind of class Naming to bind the remote object to the existing RMI registry. 36 // register ChatServerImpl object with RMI registry. 37 publicvoid register( String rmiName ) throws RemoteException, 38 IllegalArgumentException, MalformedURLException 39 { 40 // ensure registration name was provided 41 if ( rmiName == null ) 42 thrownew IllegalArgumentException( 43 "Registration name cannot be null" ); 44 45 serverObjectName = rmiName; 46 47 // bind ChatServerImpl object to RMI registry 48 try { 49 50 // create RMI registry 51 System.out.println( "Creating registry ..." ); 52 Registry registry = 53 LocateRegistry.createRegistry( 1099 ); 54 55 // bind RMI object to default RMI registry 56 System.out.println( "Binding server to registry ..." ); 57 registry.rebind( serverObjectName, this ); 58 } 59 60 // if registry already exists, bind to existing registry 61 catch ( RemoteException remoteException ) { 62 System.err.println( "Registry already exists. " + 63 "Binding to existing registry ..." ); 64 Naming.rebind( serverObjectName, this ); 65 } 66 67 System.out.println( "Server bound to registry" ); 68 69 } // end method register 70 Fig. 13.14 ChatServerImpl implementation of remote interfaces ChatServer and StoppableChatServer as Activatable remote objects.Lines 42-43Lines 52-53Line 57Line 64

  32. Removes the given ChatClient remote reference from the Set of ChatClient references. Method registerClient enables ChatClient remote objects to register with the ChatServer to participate in the chat session. Adds the ChatClient remote reference to the Set of ChatClients participating in the chat session. Enables ChatClients to leave the chat session. 71 // register new ChatClient with ChatServer 72 publicvoid registerClient( ChatClient client ) 73 throws RemoteException 74 { 75 // add client to Set of registered clients 76 synchronized ( clients ) { 77 clients.add( client ); 78 } 79 80 System.out.println( "Registered Client: " + client ); 81 82 } // end method registerClient 83 84 // unregister client with ChatServer 85 publicvoid unregisterClient( ChatClient client ) 86 throws RemoteException 87 { 88 // remove client from Set of registered clients 89 synchronized( clients ) { 90 clients.remove( client ); 91 } 92 93 System.out.println( "Unregistered Client: " + client ); 94 95 } // end method unregisterClient 96 97 // post new message to chat server 98 publicvoid postMessage( ChatMessage message ) 99 throws RemoteException 100 { 101 Iterator iterator = null; 102 103 // get Iterator for Set of registered clients 104 synchronized( clients ) { 105 iterator = new HashSet( clients ).iterator(); Fig. 13.14 ChatServerImpl implementation of remote interfaces ChatServer and StoppableChatServer as Activatable remote objects.Lines 72-82Line 77Lines 85-95Lines 90

  33. Iterate through the Set of ChatClient references and invoke remote method deliverMessage of interface ChatClient to deliver the new ChatMessage to each client. Implements method stopServer required by interface StoppableChatServer. 106 } 107 108 // send message to every ChatClient 109 while ( iterator.hasNext() ) { 110 111 // attempt to send message to client 112 ChatClient client = ( ChatClient ) iterator.next(); 113 114 try { 115 client.deliverMessage( message ); 116 } 117 118 // unregister client if exception is thrown 119 catch( Exception exception ) { 120 System.err.println( "Unregistering absent client." ); 121 unregisterClient( client ); 122 } 123 124 } // end while loop 125 126 } // end method postMessage 127 128 // notify each client that server is shutting down and 129 // terminate server application 130 publicvoid stopServer() throws RemoteException 131 { 132 System.out.println( "Terminating server ..." ); 133 134 Iterator iterator = null; 135 136 // get Iterator for Set of registered clients 137 synchronized( clients ) { 138 iterator = new HashSet( clients ).iterator(); 139 } 140 Fig. 13.14 ChatServerImpl implementation of remote interfaces ChatServer and StoppableChatServer as Activatable remote objects.Lines 109-123Lines 128-170

  34. Create and start a new Thread to ensure that the ChatServerAdministrator can unbind the remote object from the RMI Registry before the remote object terminates. Iterate through the Set of ChatClient references and invoke method serverStopping of interface ChatClient to notify each ChatClient that the server is shutting down. 141 // send message to every ChatClient 142 while ( iterator.hasNext() ) { 143 ChatClient client = ( ChatClient ) iterator.next(); 144 client.serverStopping(); 145 } 146 147 // create Thread to terminate application after 148 // stopServer method returns to caller 149 Thread terminator = new Thread( 150 new Runnable() { 151 152 // sleep for 5 seconds, print message and terminate 153 publicvoid run() 154 { 155 // sleep 156 try { 157 Thread.sleep( 5000 ); 158 } 159 160 // ignore InterruptedExceptions 161 catch ( InterruptedException exception ) { 162 } 163 164 System.err.println( "Server terminated" ); 165 System.exit( 0 ); 166 } 167 } 168 ); 169 170 terminator.start(); // start termination thread 171 172 } // end method stopServer 173 } Fig. 13.14 ChatServerImpl implementation of remote interfaces ChatServer and StoppableChatServer as Activatable remote objects.Lines 142-145Lines 149-170

  35. Method startServer launches the activatable ChatServer. Obtain an ActivationSystem by invoking static method getSystem of class ActivationGroup. Create a Properties object and add a property that specifies the policy file under which the ActivationGroup’s JVM should run. Create an ActivationGroupDesc object, which is an activation group descriptor. Invokes static method createGroup of class ActivationGroup to create the ActivationGroup. 1 // ChatServerAdministrator.java 2 // ChatServerAdministrator is a utility program for launching 3 // and terminating the Activatable ChatServer. 4 package com.deitel.messenger.rmi.server; 5 6 // Java core packages 7 import java.rmi.*; 8 import java.rmi.activation.*; 9 import java.util.*; 10 11 publicclass ChatServerAdministrator { 12 13 // set up activatable server object 14 privatestaticvoid startServer( String policy, 15 String codebase ) throws Exception 16 { 17 // set up RMI security manager 18 System.setSecurityManager( new RMISecurityManager() ); 19 20 // set security policy for ActivatableGroup JVM 21 Properties properties = new Properties(); 22 properties.put( "java.security.policy", policy ); 23 24 // create ActivationGroupDesc for activatable object 25 ActivationGroupDesc groupDesc = 26 new ActivationGroupDesc( properties, null ); 27 28 // register activation group with RMI activation system 29 ActivationGroupID groupID = 30 ActivationGroup.getSystem().registerGroup( groupDesc ); 31 32 // create activation group 33 ActivationGroup.createGroup( groupID, groupDesc , 0 ); 34 Fig. 13.15 ChatServerAdministrator application for starting and stopping the ChatServer remote object.Lines 14-52Lines 21-22Lines 25-26Lines 29-30Line 33

  36. Create an ActivationDesc object for the ChatServer remote object. Invokes static method register of class Activatable to register the Activatable remote object. Invokes static method rebind of class Naming to bind the ChatServer in the RMI Registry. Invokes method stopServer to notify clients that the ChatServer is shutting down. Invokes static method lookup of class Naming to obtain a remote reference to the ChatServer. Invokes static method unbind of class Naming to remove the ChatServer remote object from the RMI Registry. 35 // activation description for ChatServerImpl 36 ActivationDesc description = new ActivationDesc( 37 "com.deitel.messenger.rmi.server.ChatServerImpl", 38 codebase, null ); 39 40 // register description with rmid 41 ChatServer server = 42 ( ChatServer ) Activatable.register( description ); 43 System.out.println( "Obtained ChatServerImpl stub" ); 44 45 // bind ChatServer in registry 46 Naming.rebind( "ChatServer", server ); 47 System.out.println( "Bound object to registry" ); 48 49 // terminate setup program 50 System.exit( 0 ); 51 52 } // end method startServer 53 54 // terminate server 55 privatestaticvoid terminateServer( String hostname ) 56 throws Exception 57 { 58 // lookup ChatServer in RMI registry 59 System.out.println( "Locating server ..." ); 60 StoppableChatServer server = ( StoppableChatServer ) 61 Naming.lookup( "rmi://" + hostname + "/ChatServer" ); 62 63 // terminate server 64 System.out.println( "Stopping server ..." ); 65 server.stopServer(); 66 67 // remove ChatServer from RMI registry 68 System.out.println( "Server stopped" ); 69 Naming.unbind( "rmi://" + hostname + "/ChatServer" ); Fig. 13.15 ChatServerAdministrator application for starting and stopping the ChatServer remote object.Lines 36-38Lines 41-42Line 46Line 61Line 65Line 69

  37. Invokes method terminateServer to shut down the ChatServer on the specified host if the user passes argument stop. Invokes method startServer with the given policy file location and codebase if the user passes argument start. 70 71 } // end method terminateServer 72 73 // launch ChatServerAdministrator application 74 publicstaticvoid main( String args[] ) throws Exception 75 { 76 // check for stop server argument 77 if ( args.length == 2 ) { 78 79 if ( args[ 0 ].equals( "stop" ) ) 80 terminateServer( args[ 1 ] ); 81 82 else printUsageInstructions(); 83 } 84 85 // check for start server argument 86 elseif ( args.length == 3 ) { 87 88 // start server with user-provided policy, codebase 89 // and Registry hostname 90 if ( args[ 0 ].equals( "start" ) ) 91 startServer( args[ 1 ], args[ 2 ] ); 92 93 else printUsageInstructions(); 94 } 95 96 // wrong number of arguments provided, so print instructions 97 else printUsageInstructions(); 98 99 } // end method main 100 Fig. 13.15 ChatServerAdministrator application for starting and stopping the ChatServer remote object.Line 80Line 91

  38. 101 // print instructions for running ChatServerAdministrator 102 privatestaticvoid printUsageInstructions() 103 { 104 System.err.println( "\nUsage:\n" + 105 "\tjava com.deitel.messenger.rmi.server." + 106 "ChatServerAdministrator start <policy> <codebase>\n" + 107 "\tjava com.deitel.messenger.rmi.server." + 108 "ChatServerAdministrator stop <registry hostname>" ); 109 } 110 } Fig. 13.15 ChatServerAdministrator application for starting and stopping the ChatServer remote object.

  39. 1 // allow ActivationGroup to terminate the virtual machine 2 grant { 3 permission java.lang.RuntimePermission "exitVM"; 4 }; Fig. 13.16 Policy file for ChatServer’s ActivationGroup.

  40. 13.6.2 Deitel Messenger Client Architecture and Implementation • Communication Interfaces and Implementation • Client GUI Interfaces and Implementation

  41. Enables the ChatServer to notify the ChatClient when the ChatServer is shutting down. Enables the ChatServer to send new ChatMessages to the ChatClient. 1 // ChatClient.java 2 // ChatClient is a remote interface that defines methods for a 3 // chat client to receive messages and status information from 4 // a ChatServer. 5 package com.deitel.messenger.rmi.client; 6 7 // Java core packages 8 import java.rmi.*; 9 10 // Deitel packages 11 import com.deitel.messenger.rmi.ChatMessage; 12 13 publicinterface ChatClient extends Remote { 14 15 // method called by server to deliver message to client 16 publicvoid deliverMessage( ChatMessage message ) 17 throws RemoteException; 18 19 // method called when server shuting down 20 publicvoid serverStopping() throws RemoteException; 21 } Fig. 13.17 ChatClient remote interface to enable RMI callbacks.Lines 16-17Line 20

  42. 1 // ChatMessage.java 2 // ChatMessage is a Serializable object for messages in the RMI 3 // ChatClient and ChatServer. 4 package com.deitel.messenger.rmi; 5 6 // Java core packages 7 import java.io.*; 8 9 publicclass ChatMessage implements Serializable { 10 11 private String sender; // person sending message 12 private String message; // message being sent 13 14 // construct empty ChatMessage 15 public ChatMessage() 16 { 17 this( "", "" ); 18 } 19 20 // construct ChatMessage with sender and message values 21 public ChatMessage( String sender, String message ) 22 { 23 setSender( sender ); 24 setMessage( message ); 25 } 26 27 // set name of person sending message 28 publicvoid setSender( String name ) 29 { 30 sender = name; 31 } 32 Fig. 13.18 ChatMessage is a serializable class for transmitting messages over RMI.

  43. 33 // get name of person sending message 34 public String getSender() 35 { 36 return sender; 37 } 38 39 // set message being sent 40 publicvoid setMessage( String messageBody ) 41 { 42 message = messageBody; 43 } 44 45 // get message being sent 46 public String getMessage() 47 { 48 return message; 49 } 50 51 // String representation of ChatMessage 52 public String toString() 53 { 54 return getSender() + "> " + getMessage(); 55 } 56 } Fig. 13.18 ChatMessage is a serializable class for transmitting messages over RMI.

  44. Connects to the ChatServer and takes as an argument the MessageListener to which the MessageManager should deliver new incoming messages. Disconnects the MessageManager from the ChatServer and stops routing messages to the given MessageListener. Sends a message to the ChatServer. Registers a DisconnectListener to be notified when the ChatServer disconnects the client. 1 // MessageManager.java 2 // MessageManger is an interface for objects capable of managing 3 // communications with a message server. 4 package com.deitel.messenger; 5 6 publicinterface MessageManager { 7 8 // connect to message server and route incoming messages 9 // to given MessageListener 10 publicvoid connect( MessageListener listener ) 11 throws Exception; 12 13 // disconnect from message server and stop routing 14 // incoming messages to given MessageListener 15 publicvoid disconnect( MessageListener listener ) 16 throws Exception; 17 18 // send message to message server 19 publicvoid sendMessage( String from, String message ) 20 throws Exception; 21 22 // set listener for disconnect notifications 23 publicvoid setDisconnectListener( 24 DisconnectListener listener ); 25 } Fig. 13.19 MessageManager interface for classes that implement communication logic for a ChatClient.Lines 10-11Liness 15-16Lines 19-20Lines 23-24

  45. 1 // RMIMessageManager.java 2 // RMIMessageManager implements the ChatClient remote interface 3 // and manages incoming and outgoing chat messages using RMI. 4 package com.deitel.messenger.rmi.client; 5 6 // Java core packages 7 import java.awt.*; 8 import java.awt.event.*; 9 import java.rmi.*; 10 import java.rmi.server.*; 11 import java.util.*; 12 13 // Deitel packages 14 import com.deitel.messenger.*; 15 import com.deitel.messenger.rmi.*; 16 import com.deitel.messenger.rmi.server.ChatServer; 17 18 publicclass RMIMessageManager extends UnicastRemoteObject 19 implements ChatClient, MessageManager { 20 21 // listeners for incoming messages and disconnect notifications 22 private MessageListener messageListener; 23 private DisconnectListener disconnectListener; 24 25 private String serverAddress; 26 private ChatServer chatServer; 27 28 // RMIMessageManager constructor 29 public RMIMessageManager( String server ) throws RemoteException 30 { 31 serverAddress = server; 32 } 33 Fig. 13.20 RMIMessageManager remote object and MessageManager implementation for managing Chatclient communication.

  46. Invoke static method lookup of class Naming to retrieve a remote reference to the ChatServer. Passes the this reference as the argument to method registerClient. Invokes method unregisterClient of remote interface ChatServer to unregister the RMIMessageManager from the ChatServer. 34 // connect to ChatServer 35 publicvoid connect( MessageListener listener ) 36 throws Exception 37 { 38 // look up ChatServer remote object 39 chatServer = ( ChatServer ) Naming.lookup( 40 "//" + serverAddress + "/ChatServer" ); 41 42 // register with ChatServer to receive messages 43 chatServer.registerClient( this ); 44 45 // set listener for incoming messages 46 messageListener = listener; 47 48 } // end method connect 49 50 // disconnect from ChatServer 51 publicvoid disconnect( MessageListener listener ) 52 throws Exception 53 { 54 if ( chatServer == null ) 55 return; 56 57 // unregister with ChatServer 58 chatServer.unregisterClient( this ); 59 60 // remove references to ChatServer and MessageListener 61 chatServer = null; 62 messageListener = null; 63 64 } // end method disconnect 65 Fig. 13.20 RMIMessageManager remote object and MessageManager implementation for managing Chatclient communication.Lines 39-40Line 43Line 58

  47. Create a new ChatMessage object to obtain the user name from whom the message came and the message body. Invokes method postMessage of remote interface ChatServer to post the new ChatMessage to the ChatServer. Invoke method messageReceived of interface MessageListener to notify the MessageListener of the incoming ChatMessage. Invokes method fireServerDisconnected of class RMIMessageManager to notify the registered DisconnectListener that the ChatServer has disconnected the ChatClient. 66 // send ChatMessage to ChatServer 67 publicvoid sendMessage( String fromUser, String message ) 68 throws Exception 69 { 70 if ( chatServer == null ) 71 return; 72 73 // create ChatMessage with message text and userName 74 ChatMessage chatMessage = 75 new ChatMessage( fromUser, message ); 76 77 // post message to ChatServer 78 chatServer.postMessage( chatMessage ); 79 80 } // end method sendMessage 81 82 // process delivery of ChatMessage from ChatServer 83 publicvoid deliverMessage( ChatMessage message ) 84 throws RemoteException 85 { 86 if ( messageListener != null ) 87 messageListener.messageReceived( message.getSender(), 88 message.getMessage() ); 89 } 90 91 // method called when server shutting down 92 publicvoid serverStopping() throws RemoteException 93 { 94 chatServer = null; 95 fireServerDisconnected( "Server shut down." ); 96 } 97 Fig. 13.20 RMIMessageManager remote object and MessageManager implementation for managing Chatclient communication.Lines 74-75Line 78Lines 87-88Line 95

  48. Sends serverDisconnected messages to the DisconnectListener. Enables a DisconnectListener to register for notifications when the ChatServer disconnects the client. 98 // register listener for disconnect notifications 99 publicvoid setDisconnectListener( 100 DisconnectListener listener ) 101 { 102 disconnectListener = listener; 103 } 104 105 // send disconnect notification 106 privatevoid fireServerDisconnected( String message ) 107 { 108 if ( disconnectListener != null ) 109 disconnectListener.serverDisconnected( message ); 110 } 111 } Fig. 13.20 RMIMessageManager remote object and MessageManager implementation for managing Chatclient communication.Lines 99-103Lines 106-110

  49. 1 // MessageListener.java 2 // MessageListener is an interface for classes that wish to 3 // receive new chat messages. 4 package com.deitel.messenger; 5 6 publicinterface MessageListener { 7 8 // receive new chat message 9 publicvoid messageReceived( String from, String message ); 10 } Fig. 13.21 MessageListener interface for receiving new messages.

  50. 1 // DisconnectListener.java 2 // DisconnectListener defines method serverDisconnected, which 3 // indicates that the server has disconnected the client. 4 package com.deitel.messenger; 5 6 publicinterface DisconnectListener { 7 8 // receive notification that server disconnected 9 publicvoid serverDisconnected( String message ); 10 } Fig. 13.22 DisconnectListener interface for receiving server disconnect notifications.

More Related