Ask the Java Experts: Random Walk Computing answers your Java questions

On inner classes and RMI callbacks

Welcome to the first installment of the newest JavaWorld column! Many of you have been asking for a Q&A column for some time, and JavaWorld has heard your call! Welcome to the first installment of Ask the Java Experts, in which Random Walk Computing, New York's leading Java consulting shop, addresses your questions. To submit a question, e-mail experts@randomwalk.com. While we can't answer everybody's submissions, we will try to select a few every month that represent some of your most common questions. Resources for all questions answered in Ask the Java Experts are found at the bottom of the column.

Question 1: Is it possible to declare a class inside another class and to have the inner class access the private variable of the main class?

Random Walk replies:

Certainly! Java 1.1 introduced the concept of inner classes to the Java language. Here's an example of an inner class accessing a private data member of an enclosing class.

public class OuterClass {
private static String hiding = "You can't see me!";
public static class InnerClass {
public static void showMe() {
System.out.println(hiding);
}
}
public static void main (String args[]) {
}
}

When run, this application will print out "You can't see me!"

Question 2: I have a problem with RMI callbacks and hope you will help me out.

My server program successfully invokes a client method using callbacks. However since the client method executes on the server side in this case, how I am supposed to manipulate my front end AWT components from this method. Or is it not possible using RMI callbacks. Because I need my front end AWT components such as Lists to get updated with some values when it receives a callback. Please explain.

Random Walk replies:

We have received quite a few questions regarding RMI this month, from specific issues such as yours to things like "What's the ding-dong deal with this RMI stuff?". So we thought we'd use your question as a jumping off point to address RMI as a whole.

Here's the short answer to your question. It's not correct to say that the client method executes on the server. When using RMI to do callbacks to an application client, the client code does not execute on the application server. Only the RMI proxy or stub class executes on the application's server machine. The proxy invocation then arranges it so that the implementation class for the callback executes on the VM of the application client. Therefore, since the RMI server logic and the front end AWT components both coexist on the same VM, there's no problem in having an RMI "callback" update information kept by AWT components.

Here's a much longer answer, with a sample program that illustrates what's going on:

It can be difficult when learning RMI to predict what is going on where. The trick is to remember that for any RMI interface there will be two classes that execute: the proxy or stub class runs in the VM of the caller and the implementation class runs in the VM of the server.

The other thing to keep straight is that it can get confusing to label one VM the "client" and the other the "server" for a particular application. In RMI terminology, any VM that initiates an RMI invocation is the "client" and a VM that receives and processes an RMI invocation is the "server." I find it easier to think of Java VMs as peers, any of which may act as RMI clients or servers depending on the circumstance. Thus, in RMI there is really no such thing as a "callback" -- a "callback" is really just an RMI invocation in the other direction! In the context of what many people call "client/server applications," its helpful to designate the program that performs the user interface functions as the "front end" or "application client" and the program that provides services to that GUI as the "back end" or "application server."

Using this new nomenclature, the question boils down to: Can RMI be used to allow a back-end VM to send update information to a front-end VM, and have the front-end VM use that information to update the information presented by the GUI? Put this way, the answer is: Yes.

Enough text. Let's look at this in code. Suppose we have a front end whose mission in life is to display a list of stock symbols and stock prices that we're interested in. The job of the back end would then be to notice when a stock's price changes and update the front end with this information. Upon receiving such an update, the front end then would replace the old price for that stock with the new price in the AWT-based user interface.

Since you asked about updating the contents of AWT components using application server-side RMI calls, we'll use an AWT List component in the GUI. It's not the prettiest way to do it, but it does keep the code short. Apologies in advance for the flicker; this isn't a course on AWT programming!

RMI in a nutshell Remote Method Invocation (RMI) is a way for Java programs to call other Java programs that execute in other virtual machines, usually across a network.

The interface to an RMI server is defined by an interface that extends the java.rmi.Remote interface. All methods defined in remote interfaces must be declared to throw the java.rmi.RemoteException.

RMI servers begin by replacing the default SecurityManager with an instance of RMISecurityManager. To advertise available services, an instance of an RMI server object is bound to a name in an RMI registry using the java.rmi.Naming.rebind method. The RMI registry is established by running the rmiregistry daemon.

An RMI server implementation must extend the java.rmi.server.UnicastRemoteObject class and must implement the remote interface for the server. Once this class is defined and compiled, then the rmic program is used to automatically generate stub and skeleton classes.

RMI clients use the java.rmi.Naming.Lookup method to obtain a reference to RMI server objects.

The RMI Interfaces In any well-designed distributed system, it's the remote interfaces that are the most important parts of the system architecture, so lets start with those. The application server provides an interface called StockInfo. StockInfo defines two method signatures: register and unregister. This is how the front end client tells the StockInfo back-end server that the front end client exists. A registered StockInfo client must implement the StockUpdate interface, and must pass a reference to an object that implements the StockUpdate interface as the sole argument to the register method. Once the StockInfo server has a reference to the StockUpdate object, the StockInfo server implementation may use the reference to talk to the front end client at will. It is this object that acts as the "callback" object in this architecture. Here is the StockInfo interface:

package rmistock;import java.rmi.*;
public interface StockInfo extends java.rmi.Remote {
void register(StockUpdate o) throws RemoteException;
void unregister(StockUpdate o) throws RemoteException;
}

The StockUpdate interface looks like this:

package rmistock;import java.rmi.*;
public interface StockUpdate extends java.rmi.Remote {
void update(String symbol, String price) throws RemoteException;
}

Once a client has registered with the StockInfo server, the server will periodically invoke the update method of the StockUpdate object. This means that the application client is itself an RMI server, and must be prepared to service RMI invocations anytime after it makes the StockInfo.register call.

The StockInfo Server Now that the RMI interfaces are defined, there have to be implementation classes for those interfaces. For the StockInfo interface, that class is called StockInfoImpl. This class has three responsibilities:

Related:
1 2 Page 1
Page 1 of 2