Programming Tutorials Browser Tutorials Articles Struts Tutorials Hibernate Tutorials

  Tutorial: Java Tip 56: How to eliminate debugging problems for RMI-based applications - JavaWorld - July 1998

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

Tutorial Details:

Java Tip 56: How to eliminate debugging problems for RMI-based applications
Java Tip 56: How to eliminate debugging problems for RMI-based applications
By: By Satheesh A. Donthy
Make your development of RMI-based applications much easier -- use an in-process server to develop and test your client/server code
evelopers 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:
Code can be written and tested on a single machine, in a single process.
There is no need to have a network card and a valid TCP/IP address.
Any JDK 1.1-compatible debugger can be used for debugging both client and server.
Development can be done at home without disturbing the ISP settings. There is no need to get online to obtain a dynamic IP address.
RMI-based products can be demonstrated on a laptop without changing any network or TCP/IP settings.
While the server application is running, a modem can be used to get on the Internet at will.
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:
Remote (standalone) server mode
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.
Condition 1: Server does not create any remote objects that implement remote interfaces
Condition 2: Server does not use API defined in java.net.* classes
Step 1: Modifications to the server code
The Server object extends from UnicastRemoteObject and implements ServerInterface . Add a constructor to Server that takes a boolean flag to indicate the mode in which this server has to execute. If the in-process boolean flag is set to "true," then this server simply ignores all activity related to RMI. It will not register any proxies and will ask all its aggregates to follow suit. By default this flag is initialized to "false." The following code shows a simple constructor required on the Server object to support the in-process server mode.
//Non-Default constructor to handle in-process server mode.
public Server(String sWorkingDir, boolean bRunAsInProcessServer)
{
m_sWorkingDir = sWorkingDir;
bRunAsInProcessServer = bRunAsInProcessServer;
}
Step 1-A: Handle server-side proxies
If your server registers one or more remote objects to be used by clients, skip all RMI activity if the in-process flag is set to "true." Insert an if() block around the code that does Naming.bind () , Naming.rebind () , and Naming.unbind () to skip registering and unregistering proxy objects. As shown below, all RMI calls in the server code should be wrapped in a simple if{} block using the m_bRunAsInProcessServer boolean flag.
if(m_bRunAsInProcessServer == false)
{
Naming.rebind(proxyObj, proxyName);
}
Add a method to the Server class to extract direct references to proxy objects that implement remote interfaces. The client will use this method to access proxy objects, and it will cast these object references to the remote references they support. The client always goes through remote interfaces to access services on the server. It will never access any methods that are not part of remote interfaces. The following method allows the client-side code to directly access the server-side remote objects (proxies) if the client needs to access the API supported by those remote objects.
Client code will use this method when it wants to run the server in its own process.
public Object[] getServerSideProxies()
{
return m_oServerSideProxies;
}
Step 2: Modifications to the Client class
The client application has to be split into two classes. The sample code contains two files in the client package. They are:
runClient.java -- This class is responsible for obtaining the remote interfaces on the server and starting a client application.
Client.java -- This class implements all necessary client logic. It accepts the remote interfaces through its constructor and goes ahead to invoke services on the server.
Step 3: Implement the runClient class
Write a few lines of startup code in the runClient class, which decides the method of connection with the server. We can switch between two modes of the server using a boolean flag. Let's call this flag bUseRMI . If the flag is true , then the startup code tries to connect to the server through the Naming.lookup() method to obtain the remote interfaces on the server. When the flag is false , it creates a Server object and casts the server to obtain the remote interfaces.
public static void main(String[] args)
{
if((args == null)||(args.length != 2))
{
System.out.println("Usage: java com.company.product.client.runClient ");
System.out.println("Usage: java com.company


 

Read Tutorial at: Click here to view the tutorial

Rate Tutorial:
Java Tip 56: How to eliminate debugging problems for RMI-based applications - JavaWorld - July 1998

View Tutorial:
Java Tip 56: How to eliminate debugging problems for RMI-based applications - JavaWorld - July 1998

Related Tutorials:

Applet to Applet Communication
Applet to Applet Communication
 
Java Tip 72: Press Escape to close your Swing dialog windows
Java Tip 72: Press Escape to close your Swing dialog windows
 
Java memory management
Java memory management
 
Scripting power saves the day for your Java apps
Scripting power saves the day for your Java apps
 
Accelerate your RMI programming
Accelerate your RMI programming
 
Deploy code servers in Jini systems
Deploy code servers in Jini systems
 
Master J2ME for live data delivery
Master J2ME for live data delivery
 
roots of constants classes
roots of constants classes
 
Profiling the profilers
Profiling the profilers
 
Good, but obsolete
Good, but obsolete
 
Seven Low-Cost Ways to Improve Legacy Code
This article presents seven techniques I\'ve developed and used in my consulting work that are designed to improve legacy code.
 
Inside Class Loaders: Debugging
Inside Class Loaders: Debugging This article will show how to solve class-loading problems and to overcome some debugging limitations of the JDK class loaders.
 
YourKit Java Profiler 2.5.2 Released
YourKit Java Profiler 3.2 Released With help of YourKit Java Profiler, an outstanding tool for Java professionals, you can easily solve wide range of CPU and memory related performance problems in J2EE and J2SE applications.
 
YourKit Java Profiler 3.2 Released
With help of YourKit Java Profiler, an outstanding tool for Java professionals, you can easily solve wide range of CPU and memory related performance problems in J2EE and J2SE applications.
 
Java Resources
There are all Java freebies. Some of these are old, and not under maintenance. Download and use them at your risk. In case of queries, mail subrahmanyam_avb@technologist.com or varalakshmi_a@techie.com.
 
Getting Started With Bluetooth
JSR-82 brings Bluetooth API's to the J2ME environment. Read the tech tip and begin experimenting with Bluetooth today using the Wireless Toolkit 2.2 Beta.
 
Write custom appenders for log4j
The Apache Software Foundation's log4j logging library is one of the better logging systems around. It's both easier to use and more flexible than Java's built-in logging system.
 
Struts, JavaServer Faces, and Java Studio Creator:
The Evolution of Web Application Frameworks Sun Microsystems' Craig McClanahan, the creator of the Apache Struts Framework, co-specification lead for JavaServer Faces 1.0, and prime architect for Sun Java Studio Creator's new release, explains all three.
 
Sun Studio 10 Software Just Released
This world-class development environment is now extended to the AMD64 architecture and delivers reliable, scalable, and high-performance applications for the Solaris 10 Operating System.
 
Using DTrace to Profile and Debug A C++ Program (Technical Article)
In this test case, the DTrace capability in the Solaris 10 OS is used to identify an error common to C++ applications -- the memory leak.
 
Site navigation
 

 

Send your comments, Suggestions or Queries regarding this site at roseindia_net@yahoo.com.

Copyright © 2006. All rights reserved.