Presentation is loading. Please wait.

Presentation is loading. Please wait.

CIS 5930-04 – Spring 2001 Instructors: Geoffrey Fox, Bryan Carpenter Computational Science and.

Similar presentations


Presentation on theme: "CIS 5930-04 – Spring 2001 Instructors: Geoffrey Fox, Bryan Carpenter Computational Science and."— Presentation transcript:

1 dbc@csit.fsu.edu1 CIS 5930-04 – Spring 2001 http://aspen.csit.fsu.edu/it1spring01 Instructors: Geoffrey Fox, Bryan Carpenter Computational Science and Information Technology Florida State University Acknowledgements: Nancy McCracken Syracuse University Part 5: Java RMI—Remote Method Invocation

2 dbc@csit.fsu.edu2 Remote Method Invocation  Java RMI is a mechanism that allows a Java program running on one computer (e.g., the client) to apply a method to an object on a different computer (e.g., the server).  In itself, the syntax of the remote invocation looks exactly like an ordinary Java method invocation. The remote method call can be passed arguments computed in the context of the local machine. It can return arbitrary values computed in the context of the remote machine. The RMI system transparently forwards these arguments and results.  RMI is an implementation of the of the Distributed Object programming model—similar to CORBA, but simpler, and specialized to the Java language

3 dbc@csit.fsu.edu3 Example Local Machine Remote Machine res = obj.meth(arg) ; ResType meth(ArgType arg) {... return new ResImpl(...) ; }  Assume code running in the local machine holds a remote reference to an object obj on a remote machine: obj

4 dbc@csit.fsu.edu4  Remote objects—these are normal Java objects, but their class extends some RMI library class that incorporates support for remote invocation.  Remote references—object references that effectively refer to remote objects, typically on a different computer.  Remote interfaces—normal Java interfaces, that specify the “API” of a remote object. They should extend the marker interface, java.rmi.Remote. The remote interface must be known to both the local and remote code. Central Components of Java RMI

5 dbc@csit.fsu.edu5  Registries—places where the local machine initially looks to find a reference to a remote object.  Serialization—reduction of Java objects to a representation that can be communicated as a byte stream (for arguments and results).  Dynamic class loading—needed in various places. One example is when a remote method returns an object whose class (e.g. ResImpl) was not previously known on the calling machine. Also used for stubs—see later.  Security manager—used to control the behavior of code loaded from a remote host. Some Supporting Technologies

6 dbc@csit.fsu.edu6 Related Approaches to Networking  Sockets –Traditionally quite hard to program, although the java.net package makes it relatively easy to establish a socket network connection to another host. Communication takes place via streams, but you must define the detailed protocols for message exchange yourself. –High-level compared with Unix sockets, but low-level compared to RMI.  Remote Procedure Call (RPC) –An earlier UNIX protocol to allow calling remote procedures. –Programmers register their application with a host port mapper. –Protocols for parameter-passing support a limited number of types.  CORBA –See next semester’s course...

7 dbc@csit.fsu.edu7 References  Core Java 2, Volume II, Chapter 5: “Remote Objects”.  Java RMI, Troy Bryan Downing, IDG books, 1998.  “Getting Started Using RMI”, and other documents, at: http://java.sun.com/products/jdk/rmi/

8 dbc@csit.fsu.edu8 Getting Started

9 dbc@csit.fsu.edu9 The Remote Interface  In RMI, a common remote interface is the minimum amount of information that must be shared in advance between “client” and “server” machines. It defines a high-level “protocol” through which the machines will communicate.  A remote interface is an ordinary Java interface, which must extent the marker interface java.rmi.Remote.  All methods in a remote interface must be declared to throw the java.rmi.RemoteException exception.

10 dbc@csit.fsu.edu10 A Simple Example  A file MessageWriter.java contains the interface definition: import java.rmi.* ; public interface MessageWriter extends Remote { void writeMessage(String s) throws RemoteException ; }  This interface defines a single remote method, writeMessage().

11 dbc@csit.fsu.edu11 java.rmi.Remote  The interface java.rmi.Remote is a marker interface.  It declares no methods or fields; however, extending it tells the RMI system to treat the interface concerned as a remote interface.  In particular we will see that the rmic compiler generates extra code for classes that implement remote interfaces. This code allows their methods to be called remotely.

12 dbc@csit.fsu.edu12 java.rmi.RemoteException  Requiring all remote methods be declared to throw RemoteException was a philosophical choice by the designers of RMI.  RMI makes remote invocations look syntactically like local invocation. In practice, though, it cannot defend from problems unique to distributed computing— unexpected failure of the network or remote machine.  Forcing the programmer to handle remote exceptions helps to encourage thinking about how these partial failures should be dealt with.  See the influential essay: “A Note on Distributed Computing” by Waldo et al, republished in The Jini Specification: http://java.sun.com/docs/books/jini

13 dbc@csit.fsu.edu13 The Remote Object  A remote object is an instance of a class that implements a remote interface.  Most often this class also extends the library class java.rmi.server.UnicastRemoteObject. This class includes a constructor that exports the object to the RMI system when it is created, thus making the object visible to the outside world.  Usually you will not have to deal with this class explicitly—your remote object classes just have to extend it.  One fairly common convention is to name the class of the remote object after the name of the remote interface it implements, but append “Impl” to the end.

