CS 696 Emerging Technologies: Java Distributed Computing Spring Semester, 1999 RMI Configuration, API |
||
---|---|---|
© 1999, All Rights Reserved, SDSU & Roger Whitney San Diego State University -- This page last updated 16-Feb-99 |
RMI Configuration Problems
There are two problems that occur on rohan due to configuration problems. The first shows when you try to bind the server to the rmiregistry. The second when you try find the server from a client on a remote machine.
Server Binding to rmiregistry
On rohan the following will not bind the server to the rmiregistry
Naming.rebind("rmi://rohan.sdsu.edu:5555/label", serverObject );Due to some configuration problem, rmi does not think that rohan.sdsu.edu is the local host on rohan.
Use either:
Naming.rebind("rmi://:5555/label", serverObject );
Naming.rebind("rmi://localhost:5555/label", serverObject );
Or see java.rmi.registry.LocateRegistry later in this document
Client Binding to Remote Server
The situation Server & rmiregistry run on rohan
Client works fine on rohan
Client can not connect to server from any other machine
The Problem The server tells rmiregistry it is running on localhost
rmiregistry tells client to look on localhost for the server
Client’s local host does not contain server
Solution
Tell the server its host name by setting the property:
java -Djava.rmi.server.hostname=rohan.sdsu.edu HelloServer &
void setHostName() { Properties systemProperties = new Properties( System.getProperties() ); systemProperties.put("java.rmi.server.hostname","rohan.sdsu.edu"); System.setProperties(systemProperties); }
What is Supposed to Happen
1. Start RMI
2. Register Server
Server is started on a random port and gives RMI Registry, label, port number and host machine name
3. Client connects with RMI Registry
RMI Registry gives client server information
4. Client talks to server
What did Happen?
Server did not know its host name
When Client contacted RMI registry it assumes or is told that the server is on the local host, i.e. the client machine
Client tries to connect to server on its machine, but server is not there!
Exceptions
All methods in a Remote interface must state they can throw java.rmi.RemoteException
In JDK 1.1.x any exception thrown by a remote method had to be a subclass of RemoteException if you wanted the client to catch the exception. In JDK 1.2 a remote method can throw any exception and the client can catch it. The following example illustrates this.
TestException.java package whitney.rmi.examples.basic; public class TestException extends Exception { public TestException() {} public TestException( String message ) { super(message); } }Hello.java package whitney.rmi.examples.basic; import java.rmi.RemoteException; public interface Hello extends java.rmi.Remote { String sayHello() throws RemoteException, TestException; }
HelloServer.java package whitney.rmi.examples.basic; import java.io.IOException; import java.net.InetAddress; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.RMISecurityManager; import java.rmi.registry.Registry; // for port number import java.rmi.server.UnicastRemoteObject; import sdsu.util.ProgramProperties; public class HelloServer extends UnicastRemoteObject implements Hello { public HelloServer() throws RemoteException { } public String sayHello() throws RemoteException, TestException { throw new TestException( "this is a test" ); } protected static String getHostName() { try { return InetAddress.getLocalHost().getHostName(); } catch (java.net.UnknownHostException who) { return "Unknown"; } }
//HelloServer.java Continued private static String getHelloHostAddress( String args[] ) throws IOException { ProgramProperties flags = new ProgramProperties( args, "config" ); int defaultPort = Registry.REGISTRY_PORT; int port = flags.getInt( "port", defaultPort ); String serverLabel = flags.getString( "label" ); // can only bind to local host, protocol defaults // to local host, do not add a host here return "rmi://" + ":" + port + "/" + serverLabel ; } public static void main(String args[]){ System.setSecurityManager(new RMISecurityManager()); try { String serverAddress = getHelloHostAddress( args ); HelloServer serverObject = new HelloServer(); Naming.rebind( serverAddress, serverObject); System.out.println("HelloServer bound in registry under: " + serverAddress); } catch (Exception e) { System.out.println("HelloServer err: "); e.printStackTrace(); } } }
HelloClient.java package whitney.rmi.examples.basic; import java.rmi.*; import java.rmi.registry.Registry; import java.net.MalformedURLException; import java.io.IOException; import sdsu.util.ProgramProperties; public class HelloClient { public static void main(String args[]) { try { String server = getHelloHostAddress( args); System.out.println( server ); Hello remote = (Hello) Naming.lookup( server ); System.out.println( "after lookup" ); String message = remote.sayHello(); System.out.println( message ); } catch ( TestException test) { System.out.println( "TestException" + test.getMessage() ); test.printStackTrace(); } catch ( RemoteException test) { System.out.println( "RemotException" + test.getMessage() ); test.printStackTrace(); } catch ( Exception test) { System.out.println( "All" + test.getMessage() ); test.printStackTrace(); } }
//HelloClient.java Continued
private static String getHelloHostAddress( String args[] ) throws IOException { ProgramProperties flags = new ProgramProperties( args ); String host = flags.getString( "host" ); int defaultPort = Registry.REGISTRY_PORT; int port = flags.getInt( "port", defaultPort ); String serverLabel = flags.getString( "label" ); return "rmi://" + host + ":" + port + "/" + serverLabel; } }
Some Important RMI API
java.rmi.registry.Registry
Methods
java.rmi.registry.LocateRegistry
Static Methods
Server Side usage of LocateRegistry This example shows how to create a registry and bind server objects in one method and one JVM.
package whitney.rmi.examples.basic; import java.io.IOException; import java.rmi.RemoteException; import java.rmi.RMISecurityManager; import java.rmi.registry.Registry; import java.rmi.registry.LocateRegistry; import java.rmi.server.UnicastRemoteObject; import sdsu.util.ProgramProperties; public class HelloServer extends UnicastRemoteObject implements Hello { public HelloServer() throws RemoteException { } public String sayHello() throws RemoteException { return "Hello World from " + getHostName(); } private static Registry getRegistry( int port ) throws RemoteException { try { return LocateRegistry.createRegistry(port ); } catch (Exception noRegistry) { return LocateRegistry.getRegistry( port ); } } public static void main(String args[]) { System.setSecurityManager(new RMISecurityManager()); try { ProgramProperties flags = new ProgramProperties( args, "config" ); int port = flags.getInt( "port", Registry.REGISTRY_PORT); String serverLabel = flags.getString( "label" ); HelloServer serverObject = new HelloServer(); Registry myRegistry = getRegistry(port ); myRegistry.rebind( serverLabel, serverObject); System.out.println("HelloServer bound as: " + serverLabel); } catch (Exception e) { System.out.println("HelloServer err: "); e.printStackTrace(); } } }
Client-Side usage of LocateRegistry
public class HelloClient { public static void main(String args[]) { try { Registry local = LocateRegistry.getRegistry("eli.sdsu.edu", 1099 ); Hello remote = (Hello) local.lookup( "test" ); String message = remote.sayHello(); System.out.println( message ); } catch ( Exception test) { System.out.println( "All" + test.getMessage() ); test.printStackTrace(); } }
Server Parent Classes
Servers typically extend UnicastRemoteObject:
public class HelloServer extends UnicastRemoteObject implements Hello { blah}The class Structure
java.lang.Object | +----java.rmi.server.RemoteObject | +----java.rmi.server.RemoteServer | +----java.rmi.server.UnicastRemoteObject
java.rmi.server.RemoteObject
Implements java.lang.Object behavior for remote objects
Methods
whitney.rmi.examples.basic.HelloServer_Stub[RemoteStub [ref: [endpoint:[130.191.234.12:33880](remote),objID:[1ad7c0b:d5fefc4e28:-8000, 0]]]]
java.rmi.server.RemoteServer
Static Methods
java.rmi.server.logCalls
Logging Example
package whitney.rmi.examples.basic; import java.io.IOException; import java.io.PrintStream; import java.io.FileOutputStream; import java.io.BufferedOutputStream; import java.rmi.RemoteException; import java.rmi.RMISecurityManager; import java.rmi.server.UnicastRemoteObject; import java.rmi.server.RemoteServer; import java.rmi.server.ServerNotActiveException; public class HelloServer extends UnicastRemoteObject implements Hello { PrintStream logger; public HelloServer() throws RemoteException { try { FileOutputStream log = new FileOutputStream( "MyLog"); setLog(new BufferedOutputStream( log )); logger = getLog(); } catch(java.io.FileNotFoundException noFile ) { logger = null; System.err.println( "No log file" ); } } public String sayHello() throws RemoteException { try { if (logger != null ) logger.println( "sayHello called by: " + RemoteServer.getClientHost() ); } catch (ServerNotActiveException error ) { logger.println( "sayHello called, can not get client host" ); } return "Hello World from eli"; } }
Starting the Server The following command was used to start the server:
java -Djava.rmi.server.logCalls=true whitney.rmi.examples.basic.HelloServer &
Log Contents
The following are the contents of log file. These entries were generated by one client request. Note that the call to RemoteServer.getClientHost was not needed as the log entry already contained the client IP address.
Mon Feb 15 17:09:45 PST 1999:RMI:RMI TCP Connection(3)-eli.sdsu.edu/130.191.234.12:[130.191.234.12: sun.rmi.registry.RegistryImpl[0:0:0, 0]: java.rmi.Remote lookup(java.lang.String)] Mon Feb 15 17:09:46 PST 1999:RMI:RMI TCP Connection(4)-eli.sdsu.edu/130.191.234.12:[130.191.234.12: sun.rmi.transport.DGCImpl[0:0:0, 2]: java.rmi.dgc.Lease dirty(java.rmi.server.ObjID[], long, java.rmi.dgc.Lease)] Mon Feb 15 17:09:47 PST 1999:RMI:RMI TCP Connection(4)-eli.sdsu.edu/130.191.234.12:[130.191.234.12: whitney.rmi.examples.basic.HelloServer[0]: public abstract java.lang.String whitney.rmi.examples.basic.Hello.sayHello() throws java.rmi.RemoteException] Mon Feb 15 17:09:47 PST 1999:RMI:RMI TCP Connection(4)-eli.sdsu.edu/130.191.234.12:sayHello called by: 130.191.234.12
Logging - A More General System
Neil Harrison in Pattern Languages of Program
Design 3 Eds. Martin, Riehle, Buschman, 1998, pp. 277-289.
sdsu.logging.Logger
Defines types of logging messages
ScreenLogger |
Send
log data to screen
|
FileLogger |
Send
log data to a file
|
NullLogger |
Ignores
log data
|
Sample Use of Logger
import sdsu.logging.*; public class Tester { public static void main( String[] args) throws LoggerCreationException { FileLogger myLog = FileLogger.register( "LogFile"); myLog.debugOff(); myLog.warningOff(); // Some where else in the program Logger.debug( "I am lost, This does not work"); Logger.log( "Routine log stuff" ); } }
java.rmi.server.UnicastRemoteObject
Constructors
UnicastRemoteObject()
|
Create
& export a UnicastRemoteObject object using an anonymous port.
|
UnicastRemoteObject(int
port)
|
Create
& export an UnicastRemoteObject object using the particular supplied port.
|
UnicastRemoteObject(int
port,
RMIClientSocketFactory cf, RMIServerSocketFactory sf) |
Create
& export an UnicastRemoteObject object using the particular supplied port
and socket factories
|
clone() |
Returns
a clone of the remote object that is distinct from the original.
|
exportObject(Remote) |
Export
the remote object to make it available to receive incoming calls.
|