The Rest of the Server

ByteArrayOutputStream temporaryBuffer = new ByteArrayOutputStream ; copyin, temporaryBuffer, _length; _actualDocument = new DataInputStreamnew ByteArrayInputStreamtemporaryBuffer toByteArray ; } We start by declaring _actualDocument to be transient . transient is a Java keyword that tells the serialization mechanism not to serialize the variables value out. We then implement writeObject , which does two things: • Calls out.defaultWriteObject . This invokes the generic serialization mechanism which is the default to write out all nontransient objects. That is, when out.defaultWriteObject is called, everything but _actualDocument has been encoded in the stream. • Copies _actualDocument to the stream, exactly as we did for the socket-based version of the program. Similarly, in readObject , we first call defaultReadObject , which retrieves all the nontransient values, including _length , from the stream. We then read _actualDocument from the stream. Why doesnt InputStream implement the Serializable interface? The answer is that InputStream is an abstract base class whose concrete subclasses often have machine - specific state. For example, File - InputStream explicitly refers to a file on a hard drive and probably has a file descriptor as part of its state. Making objects such as FileInputStream serializable makes very little sense, since you cant guarantee that either the file or the file descriptor will be available or meaningful when the information is deserialized. Similarly, classes such as Frame or Thread , which encapsulate operating-system resources, are not serializable.

4.4 The Rest of the Server

To finish building our server, we need to write launch code. Launch code is code that is application-specific, but not business-domain specific, and handles the details of registering a server with a naming service such as the RMI registry. In our case, this boils down to two pieces of code: a Java program that runs PrinterServer and a batch file that starts the RMI registry and then runs our program. The former is shown in Exam ple 4- 5 . Example 4-5. SimpleServer.java public class SimpleServer implements NetworkConstants { public static void mainString args[] { try { File logfile = new FileC:\\temp\\serverLogfile; OutputStream outputStream = new FileOutputStreamlogfile; Printer printer = new NullPrinteroutputStream; Naming.rebindDEFAULT_PRINTER_NAME, printer; } catch Exception e { e.printStackTrace ; } } } This creates an instance of NullPrinter and then binds it into the registry under the name DEFAULT_PRINTER_NAME . The only surprising detail is this: if everything is successful, our program will exit main . Dont worry; this is normal. The fact that the RMI registry has a reference e.g., a stub for the server keeps the application alive even though weve exited. Ill explain why, and how this works, in Chapt er 16 . Note that we used rebind instead of bind in our launch code. The reason is that bind fails if the name were binding the server to is already in use. rebind , on the other hand, is guaranteed to succeed. If another server i s bound into the registry using the name we want to use, that server will be unbound from the name. In reality, bind is rarely used in launch code, but is often used in code that attempts to repair or update a registry. The format of names that are bound into the registry is fairly simple: they follow the pattern host- name:port-numberhuman-readable-name. host-name and port-number are used to find the registry. The Format of Names in the RMI Registry Servers are bound into the registry using a string. In this case, DEFAULT_PRINTER is simply default printer. More generally, names are formatted according to the following pattern: host-name:port-numberhuman-readable-name Of these three pieces of information, host-name and port-number describe the registry while human-readable-name is server-specific. That is, host-name and port-number are used to find a running instance of the RMI registry which should be listening on port-number of host-name. human-readable-name, on the other hand, is the name used internally, by the registry, to identify the server being registered. Both host-name and port-number have default values. host-name defaults to localhost and port-number defaults to 1099. Thus, the following are all equivalent names: localhost:1099default printer localhostdefault printer :1099default printer default printer The batch file, rmiprinterserver.bat, consists of the following two commands: start rmiregistry start java com.ora.rmibook.chapter4.rmiprinter.applications.SimpleServ er start is a Windows command that executes the rest of the line in a separate process. It is equivalent to putting an ampersand after a command in a Unix shell. Thus, invoking rmiprinterserver.bat from the DOS shell launches the RMI registry in another process, launches SimpleServer in a third process, and then returns to the command prompt to wait for further instructions.

4.5 The Client Application