14 dbc@csit.fsu.edu14 A Remote Object Implementation Class  The file MessageWriterImpl.java contains the class declaration: import java.rmi.* ; import java.rmi.server.* ; public class MessageWriterImpl extends UnicastRemoteObject implements MessageWriter { public MessageWriterImpl() throws RemoteException { } public void writeMessage(String s) throws RemoteException { System.out.println(s) ; }

15 dbc@csit.fsu.edu15 Remarks  The constructor MessageWriterImpl() has an empty body. But recall that if there is no explicit constructor invocation in the body of a subclass constructor, it implicitly invokes super().  Hence the vital constructor of UnicastRemoteObject is called.  This constructor is declared to throw RemoteException. The MessageWriterImpl() constructor must be declared to throw this exception in turn, otherwise there will be a compiler error message.  Of course the class must also define all the methods of the remote interface MessageWriter, which it implements.

16 dbc@csit.fsu.edu16 Compiling the Remote Object Class  To compile classes that implement Remote, you must use the rmic compiler. The reasons will be discussed later. For example: sirah$ rmic MessageWriterImpl

17 dbc@csit.fsu.edu17 Client and Server Programs  We have completed the Java files for the remote object class itself, but we still need the actual client and server programs that use this class.  In general there are some pieces of administrivia one has to deal with—publishing class files and installing security managers.  To minimize distractions, we initially make the simplifying assumption that both client and server have copies of all class files for MessageWriter (e.g., they may share access through shared NFS directories).  Then we also don’t need a security manager, because all code is “local”, and therefore trusted.

18 dbc@csit.fsu.edu18 A Server Program  We assume the file HelloServer.java contains the class declaration: import java.rmi.* ; public class HelloServer { public static void main(String [] args) throws Exception { MessageWriter server = new MessageWriterImpl() ; Naming.rebind(“messageservice”, server) ; }

19 dbc@csit.fsu.edu19 Remarks  To avoid cluttering this illustrative code with try-catch statements, we simply have the main() method throw all exceptions (not good practice in general).  This program does two things: –It creates a remote object with local name server. –It publishes a remote reference to that object with external name “MessageWriter”.  The call to Naming.rebind() places a reference to server in an RMI registry running on the local host (i.e., the host where the HelloServer program is run).  Client programs can obtain a reference to the remote object by looking it up in this registry.

20 dbc@csit.fsu.edu20 A Client Program  We assume the file HelloClient.java contains the class declaration: import java.rmi.* ; public class HelloClient { public static void main(String [] args) throws Exception { MessageWriter server = (MessageWriter) Naming.lookup( “rmi://sirah.csit.fsu.edu/messageservice”) ; server.writeMessage(“Hello, other world”) ; }

21 dbc@csit.fsu.edu21 Remarks  Again the program does two things: –It looks up a reference to a remote object with external name “MessageWriter”, and stores the returned reference with local name server. –Finally (!), it invokes the remote method, writeMessage(), on server.  The call to Naming.lookup() searches in a remote RMI registry. Its argument is a URL, with protocol tag “rmi”.  This example assumes the remote object lives on the host “sirah”, and has been registered in the default RMI registry (which happens to listen on port 1099) on that machine.

22 dbc@csit.fsu.edu22 Compiling and Running the Example  Compile HelloServer and HelloClient on their respective hosts, e.g.: sirah$ javac HelloServer merlot$ javac HelloClient  Either ensure client and server share the current directory, or copy all files with names of the form MessageWriter *.class to the client’s current directory.  Then...

23 dbc@csit.fsu.edu23 Running HelloClient/HelloServer

24 dbc@csit.fsu.edu24 Running HelloClient/HelloServer

25 dbc@csit.fsu.edu25 Running HelloClient/HelloServer

26 dbc@csit.fsu.edu26 Running HelloClient/HelloServer

27 dbc@csit.fsu.edu27 Running HelloClient/HelloServer

28 dbc@csit.fsu.edu28 Remark on Using the RMI Registry  In this example we ran the RMI registry on its default port.  In general this is probably a bad idea, especially if the server is used by many people, because there is no mechanism to prevent interference.  It is better to start a registry a non-default port number of your own choice, e.g.: sirah$ rmiregistry 4956 &  The Naming calls become, e.g.: Naming.rebind(“rmi://sirah.csit.fsu.edu:4956/messageservice”, server) ; Naming.lookup(“rmi://sirah.csit.fsu.edu:4956/messageservice”) ;

29 dbc@csit.fsu.edu29 The Mechanics of Remote Method Invocation

30 dbc@csit.fsu.edu30 Is RMI a Language Extension?  Invocation of a method on a remote object reproduces the “look and feel” of local invocation amazingly well.  Yet the internal mechanics of remote invocation are much more complex than local invocation: –Arguments—which may be objects of arbitrary complexity—are somehow collected together into messages suitable for shipping across the Internet. –Results (or exceptions) are similarly shipped back.  Perhaps surprisingly, RMI involves essentially no fundamental modification to the Java language, compiler, or virtual machine.  The illusion of remote invocation is achieved by clever libraries, plus one relatively simple “post-processor” tool (rmic).

31 dbc@csit.fsu.edu31 Exchanging Remote References  A good feature of RMI is that references to other remote objects can be passed as arguments to, and returned as results from, remote methods.  Starting with one remote object reference (presumably obtained from an RMI registry) a client can, for example, obtain references to additional remote objects—returned by methods on the first one.

32 dbc@csit.fsu.edu32 Example: a Printer Directory  Perhaps more relevant on LAN than the Internet, but it illustrates the idea: public interface Printer extends Remote { void print(String document) throws RemoteException ; } public interface PrinterHub extends Remote { Printer getPrinter(int dpi, boolean isColor) throws RemoteException ; }  A client might initially obtain a PrinterHub reference from the RMI registry. The remote object contains some table of printers on the network.  An individual Printer interface is returned to the client, according to specifications given in getPrinter().

33 dbc@csit.fsu.edu33 Remote References have Interface Type  This is a powerful feature, but there is one interesting restriction: –If a particular argument or result of a remote method itself implements Remote, the type appearing in the method declaration must be a remote interface. The declared type cannot be a remote implementation class.  We have also seen earlier that the remote object reference returned by Naming.lookup() can be cast to the expected remote interface type. –However, this reference cannot be cast it to the implementation class of the remote object! A ClassCastException will occur if you try.

34 dbc@csit.fsu.edu34 Stubs  What this tells us is that, however they are obtained— and however they look—remote references are not, in reality, Java references to remote objects. They are Java references to local objects that happen to implement the same remote interfaces as the remote objects concerned.  The local Java object referenced is actually an instance of a stub class.

35 dbc@csit.fsu.edu35 Some Important Parts of RMI  Stubs. –Each remote object class has an associated stub class, which implements the same remote interfaces. An instance of the stub class is needed on each client. Client-side remote invocations are “actually” local invocations on the stub class.  Serialization. –Arguments and results have to be “marshaled”—converted to a representation that can be sent over the Net. In general this is a highly non-trivial transformation for Java objects. Serialization is also used for distributing stubs.  The Server-side “Run-time System”. –This is responsible for listening for invocation requests on suitable IP ports, and dispatching them to the proper, locally resident remote object.

36 dbc@csit.fsu.edu36 Architecture Client Code Stub RMI “Run-time” System Remote Object Call stub method locally Return value or throw exception Call remote object method locally Return value or throw exception Send marshaled arguments Send marshaled result or exception Internet ClientServer

37 dbc@csit.fsu.edu37 The Role of rmic  The only “compiler” technology peculiar to RMI is the rmic stub generator.  The input to rmic is a remote implementation class, compiled in the normal way with javac (for example).  The stub generator outputs a new class that implements the same remote interfaces as the input class.  The methods of the new class contain code to send arguments to, and receive results from, a remote object, whose Internet address is stored in the stub instance.

38 dbc@csit.fsu.edu38 Example Operation of rmic  An earlier example of a remote implementation class: public class MessageWriterImpl extends UnicastRemoteObject implements MessageWriter {... public void writeMessage(String s) throws RemoteException {... }  We issue the command: rmic –v1.2 –keep MessageWriterImpl –The flag –v1.2 avoids generation of unnecessary code, needed only for backward compatibility (including “skeleton classes”). –The flag –keep causes the intermediate Java source to be retained.  Output files will be MessageWriterImpl_Stub.java and MessageWriterImpl_Stub.class.

39 dbc@csit.fsu.edu39 The Generated Stub Class public final class MessageWriterImpl_Stub extends java.rmi.server.RemoteStub implements MessageWriter, java.rmi.Remote {... public MessageWriterImpl_Stub(java.rmi.server.RemoteRef ref) { super(ref); } public void writeMessage(java.lang.String $param_String_1) throws java.rmi.RemoteException { try { ref.invoke(this, $method_writeMessage_0, new java.lang.Object[] {$param_String_1}, 4572190098528430103L); }... }

40 dbc@csit.fsu.edu40 Remarks on the Stub Class  The stub class includes an inherited field ref, of type RemoteRef.  Essentially the stub class is just a wrapper for this remote reference.  Remote methods are dispatched through the invoke() method on ref.  This is passed an array of Objects holding the original arguments (in general it also returns an Object).  It is also passed arguments to identify the particular method to be invoked on the server.  Essentially the stub wrapper is providing compile-time type safety. The actual work is done in library classes that don’t know the compile-time type in advance.

41 dbc@csit.fsu.edu41 Marshalling of Arguments  Objects passed as arguments to invoke() must be marshaled for transmission over the network.  The representation of a Java object inside the Java Virtual Machine is complex: –An object includes references to all its fields, which may themselves be objects. These may in turn reference other objects. –An object will reference its class object, which contains runtime information about the object’s type.  This internal representation is also not standardized— different vendors implementation of the JVM will certainly use different representations.  If objects are to be exchanged between JVMs, we need a standardized way to encode all the information.

42 dbc@csit.fsu.edu42 Object Serialization  Java has a general framework for converting objects (and groups of objects) to an external representation that can later be read back into an arbitrary JVM.  This framework is called Object Serialization.  Object serialization is very important to RMI, but it has other applications as well.  For example, a running program can use object serialization to dump the current state of a particular object to a file. Much later, another program can read the file and reincarnate an exact replica of the original object. This is a mechanism for object persistence.

43 dbc@csit.fsu.edu43 I/O Streams  The technology for serializing and deserializing objects is found in a pair of the many I/O stream classes of Java.  In general an output stream (for example) can be associated with various targets: –a file, an Internet socket connection, an internal Java array of bytes to which one is writing externally formatted data, etc.  The abstract superclass OutputStream provides low- level write methods like: public void write(byte [] buffer) throws IOException {...} Subclasses may override the implementation for a particular output target.  Subclasses may also add extra methods that take more general data, convert them to a byte array, then invoke write() to do the final output.

44 dbc@csit.fsu.edu44 Object Streams  ObjectOutputStream is a subclass that adds methods including: public void writeInt(int val) throws IOException {...} public void writeFloat(float val) throws IOException {...} etc, and most interestingly: public void writeObject(Object obj) throws IOException,... {...}  Similarly ObjectInputStream extends InputStream and adds: public int readInt() throws IOException {...} etc, and: public Object readObject() throws IOException,... {...}

45 dbc@csit.fsu.edu45 Using Object Streams  We can use the writeObject() method of an ObjectOutputStream to write an object to a file, an Internet socket connection, etc.  Later we use the readObject() method of an ObjectInputStream to read an object from the same file, the other end of the socket connection, etc.  When deserialization occurs, a new object is created in the second JVM. As far as possible this is a perfect replica of the the original object.

46 dbc@csit.fsu.edu46 Serialization Preserves Object Graphs  Consider this binary tree node class: class Node implements Serializable { Node() {} Node(Node left, Node right) { this.left = left ; this.right = right ; } private Node left, right ; }  We create a small tree, d, by: Node a = new Node(), b = new Node() ; // Leaves Node c = new Node(a, b) ; Node d = new Node(c, null) ;

47 dbc@csit.fsu.edu47 Serializing and Deserializing a Tree  Write out the root of the tree: out.writeObject(d) ; a c d b a’ c’ e b’  Read a node later by: Node e = (Node) in.readObject() ;  The whole of the original tree is reproduced. Copies a’, b’, c’ of the original sub-nodes are recreated along with e. The pattern of references is preserved.

48 dbc@csit.fsu.edu48 Referential Integrity is Preserved a c d b a’ c’ e b’  This behavior is not limited to trees.  In this example both b and c reference a single object a.  Again the pattern of links is preserved. When the root object is reconstructed from its serialized form, a single a’, referenced twice, is also created.  Generally referential integrity is preserved amongst all objects written to a single ObjectOutputStream.

49 dbc@csit.fsu.edu49 The Serializable Interface  Serializable is another marker interface. An object’s class must implement Serializable if it is to be passed to writeObject(). If it doesn’t, a NotSerializableException will be thrown.  Implementing Serializable doesn’t appear to affect the way the Java compiler and JVM treat the class in general—it seems to be simply a safety feature in ObjectOutputStream.

50 dbc@csit.fsu.edu50 Argument Passing in RMI  In general any object-valued argument or result of a remote method must either implement Remote or Serializable.  If the argument or result implements Remote, it is effectively passed by (remote) reference.  If it implements Serializable, it is passed by serialization and copying. Referential integrity is preserved within the limits of the arguments of a single invocation, as described above.

51 dbc@csit.fsu.edu51 Passing by Remote Reference  The serialization stream used by RemoteRef.invoke() is actually a subclass of ObjectOutputStream, which has been customized to make certain substitutions in the output stream.  In particular this stream recognizes the class of a remote object passed to it, and if necessary replaces it with a RemoteStub object in the output stream. –It gets the stub from an implementation class using the RemoteObject.toStub().  So even if a remote object implementation is passed as an argument (by the host that holds the object), what will be received is a stub.  Stub classes themselves implement Serializable. So once references have been converted to stubs, they just get passed from host to host by value.

52 dbc@csit.fsu.edu52 Argument Passing Examples  To end this section we work through two examples that are interesting in their own right, and also demonstrate the two fundamental ways of passing arguments in RMI.

53 dbc@csit.fsu.edu53 Example: a File Reading Service  The earlier “Hello” example involved a very trivial remote I/O service, whereby a client could write a string to the console of a server.  Here we generalize to a more useful service that reads a file on the server and returns its contents to a client.  In particular it will illustrate how RMI implicitly uses serialization for a java.util class, returned as a remote method result.

54 dbc@csit.fsu.edu54 The Remote Interface  The file FileSource.java: import java.util.* ; import java.io.* ; import java.rmi.* ; public interface FileSource extends Remote { public Vector readFile(String File) throws RemoteException, IOException ; }

55 dbc@csit.fsu.edu55 The Remote Object Implementation  The definition of FileSourceImpl: public class FileSourceImpl extends UnicastRemoteObject implements FileSource { public FileSourceImpl() throws RemoteException {} public Vector readFile(String file) throws RemoteException, IOException { Vector lines = new Vector() ; BufferReader in = new BufferReader(new FileReader(file)) ; while(true) { String line = in.readLine() ; if(line == null) break ; lines.addElement(line) ; } return lines ; }

56 dbc@csit.fsu.edu56 The Server Program  The definition of the class FileServer: public class FileServer { public static void main(String [] args) throws Exception { FileSource server = new FileSourceImpl() ; Naming.rebind( “rmi://sirah.csit.fsu.edu:4965/fileservice”, server) ; }  (We chose the registry port as a random number between 1024 and 64K.)

57 dbc@csit.fsu.edu57 The Client Program  The definition of the class FileClient: public class FileClient { public static void main(String [] args) throws Exception { FileSource server = (FileSource) Naming.lookup( “rmi://sirah.csit.fsu.edu:4965/fileservice”) ; Vector lines = server.readFile(“students”) ; // The remote invocation for(int i = 0 ; i < lines.size() ; i++) System.out.println((String) lines.get()) ; }

58 dbc@csit.fsu.edu58 Compiling  On the server: rmic FileSourceImpl javac FileServer –(Note rmic will automatically invoke javac if FileSourceImpl.java has not previous been compiled. javac, in turn, will notice a dependency on FileSource.java, and compile that file if necessary.)  Copy the files FileSource.class and FileSourceImpl_Stub.class from server to client. –Later we will see how to use dynamic class loading to avoid copying the stub class to the client manually.  On the client: javac FileClient

59 dbc@csit.fsu.edu59 Running FileClient/FileServer

60 dbc@csit.fsu.edu60 Running FileClient/FileServer

61 dbc@csit.fsu.edu61 Remarks  The file students lives on the server. It is not directly accessible to the client.  The FileSource object reads the file, and saves its lines in a Vector.  The Vector is returned as a result of the remote method readFile(). Vector, and the String class of the included elements, both implement Serializable. The return value is transparently serialized in the server and deserialized on the client.  We could also have used an array of String objects—an array type is serializable if its component type is.

62 dbc@csit.fsu.edu62 Example: The RMI Registry  The RMI registry is a process that normally runs on the server.  At first sight the registry seems to have a privileged role in RMI. Actually it is “just another” remote object.

63 dbc@csit.fsu.edu63 The RMI Registry Client Code Remote Object ClientServer Registry Store Reference Request Reference

64 dbc@csit.fsu.edu64 The Registry Remote Interface  Instead of interacting with the registry indirectly through the Naming class, it is possible to obtain a direct remote reference to the registry object.  Its remote interface is defined in the package java.rmi.registry. The interface includes: public interface Registry extends Remote { public Remote lookup(String name) throws... ; public bind(String name, Remote obj) throws... ; public rebind(String name, Remote obj) throws... ;... }

65 dbc@csit.fsu.edu65 The LocateRegistry Class  This class constructs a stub for an existing Registry object. (It can also create a new registry implementation object, running in the current JVM.)  The interface includes: public final class LocateRegistry { public static Registry getRegistry(String host, int port) throws... {...} public static Registry createRegistry(int port) throws... {...}... }

66 dbc@csit.fsu.edu66 Using the Registry Interface Directly  An alternative definition of the class FileServer: public class FileServer { public static void main(String [] args) throws Exception { FileSource server = new FileSourceImpl() ; Registry reg = LocateRegistry.getRegistry(“sirah.csit.fsu.edu”, 4965) ; reg.rebind(“fileservice”, server) ; //A remote method invocation }  We are particularly interested in this example because it involves passing a remote object implementation, server, as an argument to a remote method, rebind().

67 dbc@csit.fsu.edu67 Passing a Remote Object Argument  The server argument of rebind() is a true Java reference to a remote object implementation.  When the invoke() call is made (on the remote reference embedded in reg) it uses a customized object-stream class. As mentioned earlier, this tests for instances of remote objects among the arguments, and treats them specially.  In the output stream, it will replace the implementation object with a stub obtained by applying the RemoteObject.toStub() method to server.  Thus the registry receives a stub.  This is a general mechanism that applies whenever a locally resident remote object is passed as an argument to a remote method.

68 dbc@csit.fsu.edu68 Summary  In principle most of the features that have been discussed in this section are hidden inside the implementation of RMI. In an ideal world you would not have to know about them.  In practice, to successfully deploy an RMI-based application, you will probably need to at least be aware of some fundamental issues.  You need to be aware of the existence of stub objects, and the basic working of object serialization.  You should be aware that references to remote objects are normally produced by creating a stub object on the server, then passing this stub to registry and clients in serialized form.

69 dbc@csit.fsu.edu69 Dynamic Class Loading

70 dbc@csit.fsu.edu70 Byte Code Instructions for Stubs?  As we have seen: before any client can use an RMI remote object, it must receive a serialized stub object.  The serialized stub contains a remote reference. Data fields of the reference may include information like: –The name of the host where the remote object lives, –Some port number on that host, where the RMI run-time system is listening for invocation requests. –Any other information needed to uniquely identify the remote object within its host.  One thing serialized objects do not contain is the actual JVM instructions (the byte codes), that implement methods on the local object (e.g. the code for the wrapper methods that dispatch invoke()).

71 dbc@csit.fsu.edu71 Serialization Only Saves the Data  The Java serialization process stores all data fields from the original object.  It does not store any representation of the code associated with the methods in the object’s class.  When an object is deserialized (e.g. on some client), the client JVM must have some way of loading a class file that does contain this information.  If it cannot find a suitable class file, the deserialization process will fail. You will see a java.rmi.UnmarshalException thrown, with a nested java.lang.ClassNotFoundException.  When you are doing development using RMI, you will probably see this exception a lot!

72 dbc@csit.fsu.edu72 Copying Stub Class Files  In RMI, there are at least two ways to get the class files to the client.  The straightforward approach is to manually copy class files for all stub classes to the client: either put them in the current directory on the client, or in some directory on the client’s CLASSPATH.  This approach is reliable, easy to understand, and perhaps the best approach for initial experiments with RMI.  Eventually you may find it is too limiting. One of the benefits of the OO approach is supposed to be that the user code (here the client) doesn’t need need to know the exact implementation class in advance—only the interface. But stubs are associated with the implementation class.

73 dbc@csit.fsu.edu73 Dynamic Class Loading  A more general approach is to publish implementation class files that may be needed by clients on a Web Server.  Although the serialized representation of an object does not contain the actual information from the class file, the representation can be annotated with a URL. This specifies a Web Server directory from which the class file can be downloaded.  When the object is deserialized, the client Java Virtual Machine transparently downloads the byte codes from the Web Server specified in the annotation. On the client side, this process happens automatically.

74 dbc@csit.fsu.edu74 Dynamic Class Loading Client JVM Remote Object (MyImpl instance) Client Server Web Server Request stub class file download/ html/ MyImpl_Stub.class Server (myWWW) Serialized stub, annotated with code-base: http://myWWW/download/

75 dbc@csit.fsu.edu75 Remarks  In simple examples, the serialized stub will probably be obtained through an RMI registry running on the server (the same server where the remote object is running).  The two servers—the server where the remote object is running, and the Web Server publishing the class files— may, of course, be physically the same machine.

76 dbc@csit.fsu.edu76 The java.rmi.server.codebase Property  We need a way to cause serialized object representations to be annotated with suitably chosen URLs.  In principle this is straightforward. We set a property called java.rmi.server.codebase in the JVM where the stub (or serialized object in general) originates.  The value of this property is a code-base URL.  The RMI serialization classes read the code-base property, and embed the URL they find there in the serialized representation of arguments or results. –Unless this JVM itself downloaded the class file for the object from a Web server, in which case they embed the URL from which the class was originally loaded.

77 dbc@csit.fsu.edu77 Properties  java.rmi.server.codebase is one of the JVM default system properties (see documentation for class System).  Values of properties in general, and java.rmi.server.codebase in particular, can be set on the java command-line, or through “system calls”.  On the command-line, you can set the value of a property with name prop to value val by using the –D option, as in: java –Dprop=val MyClass  Within a running program, you can call the static method setProperty(), as in: System.setProperty(prop, val) ; Here both prop and val must be String-valued expressions. (There is a related getProperty() method.)

78 dbc@csit.fsu.edu78 Setting the Code-base  For example, our original HelloServer example might be run as follows: java –Djava.rmi.server.codebase=http://sirah.csit.fsu.edu/users/dbc/ HelloServer  This sets the java.rmi.server.codebase property to: http://sirah.csit.fsu.edu/users/dbc/ This URL gets embedded in serialization streams created by the HelloServer program.  If an object is subsequently recreated by deserialization in a different JVM (and that JVM cannot find a local copy of the associated class file) it will automatically request it from the Web server sirah, looking in the document directory users/dbc/.

79 dbc@csit.fsu.edu79 Recap: Marshalling and the Code- base  When an object is marshaled for an RMI invocation, the serialized object may be annotated with a URL: –If the class of the object was originally loaded from the local CLASSPATH, the embedded URL will be the value of the local java.rmi.server.codebase property. –If the class of the object was originally loaded dynamically from some Web Server directory, the embedded URL will be the URL for that directory.

80 dbc@csit.fsu.edu80 Recap: Unmarshalling and Loading  When an object is unmarshaled after an RMI invocation, if the class of the object is not already loaded into the JVM, then: –If the class can be found on the local CLASSPATH, it is loaded from there. –Otherwise, the class is loaded dynamically from a Web Server directory specified in the URL embedded in the serialized object.  If the loaded class uses further classes, not already loaded into the JVM: –If the used class can be found on the local CLASSPATH, it is loaded from there. –Otherwise, the class is loaded dynamically from the same URL as the first class. This rule applies recursively.

81 dbc@csit.fsu.edu81 Security Managers  There is one more thing we need to worry about.  Before a Java application is allowed to download code dynamically, a suitable security manager must be set. This means a security policy must also be defined.  In general this is a complicated topic. We won’t go into any detail: just give a recipe you can follow.

82 dbc@csit.fsu.edu82 Setting the Security Manager  In an RMI application, if no security manager is set, stubs and classes can only be loaded from the local CLASSPATH.  To enable dynamic loading, issue the command: System.setSecurityManager(new RMISecurityManager()) ; at the start of the program.  You should do this in any application that may have to download code—in the simple examples considered so far this means RMI clients that need to download stubs.  This isn’t the end of the story. You also have to define a new property: the java.security.policy property. –In simple cases this property is needed for clients, whereas java.rmi.server.codebase is needed for servers.

83 dbc@csit.fsu.edu83 Defining a Security Policy  The simplest security policy you can define is a plain text file with contents: grant { permission java.security.AllPermission “”, “” ; } ;  This policy allows downloaded code to do essentially anything the current user has privileges to do: –Read, write and delete arbitrary files; open, read and write to arbitrary Internet sockets; execute arbitrary UNIX/Windows commands on the local machine, etc.  It is a dangerous policy if there is any chance you may download code from untrustworthy sources (e.g. the Web).  For now you can use this policy, but please avoid dynamically loading code you cannot trust!

84 dbc@csit.fsu.edu84 The java.security.policy Property  If the text file containing our security policy is called (for example) policy.all, the original HelloClient example might now be run as follows: java –Djava.security.policy=policy.all HelloClient  Alternatively this property can be set inside the program using System.setProperty().

85 dbc@csit.fsu.edu85 Using Dynamic Loading  In principle, modifying your RMI application to allow dynamic loading of stub classes is now straightforward: –Install the stub classes in a Web Server document directory. –Set the java.rmi.server.codebase property for the server application, to reference that Web Server directory. –Create a security policy file on the client. –Set the java.security.policy property for the client application. –Set a security manager in the client.  This also works for any classes (not just stubs) whose serialized form may be communicated via remote method calls. You just need to reinterpret “server” and “client” application according to the direction the serialized object moves—as “source” and “destination” application.  In practice...

86 dbc@csit.fsu.edu86 Anything that Can Go Wrong Will!  Unfortunately, there are many opportunities for trivial mistakes.  Nearly all mistakes, or combinations of mistakes, seem to produce the same error report—a java.rmi.UnmarshalException, with a nested java.lang.ClassNotFoundException.  This can get pretty frustrating. Suppose originally you make two mistakes. By trial and error you may successfully correct one of them. But you never know whether you made progress, because correcting one mistake doesn’t change the error message!

87 dbc@csit.fsu.edu87 Tips for Dynamic Class Loading  First and foremost: make sure your application works without dynamic class loading. Try copying the stub files manually, first. –Be aware of firewalls.  Consider using internal registries (see the following slides).  Consider setting properties inside the Java code (or perhaps inside scripts that run the java command) and be very careful about typing errors! –Don’t forget the “/” at the end of the code-base URL.  Make sure your dynamically loadable class files really are visible on the Web. –Typically the files need to be world readable.

88 dbc@csit.fsu.edu88 Problems with the Registry  The registry is one source of problems.  If you use the rmiregistry command in conjunction with dynamic stub loading, you must be very careful to ensure that the registry program CAN NOT find the stub class files on its own CLASSPATH (or in the directory where the rmiregistry command is run).  If the registry does find the class files on its own CLASSPATH, it will load them from there, and ignore the code-base annotation it receives from the original server!  Later when the registry passes stubs on to the client, they are no longer annotated with the original code- base, and the client cannot find the class files!

89 dbc@csit.fsu.edu89 Empty CLASSPATH for the Registry  So it is usually recommended you ensure the CLASSPATH environment variable is empty when you run the rmiregistry command, and make sure the registry is run in a directory that contains no class files.  However this still leaves some pitfalls.  When the registry dynamically downloads the class file MessageWriter_Stub.class, it will also look for MessageWriter.class in the same place, because recreating a stub instance depends on the remote interface.  So you will have to publish MessageWriter.class on the Web Server as well, if only for the benefit of the registry. –“True” clients probably already have this interface definition available on their local CLASSPATH.

90 dbc@csit.fsu.edu90 Using An “Internal” Registry  An alternative approach is to use an “internal” registry object, created inside the server program using the createRegistry() method, e.g.: import java.rmi.* ; import java.rmi.registry.* ; public class HelloServer { public static void main(String [] args) throws Exception { MessageWriter server = new MessageWriterImpl() ; Registry reg = LocateRegistry.createRegistry(4965) ; reg.bind(“messageservice”, server) ; }  Now the registry simply shares the code-base property of the server, and correctly annotates stubs sent to the client, even though their class came from the local CLASSPATH.

91 dbc@csit.fsu.edu91 Collecting Things Together  Finally we will go through the “Hello” example again, this time illustrating changes to support dynamic loading of the stub class.  There is no change to the remote MessageWriter classes themselves.  However we will change the client and server applications, and the deployment procedure.

92 dbc@csit.fsu.edu92 The Server Program  The file HelloServer.java contains the declarations: import java.rmi.* ; public class HelloServer { public static void main(String [] args) throws Exception { final int regPort = Integer.parseInt(args [0]) ; System.setProperty(“java.rmi.server.codebase”, “http://sirah.csit.fsu.edu/users/dbc/”) ; MessageWriter server = new MessageWriterImpl() ; Registry reg = LocateRegistry.createRegistry(regPort) ; reg.bind(“messageservice”, server) ; }

93 dbc@csit.fsu.edu93 Remarks  The most crucial change is that the server now sets the java.rmi.server.codebase property.  In this simplified example the Web Server URL is “hard- wired” into the code.  In “production quality” code, a better strategy may be to first check (e.g. using getProperty()) whether a property is defined on the command-line, and, if not, read it from some “properties” file.  Here the port number on which the registry listens is taken from the first command-line argument. A registry is started internally.

94 dbc@csit.fsu.edu94 A Client Program  The file HelloClient.java now contains the declarations: import java.rmi.* ; public class HelloClient { public static void main(String [] args) throws Exception { System.setProperty(“java.security.policy”, “policy.all”) ; System.setSecurityManager(new RMISecurityManager()) ; MessageWriter server = (MessageWriter) Naming.lookup( “rmi://sirah.csit.fsu.edu:4965/messageservice”) ; server.writeMessage(“Hello, other world”) ; }

95 dbc@csit.fsu.edu95 Remarks  A security policy and an RMI security manager is set.  Remarks on server code, concerning “hard-wiring” of property values, apply equally here.  This version looks for a registry on port 4965 on sirah (again hard-wired into the code).

96 dbc@csit.fsu.edu96 Deployment  On the server: rmic MessageWriterImpl javac HelloServer  Copy the stub class file MessageWriterImpl_Stub.class from server to an appropriate Web Server directory. In our example this will be /home/httpd/html/users/dbc/ on sirah.  Make sure the class file is visible: check with a browser!  Copy the interface definition (either MessageWriter.java or MessageWriter.class will do) from server to client.  On the client: javac HelloClient Make sure the file policy.all exists.

97 dbc@csit.fsu.edu97 Running FileClient/FileServer

98 dbc@csit.fsu.edu98 Running FileClient/FileServer

99 dbc@csit.fsu.edu99 Running FileClient/FileServer

100 dbc@csit.fsu.edu100 Running FileClient/FileServer

101 dbc@csit.fsu.edu101 Remarks  It probably seems a lot of work—just to avoid manually copying one stub file from the server to the client.  But this facility for dynamically down-loading class files has more far-reaching implications.  It is applicable not only to stubs, but any object passed through a remote method call, where the class of the actual object received is a specialization (subclass or implementation class) of the type declared in the remote interface.  One can argue this kind of polymorphism is at the heart of object-oriented programming. In this sense dynamic class loading is a prerequisite for doing true object- oriented programming with remote objects.

102 dbc@csit.fsu.edu102 Applets

103 dbc@csit.fsu.edu103 Applets  An applet is Java GUI program, embedded in a Web page (an HTML document).  Typical browsers (Internet Explorer, Netscape) incorporate a Java Virtual Machine.  The class file for the applet is stored in the Web Server’s document directory, alongside normal HTML files and other downloadable data.  An applet class will be dynamically loaded into the browser’s JVM the first time it encounters an HTML or tag requiring that class. Hence the applet is executed on the client.  These tags can appear in any normal HTML document.

104 dbc@csit.fsu.edu104 Applets Today  Java originally became famous as the language that brought Web pages to life through applets.  Since then, other technologies for making Web pages interactive have been widely adopted.  For various commercial and technical reasons applets have decreased in popularity on the Internet. The virtual machines in Web browsers have not kept step with developments in the rest of the Java world.  Applets may still have a future in the Intranet context, where companies can control versions of browser and Java development software deployed. But on the Internet, where many incompatible versions abound, the future of traditional applets is somewhat unclear.

105 dbc@csit.fsu.edu105 Applets in this Course  Caveats notwithstanding, an applet is one natural way to provide a Web front-end to a stand-alone server program, especially if the server is implemented as an RMI object.  We wish to illustrate the principles of applet deployment, but avoid getting bogged down in issues about compatibility across browsers.  Hence we will only discuss Java 2, Swing applets.  These can be displayed in standard browsers, but the browser must have the Java Plug-in installed.  Installing the plug-in is easy for Windows. –To view the examples in this lecture you will need access to a browser with the plug-in installed, or the ability to install the plug-in on a networked PC. –Alternatively, you can use the applet viewer from the JDK.

106 dbc@csit.fsu.edu106 Writing Applets is Easy (if...)  This assumption makes writing applets very easy, if you followed the earlier lecture set on the Java GUI!  In a nutshell, you convert a Swing or AWT-based GUI to an applet GUI by changing the top level JFrame to a JApplet, perhaps moving code from the body of the main() method to the init() method of the JApplet.  There is a fly in the ointment: the applet will only successfully execute in a browser if it respects the security policy imposed by the browser.

107 dbc@csit.fsu.edu107 Applet Security Policies  Usually browsers will not allow an applet to: –read or write a file on the local computer (the client), –find any sensitive information about the local computer, –find any information about the current user! –make an Internet connection to any computer, except the server from which they were download (applets “can only phone home”), or –execute any program on the local computer.  An exception will be thrown in the applet if it tries to do any of these things.  Note that applets specifically are allowed to communicate back to the host from which they were downloaded (otherwise they wouldn’t be at all useful for our purposes).

108 dbc@csit.fsu.edu108 Example: Application to Applet  Driving code for a trivial Swing application that reads entries from a file and displays them in a list: import java.util.* ; import java.io.* ; import java.awt.event.* ; import javax.swing.* ;... declaration of classes FilePanel and FileFrame... public class FileDisplayTest { public static void main(String [] args) { FileDisplay frame = new FileDisplay() ; frame.addWindowListener(new TerminationListener()) ; frame.setVisible(true) ; }... declaration of class TerminationListener...

109 dbc@csit.fsu.edu109 The FileDisplay class  The associated JFrame class is: class FileDisplay extends JFrame{ public FileDisplay() { Vector lines = new Vector() ;... Read all lines from input file to lines... setTitle(“File Entries”) ; setSize(450, 300) ; getContentPanel().add(new FilePanel(lines)) ; }  The suppressed code reads lines from a file using a FileReader stream and saves them in the Vector called lines.

110 dbc@csit.fsu.edu110 The FilePanel class  The definition of FilePanel is just: class FilePanel extends JPanel { public FilePanel(Vector lines) { JList list = new JList(lines) ; JScrollPane scrollPane = new JScrollPane(list) ; add(scrollPane) ; }

111 dbc@csit.fsu.edu111 Conversion to an Applet  In this example there is no code in the main() method that will be needed by the Applet. We simply dispense with FileFrameTest class (and TerminationListener).  The FileDisplay class is changed to extend JApplet instead of JFrame.  This class is made public, and we change the source file name to FileDisplay.java.

112 dbc@csit.fsu.edu112 A First Attempt at an Applet Class  Now the FileDisplay class in FileDisplay.java is: public class FileDisplay extends JApplet { public FileDisplay() { Vector lines = new Vector() ;... Read all lines from input file to lines... getContentPanel().add(new FilePanel(lines)) ; }  Note we have violated a security restriction, by attempting to read a file. We will return to this issue later.

113 dbc@csit.fsu.edu113 Compiling the Applet  Copy the Java source to a suitable Web directory.  I will work in the directory: /home/http/html/users/dbc/examples/ on the host: sirah.csit.fsu.edu  Compile the applet source file in the usual way: javac FileDisplay.java  Remember to make the class files world readable: chmod o+r *.class Forgetting to do this will lead to many problems! –To be sure, check the permissions using ls –l. –Look at the directory using a Web browser (go to URL http:sirah.csit.fsu.edu/users/dbc/examples/). Can you see the class files? Will the browser let you save the class files?

114 dbc@csit.fsu.edu114 Create an HTML File  This will be the document people point their browser at. It can be an arbitrarily complicated HTML document, with surrounding text and images. For now, we use: A File Display <APPLET CODE=“FileDisplay.class” WIDTH=300 HEIGHT=450>  Note the WIDTH and HEIGHT parameters here replace the setsize() call in a Swing application.  We will assume this text is stored in the file: filedisplay.html in the same directory as the applet class files.

115 dbc@csit.fsu.edu115 Convert the HTML for the Plug-in  A Java 2 applet that is to displayed through the Java Plug-in actually needs a more complicated HTML tag. Sun provide a converter to add the extra HTML.  The converter is a Java program. On sirah you can use the script htmlconv installed in /usr/local/jdk1.2.2/bin/. It is a one-line script—if you prefer, check the definition of the script file, and invoke the java program directly.  Otherwise, if you are happy to use the script, do: htmlconv filedisplay.html –backup BAK –This saves the original files in a subdirectory BAK/, then overwrites them. –If you don’t specify the -backup option, the original files get saved in a subdirectory of “./..”. This is a poor default—if you don’t have write-permission in this parent directory, the command will fail.

116 dbc@csit.fsu.edu116 Make Sure the HTML is Visible!  Make sure the file displayfile.html is world readable: chmod o+r displayfile.html  Make sure the directory itself is visible: chmod o+r.

117 dbc@csit.fsu.edu117 Installing the Java Plug-in  To view this applet, you will need a browser with the Java plug-in installed.  If you have a suitable PC where you can install this software, go to: http://javasoft.com/products/plugin/ and follow the link for JRE 1.3 for Microsoft Windows.  Download the executable file into a suitable directory on your PC, and run it.  The plug-in is now installed. –If you are unable to install the plug-in, but have a suitable Java 2 JDK installation, you can view the applet using the appletviewer command instead. Pass the URL on the command line.

118 dbc@csit.fsu.edu118 Attempting to View the Applet  Now go to the URL: http://sirah.csit.fsu.edu/users/dbc/examples/filedisplay.html  If things go properly, you should see a blank panel with a message like: Applet Loading...  On the browser status line you should see a message like: exception: access denied (java.io FilePermission infile read).  Here “infile” is the name of the file the applet attempts to read. Trying to read it is a security violation.  The Applet failed. Exit the browser. –If an applet you are debugging fails, it is nearly always a good idea to exit the browser before trying to view the applet again.

119 dbc@csit.fsu.edu119 Adding a File Reading Service  What we really want is for the Applet to read file entries from a file on the server.  In fact this limited objective could be achieved with an HTTP GET request, but a more general approach is to use RMI.

120 dbc@csit.fsu.edu120 An Updated File Server Program  A new definition for the class FileServer (see the “Mechanics of RMI” section), supporting dynamic class loading: import java.rmi.* ; import java.rmi.registry.* ; public class FileServer { public static void main(String [] args) throws Exception { final int regPort = Integer.parseInt(args [0]) ; System.setProperty(“java.rmi.server.codebase”, “http://sirah.csit.fsu.edu/users/dbc/examples/”) ; FileSource server = new FileSourceImpl() ; Registry reg = LocateRegistry.createRegistry(regPort) ; reg.bind(“fileservice”, server) ; }

121 dbc@csit.fsu.edu121 An Updated Client  Change FileDisplay to read lines from a file called “infile” on the server: public class FileDisplay extends JApplet { public FileDisplay() { Vector lines = new Vector() ; try { FileSource server = (FileSource) Naming.lookup(“rmi://sirah.csit.fsu.edu:4965/fileservice”) ; lines = server.readFile(“infile”) ; // Remote method getContentPane().add(new FilePanel(lines)) ; } catch (Exception e) { }

122 dbc@csit.fsu.edu122 Deploying the Service  Copy the source files FileServer.java, FileSource.java and FileSourceImpl.java to the Web Server directory where the applet lives.  Compile the remote object and the server: rmic FileSourceImpl javac FileServer.java  Remember to make the class files world readable!: chmod o+r *.class  Make sure there is a file called “infile” in this directory!  Run the server: java FileServer 4965  View the applet with the browser while the server program is running.

123 dbc@csit.fsu.edu123 Class Loading in the Example  The applet class itself, FileDisplay, will be loaded dynamically by the applet class loader in the browser.  Classes it uses directly, like FilePanel, and the FileSource remote interface definition, will also be loaded by the applet class loader.  By default, these class files will be downloaded from the same directory as the original HTML.  When Naming.lookup() returns a FileSourceImp_Stub object, this will be loaded by the RMI class loader in the browser JVM.  As usual, the class file will be downloaded from a directory determined by the java.rmi.server.codebase property in the server program.  In the example, both loaders read from the same directory.

124 dbc@csit.fsu.edu124 Running Server Programs in UNIX  In this example, we assumed the server program is running in a window of its own.  In UNIX, you can run a process in the background by adding an ampersand to the command: java FileServer 4965 &  This process can go on running even after you log out.  If you use this mechanism, make sure you know how to kill the process when it is no longer needed, e.g.: sirah$ ps –udbc # Processes of user dbc PID TTY TIME CMD 30399 ? 00:00:00 java 30355 pts/2 00:00:00 bash... sirah$ kill -9 30399 # The process ID

125 dbc@csit.fsu.edu125 What Did this Achieve?  The example—displaying a file from the server—was contrived to be very simple.  But it should be clear that now we have a general mechanism whereby an applet running in a browser can communicate with a program running on the server.  Through remote methods, the applet client can effectively cause arbitrary code to be executed on the server.  This opens many options that are not available to an applet by itself: –The server program can do many things an applet itself cannot do, due to security restrictions. –Instances of the applet, running in browsers belonging to different clients, can share access to data or databases that reside on the server.

126 dbc@csit.fsu.edu126 Some Additional Features of Applets  Applets are not a primary focus of these lectures, but we briefly review some of their other properties.  In the FileDisplay example, the GUI was created in the constructor of the applet.  This is slightly unusual for an applet. It is more traditional to do initialization in a method called init()—one of several applet “event- handling” methods: init() start() stop() destroy()  Actually these methods are not invoked in the AWT event- dispatching thread. You should take appropriate care, especially if start() or stop() explicitly modifies the display—see the section “Events Revisited” in the GUI lectures.

127 dbc@csit.fsu.edu127 Life Cycle of an Applet  The system invokes four methods on JApplet: void init() when the applet is first loaded. void start() after init() and whenever the browser reloads the HTML page containing the applet. void stop() whenever the browser leaves the HTML page containing the applet. void destroy() before the browser shuts down.  Note that an applet is apparently never unloaded once it has been loaded (until the browser exits). This can be awkward for debugging (and presumably means the browser JVM eventually fills up with classes).

128 dbc@csit.fsu.edu128 Applet Parameters  The APPLET element in HTML can include parameter definitions, e.g.: <APPLET CODE=“FileDisplay.class” WIDTH=300 HEIGHT=450> Inside the applet, these parameters are read by getParameter(), e.g.: String file = getParameter(“file”) ; You are not allowed to call this method in the applet constructor. This is one reason for doing initialization in init().  Remember to convert the HTML again if you modify the applet element!

129 dbc@csit.fsu.edu129 An Improved Applet  This version will read the port number (and file name) from the applet parameters: public class FileDisplay extends JApplet { FileSource server ; FilePanel panel = new FilePanel() ; public void init() { try { getContentPane().add(panel) ; server = (FileSource) Naming.lookup(“rmi://sirah.csit.fsu.edu:” + getParameter(“port”) + “/fileservice”) ; } catch(Exception e) {... } }... }

130 dbc@csit.fsu.edu130 An Improved Applet ... it also reads the file again whenever the page is refreshed: public class FileDisplay extends JApplet {... public void start() { try { panel.setLines(server.readFile(getParameter(“file”))) ; } catch(Exception e) {... } }  We added a default constructor and setLines() method to FilePanel(). Latter uses setListData() method of JList.

131 dbc@csit.fsu.edu131 stop()  If you are writing a more general applet that allows the file to be updated, overriding the stop() method might be one natural place to save locally cached data back to the server.

132 dbc@csit.fsu.edu132 Other Applications of RMI

133 dbc@csit.fsu.edu133 Beyond Simple Client/Server  The preceding example illustrated how to use RMI to implement a back-end server program for a client, which might be an applet running in a Web browser.  RMI can do this easily, but it also allows one to do much more general things.

134 dbc@csit.fsu.edu134 Example: Exploiting Dynamic Loading  We emphasized in an earlier section that the dynamic class loading implemented in RMI goes beyond automated delivery of stub classes.  Objects of essentially any class can be returned by a remote method, and the code will be dynamically downloaded. For example, this may include code for complex graphical user interfaces.

135 dbc@csit.fsu.edu135 A Generic Service  One could define a generic service remote interface: public interface GenericService extends Remote { public GUI getGUI() ; } public interface GUI extends Serializable { public void init() ; }  The client simply does: GenericService service = (GenericService) Naming.lookup(url) ; GUI gui = service.getGUI() ; gui.init() ; // Start GUI running locally  All the client knows in advance are the two simple interfaces GenericService and GUI. The code for the actual service and GUI are downloaded dynamically. The GUI might be an arbitrary Swing interface.

136 dbc@csit.fsu.edu136 Example: Jini  Sun’s Jini is a framework for spontaneous discovery of services that exist in a LAN (for example), and for reliable federation of these services.  It makes essential (and creative) use of aspects of RMI like dynamic class loading and call-backs (discussed next).  The Jini lookup services generalize the RMI registry. In Jini an arbitrary proxy object is installed in the lookup services. –The proxy is not restricted to be an RMI stub. It can be any serializable object, typically including remote references to an actual server object.  The code for the proxy is downloaded dynamically by the client, on lookup.

137 dbc@csit.fsu.edu137 Example: Call-backs  A client can itself provide a remote interface, by creating its own remote object.  It can then pass a reference to itself to a server. Now the server can initiate communication by calling remote methods on the client. These are sometimes called call- backs.  In following pages, we outline a collaboration server example. We omit many details.  In general we see that RMI allows one to create complex “webs” of interacting objects.

138 dbc@csit.fsu.edu138 Server Remote Interface  A collaboration server allows users to register it, and to post messages.  It keeps a list of users. When any user posts a message, it distributes it to all the other users. public interface ChatServer extends Remote { public void register(Chatter c, String name) throws RemoteException ; // c is a remote reference to client object. public void postMessage(Message m) throws RemoteException ;... }  The Message class must implement Serializable.

139 dbc@csit.fsu.edu139 Client Remote Interface  The client itself is implemented as a remote object with interface: public interface Chatter extends Remote { public void notify (Message m) throws RemoteException ;... }  The notify() method will be called by the server when a message has been posted.

140 dbc@csit.fsu.edu140 A Group of Interacting Objects Remote Object (Chatter_Impl) Remote Object (ChatServer_Impl) Client Server Remote Object (Chatter_Impl) Client Remote Object (Chatter_Impl) Client postMessage(m) notify(m)

141 dbc@csit.fsu.edu141 Sketch of Server Implementation public class ChatServerImpl extends UnicastRemoteObject implements ChatServer { private Vector chatters = new Vector(); public ChatServerImpl() throws RemoteException {} public void register(Chatter c, String name) { chatters.addElement (c); } public void postMessage (Message m) { for(int i = 0 ; i < chatters.size() ; i++) { Chatter chatter = (Chatter) chatters.get(i) ; chatter.notify(Message m) ; } public static void main(String[ ] args)... set security manager, bind to registry, etc... }

142 dbc@csit.fsu.edu142 Sketch of Client Implementation public class ChatterImpl extends UnicastRemoteObject implements Chatter { public ChatterImpl(ChatApplet gui, String name) throws RemoteException() { this.gui = gui ; server = (ChatServer)Naming.lookup(...); server.register(this, name) ; // Register self with chat server } public void notify(Message m) throws RemoteException { gui.displayMessage(m) ; }... }  We assume this implementation object is created by an applet, which passes itself to the remote object constructor. It should implement displayMessage().

143 dbc@csit.fsu.edu143 Synchronization  Where multiple clients may interact with the same object (this means most useful services), one needs to pay attention to issues of interference.  Remote invocations from different clients may execute concurrently—in different threads—in the server program’s JVM.  It can be a good idea to declare the implementation of remote methods (in the definition of the implementation class) with the synchronized modifier.  This avoids the dangerous situation in which methods are being invoked simultaneously on a remote object by several clients. –Other clients will have to wait until the currently executing method has completed—they will be serviced in turn. –But now you must be wary of possible deadlocks.

144 dbc@csit.fsu.edu144 Enterprise Java Beans  Enterprise Java Beans (EJB) is a specification for a server software framework, emphasizing transactions in distributed environments.  It uses the RMI as the basic communication model, but has higher level—and more specialized—support for automatically handling issues of concurrency and transaction processing, and automatically managing persistence (saving state of objects to databases).

145 dbc@csit.fsu.edu145 Garbage Collection  For Java, an important issue is garbage collection, which automatically deallocates memory for local objects.  Remote objects are also garbage collected as follows: –A remote reference layer on the server keeps a reference count for each locally held remote object implementation. –A remote reference layer on the client notifies the server when its locally held references to the object are no longer in use. –When all references from all clients have gone (i.e. when the reference count is zero), the server object is garbage collected.  But what if a client fails to notify the server? –A client with a remote reference must periodically renew a lease with the run-time system on the server. –If the client holding the reference exits prematurely (without notifying the server) it will also stop renewing its leases. If a lease is not renewed on time, the server assumes the client has died, and the reference count is decremented anyway.


Download ppt "CIS 5930-04 – Spring 2001 Instructors: Geoffrey Fox, Bryan Carpenter Computational Science and."

Similar presentations


Ads by Google