Welcome to EZDefinition.com
Technological Concepts, Abbreviations & Definitions
Main Menu
Main categories
  • Operating Systems
  • Computer Hardware
  • Internet
  • Programming Languages
  • Multimedia
  • Software
  • Security and Encryption
  • Communications and Networking
  • Organizations
  • Books
  • Databases
  • Games
  • E-commerce

    [an error occurred while processing this directive]

  • EZDefinition Sponsor
    Please visit our sponsor Parosoft.com
    Related Links to Java Server Pages
    [an error occurred while processing this directive]
    Java Server Pages
    [an error occurred while processing this directive]
    Computer Technologies  Programming Languages  Java Java Server Pages

    RMI (Remote Method Invocation)

    RMI (Remote Method Invocation)

    Traditional approaches to executing code on other machines across a network have been confusing as well as tedious and error-prone to implement. The nicest way to think about this problem is that some object happens to live on another machine, and that you can send a message to the remote object and get a result as if the object lived on your local machine. This simplification is exactly what Java Remote Method Invocation (RMI) allows you to do. This section walks you through the steps necessary to create your own RMI objects.

    Remote interfaces

    RMI makes heavy use of interfaces. When you want to create a remote object, you mask the underlying implementation by passing around an interface. Thus, when the client gets a reference to a remote object, what they really get is an interface reference, which happens to connect to some local stub code that talks across the network. But you don’t think about this, you just send messages via your interface reference.
    When you create a remote interface, you must follow these guidelines:
    1. The remote interface must be public (it cannot have “package access,” that is, it cannot be “friendly”). Otherwise, a client will get an error when attempting to load a remote object that implements the remote interface.
    2. The remote interface must extend the interface java.rmi.Remote.
    3. Each method in the remote interface must declare java.rmi.RemoteException in its throws clause in addition to any application-specific exceptions.
    4. A remote object passed as an argument or return value (either directly or embedded within a local object) must be declared as the remote interface, not the implementation class.
    Here’s a simple remote interface that represents an accurate time service:
    //: c15:rmi:PerfectTimeI.java
    // The PerfectTime remote interface.
    package c15.rmi;
    import java.rmi.*;

    public interface PerfectTimeI extends Remote {
    long getPerfectTime() throws RemoteException;
    } ///:~
    It looks like any other interface except that it extends Remote and all of its methods throw RemoteException. Remember that all the methods of an interface and all of its methods are automatically public.

    Implementing the remote interface

    The server must contain a class that extends UnicastRemoteObject and implements the remote interface. This class can also have additional methods, but only the methods in the remote interface are available to the client, of course, since the client will get only a reference to the interface, not the class that implements it.
    You must explicitly define the constructor for the remote object even if you’re only defining a default constructor that calls the base-class constructor. You must write it out since it must throw RemoteException.
    Here’s the implementation of the remote interface PerfectTimeI:
    //: c15:rmi:PerfectTime.java
    // The implementation of
    // the PerfectTime remote object.
    package c15.rmi;
    import java.rmi.*;
    import java.rmi.server.*;
    import java.rmi.registry.*;
    import java.net.*;

    public class PerfectTime
    extends UnicastRemoteObject
    implements PerfectTimeI {
    // Implementation of the interface:
    public long getPerfectTime()
    throws RemoteException {
    return System.currentTimeMillis();
    }
    // Must implement constructor
    // to throw RemoteException:
    public PerfectTime() throws RemoteException {
    // super(); // Called automatically
    }
    // Registration for RMI serving. Throw
    // exceptions out to the console.
    public static void main(String[] args)
    throws Exception {
    System.setSecurityManager(
    new RMISecurityManager());
    PerfectTime pt = new PerfectTime();
    Naming.bind(
    "//peppy:2005/PerfectTime", pt);
    System.out.println("Ready to do time");
    }
    } ///:~
    Here, main( ) handles all the details of setting up the server. When you’re serving RMI objects, at some point in your program you must:
    1. Create and install a security manager that supports RMI. The only one available for RMI as part of the Java distribution is RMISecurityManager.
    2. Create one or more instances of a remote object. Here, you can see the creation of the PerfectTime object.
    3. Register at least one of the remote objects with the RMI remote object registry for bootstrapping purposes. One remote object can have methods that produce references to other remote objects. This allows you to set it up so the client must go to the registry only once, to get the first remote object.

    Setting up the registry

    Here, you see a call to the static method Naming.bind( ). However, this call requires that the registry be running as a separate process on the computer. The name of the registry server is rmiregistry, and under 32-bit Windows you say:
    start rmiregistry
    to start it in the background. On Unix, the command is:
    rmiregistry &
    Like many network programs, the rmiregistry is located at the IP address of whatever machine started it up, but it must also be listening at a port. If you invoke the rmiregistry as above, with no argument, the registry’s port will default to 1099. If you want it to be at some other port, you add an argument on the command line to specify the port. For this example, the port is located at 2005, so the rmiregistry should be started like this under 32-bit Windows:
    start rmiregistry 2005
    or for Unix:
    rmiregistry 2005 &
    The information about the port must also be given to the bind( ) command, as well as the IP address of the machine where the registry is located. But this brings up what can be a frustrating problem if you’re expecting to test RMI programs locally the way the network programs have been tested so far in this chapter. In the JDK 1.1.1 release, there are a couple of problems:
    1. localhost does not work with RMI. Thus, to experiment with RMI on a single machine, you must provide the name of the machine. To find out the name of your machine under 32-bit Windows, go to the control panel and select “Network.” Select the “Identification” tab, and you’ll see your computer name. In my case, I called my computer “Peppy.” It appears that capitalization is ignored.
    2. RMI will not work unless your computer has an active TCP/IP connection, even if all your components are just talking to each other on the local machine. This means that you must connect to your Internet service provider before trying to run the program or you’ll get some obscure exception messages.
    With all this in mind, the bind( ) command becomes:
    Naming.bind("//peppy:2005/PerfectTime", pt);
    If you are using the default port 1099, you don’t need to specify a port, so you could say:
    Naming.bind("//peppy/PerfectTime", pt);
    You should be able to perform local testing by leaving off the IP address and using only the identifier:
    Naming.bind("PerfectTime", pt);
    The name for the service is arbitrary; it happens to be PerfectTime here, just like the name of the class, but you could call it anything you want. The important thing is that it’s a unique name in the registry that the client knows to look for to procure the remote object. If the name is already in the registry, you’ll get an AlreadyBoundException. To prevent this, you can always use rebind( ) instead of bind( ), since rebind( ) either adds a new entry or replaces the one that’s already there.
    Even though main( ) exits, your object has been created and registered so it’s kept alive by the registry, waiting for a client to come along and request it. As long as the rmiregistry is running and you don’t call Naming.unbind( ) on your name, the object will be there. For this reason, when you’re developing your code you need to shut down the rmiregistry and restart it when you compile a new version of your remote object.
    You aren’t forced to start up rmiregistry as an external process. If you know that your application is the only one that’s going to use the registry, you can start it up inside your program with the line:
    LocateRegistry.createRegistry(2005);
    Like before, 2005 is the port number we happen to be using in this example. This is the equivalent of running rmiregistry 2005 from a command line, but it can often be more convenient when you’re developing RMI code since it eliminates the extra steps of starting and stopping the registry. Once you’ve executed this code, you can bind( ) using Naming as before.

    Creating stubs and skeletons

    If you compile and run PerfectTime.java, it won’t work even if you have the rmiregistry running correctly. That’s because the framework for RMI isn’t all there yet. You must first create the stubs and skeletons that provide the network connection operations and allow you to pretend that the remote object is just another local object on your machine.
    What’s going on behind the scenes is complex. Any objects that you pass into or return from a remote object must implement Serializable (if you want to pass remote references instead of the entire objects, the object arguments can implement Remote), so you can imagine that the stubs and skeletons are automatically performing serialization and deserialization as they “marshal” all of the arguments across the network and return the result. Fortunately, you don’t have to know any of this, but you do have to create the stubs and skeletons. This is a simple process: you invoke the rmic tool on your compiled code, and it creates the necessary files. So the only requirement is that another step be added to your compilation process.
    The rmic tool is particular about packages and classpaths, however. PerfectTime.java is in the package c15.rmi, and even if you invoke rmic in the same directory in which PerfectTime.class is located, rmic won’t find the file, since it searches the classpath. So you must specify the location off the class path, like so:
    rmic c15.rmi.PerfectTime
    You don’t have to be in the directory containing PerfectTime.class when you execute this command, but the results will be placed in the current directory.
    When rmic runs successfully, you’ll have two new classes in the directory:
    PerfectTime_Stub.class
    PerfectTime_Skel.class
    corresponding to the stub and skeleton. Now you’re ready to get the server and client to talk to each other.

    Using the remote object

    The whole point of RMI is to make the use of remote objects simple. The only extra thing that you must do in your client program is to look up and fetch the remote interface from the server. From then on, it’s just regular Java programming: sending messages to objects. Here’s the program that uses PerfectTime:
    //: c15:rmi:DisplayPerfectTime.java
    // Uses remote object PerfectTime.
    package c15.rmi;
    import java.rmi.*;
    import java.rmi.registry.*;

    public class DisplayPerfectTime {
    public static void main(String[] args)
    throws Exception {
    System.setSecurityManager(
    new RMISecurityManager());
    PerfectTimeI t =
    (PerfectTimeI)Naming.lookup(
    "//peppy:2005/PerfectTime");
    for(int i = 0; i < 10; i++)
    System.out.println("Perfect time = " +
    t.getPerfectTime());
    }
    } ///:~
    The ID string is the same as the one used to register the object with Naming, and the first part represents the URL and port number. Since you’re using a URL, you can also specify a machine on the Interne.
    What comes back from Naming.lookup( ) must be cast to the remote interface, not to the class. If you use the class instead, you’ll get an exception.
    You can see in the method call
    t.getPerfectTime()
    that once you have a reference to the remote object, programming with it is indistinguishable from programming with a local object (with one difference: remote methods throw RemoteException)


    [an error occurred while processing this directive]

    [an error occurred while processing this directive]
     

    All Rights Reserved

    Terms of usage   Please read our privacy stetment
    Copyright © 1999-2006 EZDefinition.com

     

    [an error occurred while processing this directive]