Chapter 13: Remote Method Invocation
Outline
13.1 Introduction
13.2 Case Study: Creating a Distributed System with RMI
13.3 Defining the Remote Interface
13.4 Implementing the Remote Interface
13.5 Compiling and Executing the Server and the Client 13.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 Applications
13.7 Internet and World Wide Web Resources
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
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
13.3 Defining the Remote Interface
• Remote interface
– Describes the remote methods
– Extends interface java.rmi.Remote
2002 Prentice Hall.
Outline
Fig. 13.1
WeatherService interface.
Line 10 Line 13
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 }
Interface WeatherService extends interface Remote.
Declares method getWeatherInformation, which clients can invoke to retrieve weather information from the remote object.
13.4 Implementing the Remote Interface
• Remote object implementation
– WeatherServiceImpl
2002 Prentice Hall.
Outline
Fig. 13.2
WeatherServiceIm pl class
implements
remote interface WeatherService.
Lines 13-14 Line 21
Lines 32-33
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
Extends class
UnicastRemoteObject to obtain basic functionality required for all remote objects and implements interface WeatherService.
Invokes the default constructor for class UnicastRemoteObject.
Create a URL object for the Traveler’s Forecast Web page.
Outline
Fig. 13.2
WeatherServiceIm pl class
implements
remote interface WeatherService.
Line 42-43 Line 57
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
Read through the Traveler’s Forecast Web page until reaching the sentinel.
Read next line from the Web page.
2002 Prentice Hall.
Outline
Fig. 13.2
WeatherServiceIm pl class
implements
remote interface WeatherService.
Lines 70-85 Lines 76-79 Line 82
Line 87
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
Read each city’s weather information and place this information in
WeatherBean objects.
Construct a WeatherBean object for the current city.
Adds the WeatherBean object to the List.
Closes the
BufferedReader and its associated InputStream.
Outline
Fig. 13.2
WeatherServiceIm pl class
implements
remote interface WeatherService.
Lines 107-110 Line 121
Line 124
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 }
Implementing method defined in interface to respond to remote request.
Defines the URL that a client can use to obtain a remote reference to the server object.
Invokes static method rebind of class Naming to bind the remote WeatherServiceImpl object service to the RMI registry with the specified URL.
2002 Prentice Hall.
Outline
Fig. 13.3 WeatherBean stores weather forecast for one city.
Lines 25-45
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
Load a property file that contains image names for displaying the weather information.
Outline
Fig. 13.3 WeatherBean stores weather forecast for one city.
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
2002 Prentice Hall.
Outline
Fig. 13.3 WeatherBean stores weather forecast for one city.
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 }
Outline
Fig. 13.4
WeatherServiceCl ient client for WeatherService remote object.
Line 24
Lines 27-28 Lines 31-32
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 public class 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
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.
2002 Prentice Hall.
Outline
Fig. 13.4
WeatherServiceCl ient client for WeatherService remote object.
Lines 35-36 Line 40
Line 68
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 public static void 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" );
Create a WeatherListModel to facilitate displaying the weather information in a JList.
Sets a
ListCellRenderer for the JList.
Creates a new
WeatherServiceClient that connects to an RMI registry running on localhost.
Outline
Fig. 13.4
WeatherServiceCl ient client for WeatherService remote object.
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 }
2002 Prentice Hall.
Outline
Fig. 13.5
WeatherListModel is a ListModel implementation for storing weather
information.
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 public class 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 public int getSize() 32 {
33 return list.size();
34 } 35
Outline
Fig. 13.5
WeatherListModel is a ListModel implementation for storing weather
information.
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 public void add( Object element ) 44 {
45 list.add( element );
46 fireIntervalAdded( this, list.size(), list.size() );
47 } 48
49 // remove element from WeatherListModel 50 public void 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 public void clear()
63 {
64 // get original size of List 65 int size = list.size();
66
67 // clear all elements from List 68 list.clear();
69
2002 Prentice Hall.
Outline
Fig. 13.5
WeatherListModel is a ListModel implementation for storing weather
information.
70 // notify listeners that content changed 71 fireContentsChanged( this, 0, size );
72 } 73 }
Outline
Fig. 13.6
WeatherCellRende rer is a custom ListCellRenderer for displaying WeatherBeans in a JList.
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 public class 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 return new WeatherItem( ( WeatherBean ) value );
19 } 20 }
2002 Prentice Hall.
Outline
Fig. 13.7 WeatherItem
displays weather information for one city.
Lines 22-29
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 }
The static block loads the
ImageIcon backgroundImage into memory when the virtual machine loads the WeatherItem class itself.
Outline
Fig. 13.7 WeatherItem
displays weather information for one city.
Lines 38-56
36
37 // display information for city's weather 38 public void 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 }
Draws the backgroundImage, the city name, the temperature and the WeatherBean’s ImageIcon.
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
13.5 Compiling and Executing the Server Client (Cont.)
Fig. 13.10 WeatherServiceClient application window.
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)
13.6 Case Study: Deitel Messenger with Activatable Sever (Cont.)
Name Role
ChatServer Remote interface through which clients register for a chat, leave a chat, and post chat messages.
StoppableChatServer Administrative remote interface for terminating the chat server.
ChatServerImpl Implementation of the ChatServer remote interface that provides an RMI-based chat server.
ChatServerAdministrator Utility program for launching and terminating the activatable ChatServer.
ChatClient Remote interface through which the ChatServer communicates with clients.
ChatMessage Serializable object for sending messages between ChatServer and ChatClients.
MessageManager Interface that defines methods for managing
communication between the client’s user interface and the ChatServer.
RMIMessageManager ChatClient and MessageManager
implementation for managing communication between the client and the ChatServer.
MessageListener Interface for classes that wish to receive new chat messages.
DisconnectListener Interface for classes that wish to receive notifications when the server disconnects.
ClientGUI GUI for sending and receiving chat messages using a MessageManager.
DeitelMessenger Application launcher for Deitel Messenger client.
Fig. 13.11 Pa rtic ipants of DeitelMessenger c a se study.
13.6.1 Activatable Deitel Messenger ChatServer
• Remote interface
• Activatable remote object implementation
• Utility program for registering and unregistering
remote object
Outline
Fig. 13.12 ChatServer
remote interface for Deitel
Messenger chat server.
Line 13
Lines 16-17 Lines 20-21 Lines 24-25
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 public interface ChatServer extends Remote { 14
15 // register new ChatClient with ChatServer
16 public void registerClient( ChatClient client ) 17 throws RemoteException;
18
19 // unregister ChatClient with ChatServer
20 public void unregisterClient( ChatClient client ) 21 throws RemoteException;
22
23 // post new message to ChatServer
24 public void postMessage( ChatMessage message ) 25 throws RemoteException;
26 }
Declares that interface ChatServer extends interface Remote, which RMI requires for all remote interface.Enables a ChartClient to register
with the ChatServer and take part in the chat session.
Enables clients to remove themselves from the chat session.
Enables clients to post new messages to the chat session.
2002 Prentice Hall.
Outline
Fig. 13.13
StoppableChatSer ver remote
interface for stopping a ChatServer remote object.
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 public interface StoppableChatServer extends Remote { 10
11 // stop ChatServer
12 public void stopServer() throws RemoteException;
13 }
Outline
Fig. 13.14
ChatServerImpl implementation of remote
interfaces
ChatServer and StoppableChatSer ver as
Activatable remote objects.
Line 23 Line 33
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 public class 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 }
Creates a Set for maintaining remote references to registered ChatClients.
Invokes the superclass constructor to complete activation.
2002 Prentice Hall.
Outline
Fig. 13.14
ChatServerImpl implementation of remote
interfaces
ChatServer and StoppableChatSer ver as
Activatable remote objects.
Lines 42-43 Lines 52-53 Line 57
Line 64
36 // register ChatServerImpl object with RMI registry.
37 public void register( String rmiName ) throws RemoteException, 38 IllegalArgumentException, MalformedURLException
39 {
40 // ensure registration name was provided 41 if ( rmiName == null )
42 throw new 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
Throw an IllegalArgumentException if the provided name for the remote object is null.
Use static method createRegistry of class LocateRegistry to create a new Registry on the local machine at port 1099.
Invokes method rebind of class Registry to bind the activatable object to the Registry.
Invokes static method rebind of class Naming to bind the remote object to the existing RMI registry.
Outline
Fig. 13.14
ChatServerImpl implementation of remote
interfaces
ChatServer and StoppableChatSer ver as
Activatable remote objects.
Lines 72-82 Line 77
Lines 85-95 Lines 90
71 // register new ChatClient with ChatServer
72 public void 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 public void 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 public void postMessage( ChatMessage message ) 99 throws RemoteException
100 {
101 Iterator iterator = null;
102
103 // get Iterator for Set of registered clients 104 synchronized( clients ) {
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.
Removes the given ChatClient remote reference from the Set of ChatClient references.
2002 Prentice Hall.
Outline
Fig. 13.14
ChatServerImpl implementation of remote
interfaces
ChatServer and StoppableChatSer ver as
Activatable remote objects.
Lines 109-123 Lines 128-170
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 public void 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
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.
Outline
Fig. 13.14
ChatServerImpl implementation of remote
interfaces
ChatServer and StoppableChatSer ver as
Activatable remote objects.
Lines 142-145 Lines 149-170
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 public void 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 }
Iterate through the Set of ChatClient references and invoke method
serverStopping of interface
ChatClient to notify each ChatClient that the server is shutting down.
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.
2002 Prentice Hall.
Outline
Fig. 13.15
ChatServerAdmini strator
application for starting and stopping the ChatServer remote object.
Lines 14-52 Lines 21-22 Lines 25-26 Lines 29-30 Line 33
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 public class ChatServerAdministrator { 12
13 // set up activatable server object
14 private static void 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
Method startServer launches the activatable ChatServer.
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.
Obtain an ActivationSystem
by invoking static method getSystem of class
ActivationGroup.
Invokes static method createGroup of class ActivationGroup to create the ActivationGroup.
Outline
Fig. 13.15
ChatServerAdmini strator
application for starting and stopping the ChatServer remote object.
Lines 36-38 Lines 41-42 Line 46
Line 61 Line 65 Line 69
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 private static void 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" );
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 static method lookup of class Naming to obtain a remote reference to the ChatServer.
Invokes method stopServer to notify clients that the ChatServer is shutting down.
Invokes static method unbind of class Naming to remove the ChatServer remote object from the RMI Registry.
2002 Prentice Hall.
Outline
Fig. 13.15
ChatServerAdmini strator
application for starting and stopping the ChatServer remote object.
Line 80 Line 91
70
71 } // end method terminateServer 72
73 // launch ChatServerAdministrator application
74 public static void 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 else if ( 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
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.
Outline
Fig. 13.15
ChatServerAdmini strator
application for starting and stopping the ChatServer remote object.
101 // print instructions for running ChatServerAdministrator 102 private static void 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 }
2002 Prentice Hall.
Outline
Fig. 13.16
Policy file for ChatServer’s ActivationGroup.
1 // allow ActivationGroup to terminate the virtual machine 2 grant {
3 permission java.lang.RuntimePermission "exitVM";
4 };