| Storing Objects in the Directory

## Remote Objects

> The RMI (Java Remote Method Invocation) system is a mechanism that enables an object on one Java virtual machine to invoke methods on an object in another Java virtual machine. Any object whose methods can be invoked in this way must implement the `java.rmi.Remote` interface. When such an object is invoked, its arguments are marshalled and sent from the local virtual machine to the remote one, where the arguments are unmarshalled and used. When the method terminates, the results are marshalled from the remote machine and sent to the caller's virtual machine.

> To make a remote object accessible to other virtual machines, a program typically registers it with the RMI registry. The program supplies to the registry the string name of the remote object as well as the remote object itself. When a program wants to access a remote object, it supplies the object's string name to the registry that is on the same machine as the remote object. The registry returns to the caller a reference (called stub) to the remote object. When the program receives the stub for the remote object, it can invoke methods on the object (through the stub).

> A program can also obtain references to remote objects as a result of remote calls to other remote objects or from other naming services. For example, the program can look up a reference to a remote object from an LDAP server that supports the schema defined RFC 2713.

> The string name accepted by the RMI registry has the syntax "rmi://hostname:port/remoteObjectName", where hostname and port identify the machine and port, respectively, on which the RMI registry is running and remoteObjectName is the string name of the remote object. hostname, port, and the prefix, `"rmi:"`, are optional. If hostname is not specified, then it defaults to the local host. If port is not specified, then it defaults to 1099. If remoteObjectName is not specified, then the object being named is the RMI registry itself. See the RMI specification for details.

> RMI can be supported by using the Java Remote Method Protocol (JRMP) and the Internet Inter-ORB Protocol (IIOP). The JRMP is a specialized protocol designed for RMI; the IIOP is the standard protocol for communication between CORBA objects. RMI over IIOP allows Java remote objects to communicate with CORBA objects that might be written in a non-Java programming language.

> Some service providers, such as Sun's LDAP service provider, support the binding of `java.rmi.Remote` objects into directories. When `java.rmi.Remote` objects and/or RMI registries are bound into an enterprise-wide shared namespace such as the LDAP, RMI clients can look up `java.rmi.Remote` objects without knowing on which machine the objects are running.

> #### Binding a Remote Object

> > Before you go on: To run this example, you need the Java 2 Platform, v1.2 or higher release. You also need `ldapbp.jar`, as stated in the introduction of this lesson.

> The following example defines a `java.rmi.Remote` interface `Hello` that has one method, `sayHello()`.

> >     public interface Hello extends Remote {
> >         public String sayHello() throws RemoteException;
> >     }

> It also defines an implementation of this interface, `HelloImpl`.

> >     public class HelloImpl extends UnicastRemoteObject implements Hello {
> >         public HelloImpl() throws RemoteException {
> >         }

> >         public String sayHello() throws RemoteException {
> >             return ("Hello, the time is " + new java.util.Date());
> >         }
> >     }

> This example also creates an instance of `HelloImpl` and binds it in the directory, assigning it the name `"cn=RemoteHello"`.

> >     // Create the remote object to be bound, and give it a name
> >     Hello h = new HelloImpl();

> >     // Bind the object to the directory
> >     ctx.bind("cn=RemoteHello", h);

> After the object has been bound in the directory, an application can look it up by using the following code.

> >     Hello h2 = (Hello)ctx.lookup("cn=RemoteHello");
> >     h2.sayHello();

> To run this example, you must do the following.

> 1. Compile `Hello.java`, `HelloImpl.java` and this example:

>    >     # javac Hello.java HelloImpl RemoteObj.java

> 2. Run `rmic` with `HelloImpl` as the argument to produce the stubs for the remote object:

>    >     # rmic HelloImpl

> 3. Copy `Hello.class`, `HelloImpl.class` and the class files generated by `rmic` to a directory on a Web server.
> 4. Specify this directory as the codebase to the Java interpreter.

>    >     # java -Djava.rmi.server.codebase=http://web1/example/classes/ RemoteObj

> `RemoteObj` does not terminate, because it created the remote object `HelloImpl` that other RMI clients can contact and use. However, this program will terminate eventually, when the remote object becomes garbage collected. To prevent the object's being garbage collected, you must maintain a (live) reference to the remote object. If you had registered the object in the RMI registry instead, then maintaining a reference would not be necessary because the registry would automatically maintain a reference to the object.

> When you later look up this object from the directory, the directory will return the bound `HelloImpl` remote object. The RMI will automatically download the necessary class files from the codebase specified in the `"java.rmi.server.codebase"` property. See the Reading Objects from the Directory lesson for an example.

> #### Binding a Remote Object by Using a Reference

> > Before you go on: This example requires that you have started the RMI registry on your machine. You also need `rmiregistry.jar`, as stated in the introduction of this lesson.

> The following example uses the same `Hello` and `HelloImpl` classes used in the previous example. It creates a `Reference` containing an RMI URL (`"rmi://mymachine/hello"`) and binds it in the directory.

