Wizard API updated!
Tim Boudreau has released a new version of the Swing Wizard library (version 0.997) that fixes the WizardException bug reported in JavaWorld's recent Open Source Java Project profile. The article's examples have been reworked to test out the new, improved WizardException. Thanks, Tim, for this helpful fix!
Open Source Java Projects: The Wizard API

Newsletter sign-up

Sign up for our technology specific newsletters.

Enterprise Java
View all newsletters

Email Address:

Java Tip 56: How to eliminate debugging problems for RMI-based applications

Make your development of RMI-based applications much easier -- use an in-process server to develop and test your client/server code

Developers with experience using RMI for product development largely agree that debugging client/server code presents many difficulties. Stepping into the server from the client or vice versa is not fun for many reasons. Debugging client/server programs using the RMI API is particularly painful, because the execution path jumps back and forth between client and server.

This article presents a simple and elegant solution to the many problems associated with RMI-based product development. The article assumes you have a reasonably good understanding of RMI-based client/server development.

Problems in debugging

Running two debuggers on one machine requires us to have reasonably high-end machines. And switching between two applications is always a nuisance. If we run the debuggers on two different machines, then we need to use two keyboards to step through the debugging process. These petty debugging logistics distract the developer from problem solving.

A common source of trouble is running RMI-based applications on a computer or laptop that is not configured adequately for TCP/IP. This is a big problem for developers who prefer to use their laptops or home PC for product development. Most people use modems to connect to the Internet -- and their TCP/IP is configured to obtain a dynamic address each time they connect to their ISP. So, whenever an RMI application is run, the dial-up dialog box comes up to put the computer on a valid network. To avoid this problem, we can tweak the TCP/IP and COM port settings so that we can run RMI applications without connecting to the ISP -- but then we cannot connect to the Internet while we are developing RMI applications. Reconfiguring the computer (or laptop) frequently is not a feasible solution. As a whole, working from home is not an easy option for those using RMI.

This article describes a simple design technique that allows us to debug the server and client in a single process, without breaking any RMI guidelines or the existing code base. It describes how RMI can be bypassed entirely when you want to debug the client and server code in any debugger in a traditional style (within a single process). The same codebase can be used to run the client and server in separate processes or in a single process, merely by toggling a boolean flag in the client.

Benefits from this design technique

You can implement this technique for your existing codebase in half a day or in a full day, depending on the number of remote interfaces your server supports -- and depending on your typing speed. Once everything is in place, developers can reap the following benefits:

  1. Code can be written and tested on a single machine, in a single process.
  2. There is no need to have a network card and a valid TCP/IP address.
  3. Any JDK 1.1-compatible debugger can be used for debugging both client and server.
  4. Development can be done at home without disturbing the ISP settings. There is no need to get online to obtain a dynamic IP address.
  5. RMI-based products can be demonstrated on a laptop without changing any network or TCP/IP settings.
  6. While the server application is running, a modem can be used to get on the Internet at will.
  7. There is no need to run an RMI registry at the time of debugging.


This design technique requires us to implement the server to support two modes of execution. These modes are:

  1. Remote (standalone) server mode
  2. In-process server mode


Remote (standalone) server mode

In this mode, the server process will be kicked off on a server machine using a simple startup program. This startup program creates a server object and binds it to the registry so that clients can do a lookup through Naming.lookup(). If the server object is creating one or more server-side proxy objects that support remote interfaces, then the server takes the responsibility of registering them with the local RMI registry. Any RMI-based server supports this mode by default.

In-process server mode

In the second mode, the server assumes that it is running inside the client's process. An in-process server is functionally a subset of the remote server. In this mode, the server assumes that the client has direct access to all remote interfaces supported by the server. This is possible because the client and server are sharing the same process space.

In this mode, server objects (server proxies) that implement remote interfaces need not be registered with the local RMI registry. Also, the server avoids invoking the Naming.bind() and Naming.rebind() methods. In addition, it avoids making calls to the API defined in java.net.* classes because the network API methods are not required for setting up communication between client and server. However, the server does not care how the client gets a direct reference to its remote interfaces. The server simply makes sure that all of its services are always available only through remote interfaces. This is precisely the design philosophy of the RMI protocol -- so an in-process server does not break any RMI guidelines.

How does a client communicate with the in-process server?

The client implementation has to be split into two pieces to be able to deploy the design technique described above. The first part of the client code will isolate the RMI-based code from the client implementation. It obtains the remote interfaces on the server using either RMI or through an in-process server. The second part of the client code accepts these remote interfaces to invoke the remote API on the server.

Step-by-step implementation of client/server

Here is a summary of changes required to the client and server code:

  • The server should be modified to support two modes of execution (if required)
  • The client should be split into two parts:
    • The first part acquires a remote server interface
    • The second part accepts the server interface and invokes the client application


The following sections describe these steps in more detail using a sample application.

If your server satisfies the following conditions, then the server can be run as an in-process server without modifying a single line of server code, and you can skip ahead to Step 2. Otherwise, continue with Step 1 below.

1 | 2 | 3 |  Next >
Resources
  • The sample code for this Java Tip is available in zip format http://www.javaworld.com/javatips/javatip56/javatip56.zip
  • For information on Remote Method Invocation, see http://java.sun.com/products/jdk/rmi/index.html