ClientNetworkWrapper Network-Aware Wrapper Objects

Both of these objects inherit from a convenience class named NetworkBaseClass , which defines a few constants and has convenience methods for closing sockets and streams: public abstract class NetworkBaseClass { public static final String DEFAULT_SERVER_NAME = localhost; public static final int DEFAULT_SERVER_PORT = 2100; public static final int DEFAULT_SERVER_BACKLOG = 10; public void closeSocketSocket socket { if null=socket { try { socket.close ; } catch IOException exception{ } } } public void closeStreamInputStream stream { omitted similar to close socket } public void closeStreamOutputStream stream { omitted similar to close socket } }

3.3.2.1 ClientNetworkWrapper

ClientNetworkWrapper is the client side object which encapsulates the protocol. The core of this encapsulation is the sendDocumentToPrinter method: private String _serverMachine; private int _serverPort; almost all the set-up and initialization of object code omitted.... public void sendDocumentToPrinterDocumentDescription documentDescription throws ConnectionException, PrinterException { Socket connection = null; try { connection = new Socket_serverMachine, _serverPort; documentDescription.writeToStreamconnection.getOutputStre am ; readStatusFromSocketconnection; } catch IOException e { e.printStackTrace ; throw new ConnectionException ; } finally { closeSocketconnection; } } private void readStatusFromSocketSocket connection throws PrinterException, IOException { InputStream inputStream = connection.getInputStream ; DataInputStream dataInputStream= new DataInputStreaminputStream; BufferedReader reader = new BufferedReadernew InputStreamReaderinputStream; boolean response = dataInputStream.readBoolean ; if response { return; } throw new PrinterExceptioninputStream; } The points to note about this method are: • It is a straightforward procedural wrapper around the protocol; a connection is made, an instance of DocumentDescription is sent, a return value is read from the sockets input stream, and a PrinterException may be thrown based on the return value. Once youve defined the protocol, writing ClientNetworkWrapper is straightforward. • Once again, the information that has already been read is used to help interpret the remainder of the stream. Since the communication is entirely via a stream of bytes, the server cant simply throw an exception and expect it to be propagated to the client application you cant throw an exception through a socket connection. But the server can send a boolean that the client interprets as a signal that there is more information available. The client knows that if there is more information sent, it is a marshalled instance of PrinterException and behaves accordingly. Were cheating a bit on exceptions. In particular, what if there were more than one type of exception that could be thrown? Instead of just passing a boolean back from the server, wed need to pass more metadata. For example, we could pass back a boolean indicating that an exception has been thrown, followed by a string containing the name of the exception class, followed by the actual instance data. The client would receive the boolean and create an instance of the class by getting the class object with Class.forName and then using the reflection API to find the appropriate constructor.

3.3.2.2 ServerNetworkWrapper