Web Services-Not Always the Best Solution, Page 4
The RMI Implementation
The RMI approach assumes that both client and server are Java-based; it's a "pure Java" solution. When RMI first appeared, it triggered the same hype in the Java world as SOAP did a few years ago. Nowadays though, it seems that everyone has dropped RMI in favor of using web services for interconnecting applications.
| Author's Note: If you're not familiar with writing RMI applications, see this short Sun tutorial. I won't go into detail about how RMI works here; instead, I'll concentrate on actually implementing the example over RMI. |
First, you need to define the RMI interface. An RMI interface must extend the Remote interface, so you can't use the AddressBook contract interfaceat least not without altering the interface hierarchy which might be a bit confusing. Instead, here's a new interface for the RMIAddressBook application that offers the same functionality as the AddressBookContract, but is based on the Remote interface:
public interface RMIAddressBook extends Remote
{
public AddressBean findAddress( String name )
throws RemoteException;
}
| Author's Note: Before starting the server you must start the RMI registry. |
public class RMIAddressBookServer implements RMIAddressBook
{
private static final String SERVICE_NAME = "addressbook";
private AddressBook book;
public RMIAddressBookServer()
{
super();
book = new AddressBook();
}
@Override
public AddressBean findAddress(String name)
throws RemoteException
{
return book.findFriend( name );
}
public static void main( String args[] )
{
if( System.getSecurityManager() == null )
{
System.setSecurityManager(
new RMISecurityManager() );
}
try
{
RMIAddressBookServer engine = new RMIAddressBookServer();
RMIAddressBook stub = (RMIAddressBook)
UnicastRemoteObject.exportObject(engine, 0);
Registry registry = LocateRegistry.getRegistry();
registry.rebind( SERVICE_NAME, stub );
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
| Author's Note: When running the RMI server you might have to change your java.policy file to grant sufficient rights to the RMI server. You can find out how to do that in the RMI tutorial. |
The client implementation is easy: All you need to do is look up the RMI service in the registry, get a reference to it, and then call it remotely and return the result immediately. Because the example uses the same RMI server throughout the entire client lifecycle, you can look it up in the constructor and store the remote handle. The code simply delegates the findFriend call to the remote RMI server:
public class RMIAddressBookClient
extends SimpleMeasurementImpl
implements AddressBookContract
{
RMIAddressBook book;
public RMIAddressBookClient()
{
try
{
Registry registry = LocateRegistry.getRegistry();
book = (RMIAddressBook) registry.lookup(
RMIAddressBookServer.SERVICE_NAME );
}
catch( Exception e )
{
book = null;
}
}
@Override
public AddressBean findFriend(String name)
{
timeStart = System.nanoTime();
try
{
return book.findAddress( name );
}
catch( Exception re )
{
re.printStackTrace();
return null;
}
finally
{
timeEnd = System.nanoTime();
}
}
}
Starting the RMI server and running the client render the following on my PC:
class rmi.RMIAddressBookClient found Liv : Oxford Street , London , SW1 in 3,789,190
The result required about 0.003 seconds to run the clientmore than 100 times faster than the XML-based approach154.1859 times faster, to be precise.
At this point you might be tempted to say that that's enough optimization (300 times faster than the web service approach sounds very good!) and opt for the RMI approach immediately. But is that the only alternative that is faster than XML? Consider another possibility, in which the server is TCP/IP-based and communicates with the client over sockets but they exchange Java objects directly rather than XML. This scheme eliminates building and parsing XML messages, and relies instead on Java's built-in serialization mechanismswhich might turn out to be faster.
