Chapter 1. Introduction to RMI

  • Java and RMI—Architecture of an RMI system—Syntax of RMI—First principles—Baby's first words—Exercises

In this chapter

This chapter provides a high-level introduction to Remote Method Invocation (RMI) in Java. It outlines the architecture of an RMI system—from a simple configuration to a more advanced system such as RMI over Internet Inter-ORB Protocol (IIOP). As well as briefly stating the basic principles of RMI, this chapter also provides an RMI version of a simple echo service.

Java and RMI

In 1995, Sun Microsystems introduced the Java programming language. Since then it has been enthusiastically adopted by software developers looking for ways to build secure, platform-independent applications for distributed network environments like the World Wide Web. Along with the advantages of its portability between platforms, Java is an attractively simple language to learn, combining many of the runtime advantages of Smalltalk and the programming concepts of Modula-3 with the familiar syntax of C++. Developers can also benefit from its remarkably complete runtime library, its designed-in security model, and its price—to most developers Java is free.

Increasingly complex computing environments require increasingly powerful programming techniques like object-oriented programming. The Internet enables the deployment of enormous distributed applications. Java is an object-oriented language that allows developers to produce distributed client-server applications. Distributed applications depend on the communication between “objects” residing in different locations.

RMI adds to Java the power and flexibility of remote procedure calls (RPC), in a way which preserves the “object-oriented” nature of Java. It provides a framework within which Java objects in distinct Java virtual machines (JVMs) can interact. RMI is built on top of Java's object and class facilities, its object serialization protocol, and its TCP/IP networking support.

Architecture of RMI systems

The following high-level diagrams illustrate the components that are involved in:

  • a simple RMI system

  • an advanced RMI system

  • an RMI over IIOP system.

These examples illustrate the architecture that you will be working with when designing and building an RMI system. You can find out more about each component in the subsequent chapters of the book.

Figure 1.1 illustrates the RMI system at its simplest: a remote interface, a client, and one or more servers—remote objects—residing on a host. The client invokes methods on remote objects via the remote interface. A naming service such as the RMI registry resides on the host, to provide the mechanism the client uses to find one or more initial RMI servers. You can find out more about the RMI registry in Chapter 6.

Simple RMI system

Figure 1.1. Simple RMI system

Figure 1.2 illustrates a more advanced RMI system, including RMI Activation—a system which allows servers to be activated on demand. The RMI Activation system is discussed in detail in Chapter 10.

Advanced RMI system showing codebase and activation

Figure 1.2. Advanced RMI system showing codebase and activation

This diagram also illustrates that a web server providing an RMI codebase service may also be present in an RMI system. A codebase is a global location for Java class files and Java Archive (JAR) files, accessible to RMI clients and servers. You can find out more about using codebases in Chapter 9.

Figure 1.3 illustrates RMI over IIOP.In RMI/IIOP, the COS Naming service, accessed via the Java Naming and Directory Interface (JNDI), is used instead of the RMI registry. In RMI over IIOP you cannot use RMI Activation, which is only supported under the Java remote method protocol (JRMP). Find out more about these topics in Chapter 13 and Chapter 14.

RMI over IIOP

Figure 1.3. RMI over IIOP

Syntax of RMI

RMI reduces the complexities of distributed computing—such as locating the server, network connections, data transfer, synchronization, and propagating errors—to a simple method call and exception handler in the client, as shown in Example 1.1.

Example 1.1. Syntax of RMI

try
{
      result = remoteInterface.method(args);
}
catch (RemoteException ex)
{
      // handle a remote exception...
}

First principles—remote method invocation

Remote method invocation is the invocation of a method in a remote object.

A remote object is an object whose remote methods can be invoked—via a remote interface—from another Java virtual machine.[1] A remote object has all the usual properties of a Java object: it has state and methods; it can refer to other objects. It even has implementations of Object.clone, Object.equals, Object.hashCode, and Object.toString, with behaviour that is reasonable for a remote object.

A remote method is a method defined in a remote interface; it is invoked via that interface.

A remote interface is a Java interface which extends java.rmi.Remote. Its methods must all throw RemoteException.

Because Java interfaces cannot specify static methods, it follows that a remote method cannot be static.

Any object, even a local one, can be thought of as a server; its users are its clients. A local object is essentially a local server; a remote object is a remote server.

Remote methods in a remote object can be invoked via RMI even if the object is in fact in the same JVM. Obviously in this case they could also be invoked directly, i.e. via local method invocation.

