A Final Word About Factories

performance by preventing a large number of really costly operations such as spawning a JVM from occurring at the same time. The default value for sun.rmi.rmid.maxstartgroup is 3 ms.

17.6.6.6 sun.rmi.server.activation.debugExec

This is the simplest, and possibly the most useful, of the rmid parameters. Its boolean valued. If its set to true , then the activation system will print out the command line used to create JVMs. This can really help in debugging an activatable system. You get to see exactly what parameters and properties are set in the created JVMs. The default for sun.rmi.server.activation.debugExec is false . In addition to these parameters, has some security -related parameters that we will discuss in Chapt er 19

17.7 A Final Word About Factories

In this chapter, we discussed the idea of a factory. At its most fundamental level, a factory is a server that launches other servers in response to client demands. However, a factory is more than just a remote constructor; its also a way to share resources among clients, and its a very convenient place to insert code that manages the server lifecycle. Theres another interesting point lurking here. Factories simplify client applications by providing client applications with the illusion of persistent servers. Consider the typical account server in our example. From the clients point of view, this server is always up and always available. The client calls the factory, using a method call that looks quite a bit like a naming-system lookup call. In response, the client gets a stub to a server. As long as the client holds on to the stub, the distributed garbage collector will keep the server alive, and the stub will be a valid reference. If the client discards the stub and then makes another request to the factory, the client will get another stub. Its quite possible that in the interim, the account server was shut down, and the new stub the client gets is actually for an entirely different instance of Account but with the same state as the previous instance. However, this fact is completely hidden from the client application. This can be summarized in two points: • Factories enable the automatic launching and shutdown of servers and provide an ideal mechanism for inserting persistence code. As such, they greatly simplify the design and implementation of large sets of similar server objects. • Factories enable clients to be written as if all the associated servers are up all the time. They also greatly simplify the design and implementation of client code. These two points make factories an incredibly important and versatile tool in the fight against application complexity. Part III: Advanced Topics Chapter 18. Using Custom Sockets One of the major themes of this book is that RMI, for all its power and convenience, is really just a layer implemented on top of the standard socket objects shipped with the JDK. In this chapter, I build on this theme by showing how to replace the standard cleartext sockets that RMI uses with other sockets. The fact that RMI allows you to do this, and to do this differently for each type of server, is a very powerful feature. By the end of this chapter, youll understand how to change the sockets that RMI uses and know when doing so is an appropriate design strategy. As Ive mentioned countless times, RMI is built on top of sockets. This means that: • Data sent between clients and servers in both directions is sent using a streams interface. • Connections between clients and servers are created and maintained by using the socket classes defined in the java.net package. • RMI doesnt make any assumptions about the underlying network infrastructure or communication protocol. Understanding these points, and what they imply, is crucial for understanding how RMI works under the covers. However, the strict separation they imply between RMI on the one hand, and the operating system and network transport protocol on the other, also leads quite naturally to the following thought: If I can define a new socket class, and my socket-level communications protocols will work with it, then my RMI applications, which are built on top of sockets and dont make any assumptions about the underlying network, should also be able to run on top of my new sockets. Indeed, this turns out to be the case. RMI, through the definition of custom socket factories, contains a remarkably flexible way of letting you use whatever sockets you feel like using to handle the raw bits that need to get sent over the wire. Why Use a Custom Socket Class? By default, RMI uses the standard socket classes defined in the java.net package to send information over the wire. Servers use instances of ServerSocket to listen for connections, and clients initiate connections using instances of Socket . These sockets send information as plain text, without any encryption or compression, and thus involve a trade-off. On the positive side, they involve the least CPU usage information is not transformed in any way and are the most straightforward to use. The latter is true because compression can get a little tricky. The semantics of flush , especially with GZIPOutputStream , are not entirely compatible with the idea of sending remote method invocations as discrete and self - contained units. On the negative side, they use more bandwidth than needed, and information is very vulnerable while its being sent over the network. This leads to two reasons for using custom sockets: • If youre not on a secured network, and the information being sent across the wire is sensitive, you may want to use encrypting sockets, such as the SSL sockets we discussed in Chapt er 2 . • If youre on a very congested network where bandwidth is an issue, you may want to compress information before sending it over the wire. In both of these cases, an explicit trade is made: single -machine resources, such as CPU time, are used to transform data for better network characteristics. In addition to these trade-offs, there are local e.g., not involving how data is sent over the network reasons to use a custom socket. One common reason is to monitor socket usage and track how much information is sent over the wire. This is an important part of performance profiling and may, in fact, lead to the use of compressing sockets.

18.1 Custom Socket Factories