> >     String rmiurl = "rmi://mymachine/hello";

> >     // Create the reference containing the (future) location of the object
> >     Reference ref = new Reference("Hello", new StringRefAddr("URL", rmiurl));

> >     // Bind the object to the directory
> >     ctx.bind("cn=RefHello", ref);

> It then creates an instance of `HelloImpl` and binds it in the local RMI registry by using the same RMI URL (`"rmi://mymachine/hello"`).

> >     // Create the remote object to be bound
> >     Hello h = new HelloImpl();

> >     // Bind the object to the RMI registry
> >     ctx.rebind(rmiurl, h);

> After the object has been bound in both the directory and the RMI registry, an application can look up the object by using the following code.

> >     Hello h2 = (Hello)ctx.lookup("cn=RefHello");
> >     System.out.println(h2.sayHello());

> In effect, this method has one more level of indirection than the previous example offered. The information stored in the directory (the `Reference`) is actually a pointer to information stored in another naming service (the RMI registry), which in turn, contains the reference to the `java.rmi.Remote` object.

> To run this example, you must do the following.

> 1. Perform Steps 1-3 from the previous example.
> 2. Compile this example:

>    >     # javac RemoteRef.java

> 3. Specify the codebase directory as the codebase to the Java interpreter.

>    >     # java -Djava.rmi.server.codebase=http://web1/example/classes/ RemoteRef

> `RemoteRef` does not terminate, because it created the remote object `HelloImpl` that other RMI clients can contact and use.

> When you later look up this object from the directory, the directory will return the bound `HelloImpl` remote object. The RMI will automatically download the necessary class files from the codebase specified in the `"java.rmi.server.codebase"` property. See the Reading Objects from the Directory lesson for an example.

> #### Binding a Remote Object That Uses IIOP

> > Before you go on: This example requires that you have `ldapbp.jar`, as stated in the introduction of this lesson. If you are not using the Java 2 SDK, v1.3, then you also need to install the RMI-IIOP Standard Extension. If you are not using the Java 2 SDK, v1.2 or higher release, then you also need to install Java IDL, a version of which comes with the RMI-IIOP Standard Extension.

> The procedure for binding a `java.rmi.Remote` object that uses IIOP or JRMP is identical as far as the JNDI is concerned. From the user/application's perspective, they differ only in how the stubs for the `java.rmi.Remote` object are generated. Looking up the object presents a bigger difference: When the object is looked up from the directory (or some other naming service), the result must be narrowed by using `javax.rmi.PortableRemoteObject.narrow()` instead of the Java type cast operator.

> The following example uses the `Hello` interface from the JRMP example. It defines an implementation of this interface, `RiHelloImpl`, that is analogous to `HelloImpl`, except that it extends from `javax.rmi.PortableRemoteObject` instead of from `java.rmi.server.UnicastRemoteObject`.

> >     public class RiHelloImpl extends PortableRemoteObject implements Hello {
> >         public RiHelloImpl() throws RemoteException {
> >         }

> >         public String sayHello() throws RemoteException {
> >             String date = new String((new java.util.Date()).toString());
> >             return ("RMI/IIOP hello | " + date);
> >         }
> >     }

> The example creates an instance of `RiHelloImpl` and binds it in the directory, assigning it the name `"cn=RmiiiopHello"`.

> >     // Create the remote object to be bound, and give it a name
> >     Hello h = new RiHelloImpl();

> >     // Bind the object to the directory
> >     ctx.bind("cn=RmiiiopHello", h);

> After the object has been bound in the directory, an application can look it up by using the following code.

> >     // Look up the object
> >     org.omg.CORBA.Object cobj = (org.omg.CORBA.Object)ctx.lookup("cn=RmiiiopHello");

> >     // Narrow the object to the desired type
> >     Hello robj = (Hello)PortableRemoteObject.narrow(cobj, Hello.class);

> >     // Invoke the method
> >     System.out.println(robj.sayHello());

> To run this example, you must do the following.
> 1. Compile `Hello.java`, `RiHelloImpl.java` and this example:

>    >     # javac Hello.java RiHelloImpl RmiiiopObj.java

> 2. Run `rmic` with `RiHelloImpl` as the argument and the `"-iiop"` option to produce the IIOP stubs for the remote object:

>    >     # rmic -iiop RiHelloImpl

> 3. Copy `Hello.class`, `RiHelloImpl.class` and the class files generated by `rmic` to a directory on a Web server.
> 4. Specify this directory as the codebase to the Java interpreter.

>    >     # java -Djava.rmi.server.codebase=http://web1/example/classes/ RmiiiopObj

> `RmiiiopObj` does not terminate, because it created the remote object `RiHelloImpl` that other RMI clients can contact and use.

> When you later look up this object from the directory, the directory will return the bound `RiHelloImpl` remote object. The RMI will automatically download the necessary class files from the codebase specified in the `"java.rmi.server.codebase"` property. See the Reading Objects from the Directory lesson for an example.

| Storing Objects in the Directory