To be accessible via RMI, a remote object must:

  • implement a remote interface

  • be exported to the RMI system.

An object is exported to the RMI system implicitly on construction, or explicitly by an exportObject method (to be discussed in a later chapter).

Remote stubs

A remote object is accessed via a remote stub. A remote stub is an object which implements the same remote interface(s) as the remote object it refers to. Its class is generated from the corresponding remote object by the RMI system at compile-time.

A remote stub can only be obtained as the result of another remote method invocation.[2] The client uses the remote stub as an instance of the remote interface implemented by the remote object. The remote stub is not itself the remote object; nor is it an instance of the remote class. A remote stub is really a proxy for the remote object.

For the record, a remote stub also has all the usual properties of a Java object: state, methods, and external references, although only the methods (not the state or external references) are of interest to the RMI client. It also has reasonable implementations of Object.clone, Object.equals, Object.hashCode, and Object.toString.

Remote exceptions

A remote exception is any object of the class java.rmi.RemoteException, or of any class derived from it.

Baby's first words

Consider a simple echo service as shown in Example 1.2.

Example 1.2. Simple echo service and client

class EchoServer
{
      public Object      echo(Object object) { return object;}
}

class EchoClient
{
      public static void main(String[] args) throws Exception
      {
             EchoServer echo = new EchoServer();
             System.out.println(echo.echo("O che bon eccho"));
      }
}

We can improve on this, by decoupling the server from the client—specifying an intermediate interface—and by using a ServerFactory for creating server objects. Such a version might look like Example 1.3.

Example 1.3. Decoupled echo service with factory

public interface Echo
{
       Object      echo(Object object);
}

class EchoServer implements Echo
{
      public Object    echo(Object object)    { return object;}
}

class EchoFactory
{
      public static Echo getEcho()            { return new EchoServer();}
}

class EchoClient
{
      public static void main(String[] args) throws Exception
      {
             Echo  echo = EchoFactory.getEcho();
             System.out.println(echo.echo("o che bon eccho"));
      }
}

An RMI version of the echo service is only a slight modification of Example 1.3, as shown in Example 1.4.

Example 1.4. RMI Echo interface, service, factory, and client

// imports not shown
public interface RemoteEcho extends Remote
{
       Object      echo(Object object) throws RemoteException;
}

class RemoteEchoServer extends UnicastRemoteObject
      implements RemoteEcho
{
      public RemoteEchoServer() throws RemoteException {}

      public Object    echo(Object object)
             throws RemoteException          { return object;}

      public static void main(String[] args) throws Exception
      {
             RemoteEchoServer server = new RemoteEchoServer();
             Naming.rebind(RemoteEcho.class.getName(),server);
      }
}

public class RemoteEchoFactory
{
      public static RemoteEcho getEcho()   throws Exception
      {
             return (RemoteEcho)Naming.lookup
                    (RemoteEcho.class.getName());
      }
}

class RemoteEchoClient
{
      public static void main(String[] args) throws Exception
      {

             RemoteEcho echo = RemoteEchoFactory.getEcho();
             System.out.println(echo.echo("o che bon eccho"));
      }
}

In the RMI version, we made the following changes:

  • we imported the RMI packages

  • the Echo interface now extends java.rmi.Remote, and its methods now throw RemoteException

  • the EchoServer class now extends java.rmi.server.UnicastRemoteObject

  • the EchoServer class now has a main procedure so it can execute in its own JVM

  • the EchoFactory now obtains its Echo object via the RMI registry instead of directly instantiating an EchoServer object

  • various exceptions can be thrown; we have shown this by just declaring the main methods to throw Exception, for brevity, but in practice you will want extensive try ... catch exception handling.

That's it!

The original version and both client/server versions can only execute in a single Java Virtual Machine (JVM). The RMI version can execute in a single JVM, in two JVMs on the same computer, or in two JVMs in two machines connected by a network.

Exercises

1:

Using the Echo service as a template, design and write a date/time service which returns the current date at the server, and a client which displays the remote date. Since we have not discussed the RMI runtime environment yet, you do not need to execute the exercise at this point.



[1] RMI specification, § 2.2.

[2] Normally. Obviously this statement implies an infinite regress. Where do we get the initial remote stub? It is specially constructed for the RMI registry, which is a bootstrapping mechanism provided in order to break out of the regress. See the separate chapter on the registry. It is also possible to acquire remote stubs via serialized MarshalledObjects.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.70.101