<document>
<header>
<product>resin</product>
<title>RMI Resource</title>
<description>
<p>
Resin supports the use of RMI with the resource class 
<a href="javadoc|com.caucho.resources.rmi.RmiRegistry|"/>.
</p>

</description>
</header>

<body>
<summary objsummary='localtoc'/>

<section name="concepts" title="RMI concepts">

<p>
The goal of RMI is to provide <var/services/> to remote clients.  A remote
client obtains and uses a <var/proxy object/> that implements an
<var/interface/>.  The interface is the contract for the service, it is the
definition of the methods that the service provides.
</p>

<p>
Because the client is using a proxy object, the actual execution of code
occurs on the server.  A proxy object is placeholder that the client uses
to cause execution of code on a server.
</p>

<section name="concepts/registry" title="Registry">

<p>
The RMI registry is used to store a list of available services.  A client uses
the registry to make it's proxy object, and the Registry is responsible for
giving appropriate information to the client so that it can hook up with the
server that implements the service.  
</p>

<p>
In many scenarios, the Registry and the server for the services are in the same
JVM.  It is possible, however, for the Registry to run in a different
JVM or even on a different machine than the server or servers that implement
the services. 
</p>

<p>
A registry has a TCP port that it uses to listen to incoming requests,
typically this is port 1099.  The RMI registry is a global resource, each JVM
can have only one Registry on a particular port.  This has important
ramifications for the naming of services.
</p>

</section> <!-- concepts/registry -->

</section> <!-- concepts -->

<section title="The Hessian alternative">

<p>If you are considering RMI as a mechanism for publishing services, you may
want to consider using <a href="doc|protocols|hessian">Hessian</a> instead.  Hessian offers the following
advantages:</p>

<ul>
<li>it does not have a global namespace, separate web-app's can provide
services with the same name without conflict
<li>it supports the use of clients written in languages other than Java
<li>it does not require the manual generation of stubs
<li>it does not require a security-manager
</ul>


More information is available in the 
<a href="doc|protocols|hessian">Hessian</a> section of the documentation.

</section>

<section name="security-manager" title="Requirement: security-manager">

<p>
The JDK requires that a security manager be in place for the use of RMI.
This is true for both clients and servers.
A security manager is enabled in Resin using the <a config-tag="security-manager"/> configuration:
</p>

<example title="enabling security-manager in resin.conf">
&lt;resin xmlns="http://caucho.com/ns/resin"
       xmlns:resin="http://caucho.com/ns/resin/core"&gt;

  &lt;security-manager/&gt;

  ...
</example>

<p>
For clients that are applets, the developer does not need to enable the
security manager; the browser provides the security manager.
</p>

<p>
More information is available in the 
<a href="doc|security|securitymanager">Security</a>
section of the documentation.
</p>

</section>
<section name="ref" title="com.caucho.resources.rmi.RmiRegistry">
<p>
Resin provides the resource class 
<a href="javadoc|com.caucho.resources.rmi.RmiRegistry|"/>
to define an RMI Registry and register services with it.
If the Registry is on the `localhost' server, then Resin will also start the
RMI Registry if needed.
</p>

<example title="Example use of RMI Registry">
&lt;web-app&gt;
  &lt;resource type="com.caucho.resources.rmi.RmiRegistry"&gt;
    &lt;init&gt;
      &lt;server&gt;localhost&lt;/server&gt;  <!-- optional, default is `localhost' -->
      &lt;port&gt;1099&lt;/port&gt;           <!-- optional, default is `1099' -->

      &lt;rmi-service service-name="HelloWorld" 
                      service-class="example.HelloWorldImpl"/&gt;
      &lt;rmi-service .... &gt;
    &lt;/init&gt;
  &lt;/resource&gt;
&lt;/web-app&gt;
</example>


<defun title="com.caucho.resources.rmi.RmiRegistry" version="Resin 3.0.6">

<deftable-childtags>
<tr><td occur="?">server<td>the ip address of the server with the Registry<td>localhost
<tr><td occur="?">port<td>the port of the Registry<td>1099
<tr><td occur="*">rmi-service<td>an rmi service (see below)<td>&nbsp;
</deftable-childtags>

<p>
<code>RmiRegistry</code> is used to define the location of an RMI Registry to
use.  If <code>server</code> is `localhost', then the Registry will be started
on the specified port, if it has not already been started.
</p>

<p>
If <code>server</code> is something other than `localhost', then it is assumed
that the Registry has been started by some other JVM , and is treated as remote Registry to register any services defined with <code>rmi-server</code>.
</p>
</defun>
 

<defun title="rmi-service" version="Resin 3.0.6">
<parents>com.caucho.resources.rmi.RmiRegistry</parents>

<p>
Each <code>RmiRegistry</code> can have <code>rmi-service</code> children, which
causes the service to be instantiated and registered with the RMI Registry
defined by the containing <code>RmiRegistry</code>.  
</p>

<deftable-childtags>
<tr><td occur="1">service-name<td>the name of the service, used for registration in the Registry and also used by clients to locate the service.<td>required
<tr><td occur="1">server-class<td>the name of the implementation class for the service<td>required
</deftable-childtags>
</defun>
</section> <!-- ref -->

<section name="implement" title="Implementing a service">

<section title="Interface and Implementaion">

<p>An RMI service requires the developer to create two classes - an interface
and an implementation.  The interface defines the contract for the service, it
is given to the client and it is the client view of the service.  The
implementation class implements the functionality; it implements
the interface and is used on on the server.</p>

<p>The following is a simple hello world example.</p>

<example title="interface - WEB-INF/classes/example/HelloWorld.java">
package example;

import java.rmi.Remote;
import java.rmi.RemoteException;


public interface HelloWorld extends Remote
{
  public String sayHello()
    throws RemoteException;
}
</example>

<example title="implementation - WEB-INF/classes/example/HelloWorldImpl.java">
package example;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;


public class HelloWorldImpl extends UnicastRemoteObject implements HelloWorld
{
  public HelloWorldImpl()
    throws RemoteException
  {
    super();
  }

  public String sayHello()
    throws RemoteException
  {
    return "Hello, World";
  }
}
</example>

</section>

<section title="Making Stubs">

<p>When the client uses a service, it uses a <var/proxy object/>.  The proxy
object is a placeholder, it implements the interface defined for the service,
and call's through to the server so that the code is executed on the
server.</p>

<p>RMI calls proxy objects <code>Stubs</code>, and the stubs must be manually
generated.  The generation of stubs is done using the <code>rmic</code>
tool.</p>

<example title="using rmic to generate Stubs">
rmic -v1.2 -d WEB-INF/classes/  example.HelloWorldImpl 
</example>

<p>
This call to <code>rmic</code> will use the file
<code>WEB-INF/classes/example/HelloWorldImpl.class</code> to generate the class
file <code>WEB-INF/classes/example/HelloWorldImpl_Stub.class</code>.
</p>

<p>
It is tedious to perform this step manually, an ant build script (as shown
in a later section) can be used to expediate the process.
</p>

</section>

<section name="implement/deploy" title="Deploying the service with Resin">
<p>
Once the work of making an interface, an implementation, and generating a stub
is complete, it is a simple process to deploy the service in Resin.  
</p>

<example title="Deploying the service with Resin">
&lt;web-app&gt;
  &lt;resource type="com.caucho.resources.rmi.RmiRegistry"&gt;
    &lt;init&gt;
      &lt;server&gt;localhost&lt;/server&gt;  <!-- optional, default is `localhost' -->
      &lt;port&gt;1099&lt;/port&gt;           <!-- optional, default is `1099' -->

      &lt;rmi-service service-name="HelloWorld" service-class="example.HelloWorldImpl"/&gt;
    &lt;/init&gt;
  &lt;/resource&gt;
&lt;/web-app&gt;
</example>

<p>
More than once service is easily deployed
with the use of multiple <code>rmi-service</code> tags:
</p>

<example title="Deploying more than once service with Resin">
&lt;web-app&gt;
  &lt;resource type="com.caucho.resources.rmi.RmiRegistry"&gt;
    &lt;init&gt;
      &lt;server&gt;localhost&lt;/server&gt;  <!-- optional, default is `localhost' -->
      &lt;port&gt;1099&lt;/port&gt;           <!-- optional, default is `1099' -->

      &lt;rmi-service service-name="HelloWorld" service-class="example.HelloWorldImpl"/&gt;
      &lt;rmi-service service-name="HelloAgainWorld" service-class="example.HelloAgainWorldImpl"/&gt;
    &lt;/init&gt;
  &lt;/resource&gt;
&lt;/web-app&gt;
</example>

<section title="Choosing a name">

<p>By convention, the name chosen for the service often matches the name of the
interface class.  For example, if the interface name is "example.HelloWorld"
then service-name is "HelloWorld" or even "example.HelloWorld" to match.
</p>

<p>The RMI Registry has a global namespace.  If two different web-app's try to
publish the same service, with the same name, there will be conflicts.</p>

</section>
</section>  <!-- implement/deploy -->

<section title="An example build file">
<p>
An ant build file is useful for completing the <code>rmic</code> step, and for
preparing a jar for use by the client.  The client jar contains the interfaces
and the stubs.
</p>

<p>
The following build file, placed in <code>/WEB-INF/build</code>, creates
the jar file <code>/rmiclient.jar</code>.
</p>

<example title="WEB-INF/build.xml">
&lt;project name="rmiexample" default="dist" basedir="."&gt;

&lt;property file="local.properties"/&gt;
&lt;property file="build.properties"/&gt;
&lt;property environment="env"/&gt; 

&lt;property name="build.compiler.emacs" value="true"/&gt; 
&lt;property name="resin.home" value="${'${'}env.RESIN_HOME}"/&gt; 

&lt;property name="rmiclient.jar" value="../rmiclient.jar"/&gt;

&lt;!-- NOTE: new RMI interfaces must have corresponding entries addeed
   -       in the rmiclient.jar taget
   --&gt;

&lt;path id="compile.classpath"&gt;
  &lt;fileset dir="${'${'}resin.home}/lib"&gt;
    &lt;include name="**/*.jar" /&gt;
  &lt;/fileset&gt;
&lt;/path&gt;

&lt;target name="init"&gt;
  &lt;tstamp/&gt;
&lt;/target&gt;

&lt;target name="compile" depends="init"&gt;
  &lt;mkdir dir="classes"/&gt;
  &lt;javac classpathref="compile.classpath"
         destdir="classes"
         debug="true"&gt;
    &lt;src path="classes"/&gt;
  &lt;/javac&gt;
&lt;/target&gt;

&lt;target name="rmic" depends="init,compile"&gt;
  &lt;rmic base="classes"
        classpathref="compile.classpath"
        includes="**/*Impl.class"/&gt;
&lt;/target&gt;


&lt;target name="rmiclient.jar" depends="init,rmic"&gt;
  &lt;jar destfile="${'${'}rmiclient.jar}"&gt;
    &lt;fileset dir="classes"&gt;
      &lt;patternset&gt;
        &lt;include name="**/HelloWorld.class"/&gt;
        &lt;include name="**/*_Stub.class"/&gt;
      &lt;/patternset&gt;
    &lt;/fileset&gt;
  &lt;/jar&gt;
&lt;/target&gt;

&lt;target name="dist" depends="rmiclient.jar"/&gt;

&lt;/project&gt;
</example>

</section>

</section>

<section name="client" title="Implementing a client">
<p>
The client is usually on a different machine, or at least in a different JVM, than the server.  That is the point of RMI, it enables the execution of code on a remote machine.
</p>

<p>
In order to use the RMI service, the client needs the interface classes and the
Stubs.  The easiest way to provide these to the client is to provide a jar; the
ant build file above provides an example of using ant to automate the creation
of the jar file for the client.  
</p>

<p>
Once the jar file is available to the client, using the RMI service id fairly simple.
</p>

<example title="An RMI client">
  String server = "//server-with-registry.com:1099/";
  HelloWorld remote = (HelloWorld) Naming.lookup(server + "HelloWorld");

  System.out.println(remote.sayHello());
</example>

</section> <!-- client -->

<section name="scenarios" title="Scenarios">

<section title="A Resin server that provides the Registry and the service">

<p>In the most common scenario, the Resin server provides both the RMI Registry
and the RMI services.  When the registry server is defined as `localhost',
Resin will start the rmi registry if has not been started already.</p>

<p>This provides a simple method of using RMI, you don't have to worry about
the (somewhat tricky) process of starting the rmi registry yourself.</p>

<example title="Scenario: a Resin server that provides the Registry and the service">
&lt;web-app&gt;
  &lt;resource type="com.caucho.resources.rmi.RmiRegistry"&gt;
    &lt;init&gt;
      &lt;server&gt;localhost&lt;/server&gt;
      &lt;port&gt;1099&lt;/port&gt;

      &lt;rmi-service service-name="HelloWorld" service-class="example.HelloWorldImpl"/&gt;
      &lt;rmi-service .... &gt;
    &lt;/init&gt;
  &lt;/resource&gt;
&lt;/web-app&gt;
</example>

<p>
When the Resin server starts, it will start the rmi registry on port 1099 and register the `HelloWorld' service with it.
</p>
</section>

<section title="A Registry on a different server">

<p>In this scenario, the rmi registry is located on the machine
<code>services.hogwarts.com</code>.  The registry is started with a custom (not
Resin) server implemented by Hogwarts.</p>

<p>The requirement is for the HelloWorld service, implemented within a Resin
server, to be registered with the remote Registry.</p>

<p>In this scenario, the Resin resource RmiRegistry is used to attach to the
existing RMI registry running on <code>services.hogwarts.com</code>.  </p>

<example title="A Registry on a different server">
&lt;web-app&gt;
  &lt;resource type="com.caucho.resources.rmi.RmiRegistry"&gt;
    &lt;init&gt;
      &lt;server&gt;services.hogwarts.com&lt;/server&gt;
      &lt;port&gt;1099&lt;/port&gt;

      &lt;rmi-service service-name="HelloWorld" service-class="example.HelloWorldImpl"/&gt;
      &lt;rmi-service .... &gt;
    &lt;/init&gt;
  &lt;/resource&gt;
&lt;/web-app&gt;
</example>

<p>
When the Resin server starts, it will register the `HelloWorld' service with
the RMI Registry on <code>services.hogwarts.com</code>.  Since the server is on
a remote machine, Resin will not create a registry on the local machine.  When
the REsin server shuts down, or is restarted, the `HelloWorld' service will be
removed from the remote registry.
</p>
</section>


<section title="A Registry in a different JVM">

<p>In this scenario, the rmi registry is located on the same machine
as the Resin server, but is started  with a custom (not
Resin) server implemented by Hogwarts.</p>

<p>This is essentially the same scenario as having a Registry on a different
szerver.  The server name cannot be provided as `localhost', however, because
Resin will try to create the RMI registry.</p>

<p>The solution is to use an IP address of `127.0.0.1' as the address of the
server.  Because the server name is not `localhost', the RMI registry will not
be created.</p>

<example title="A Registry in a different JVM">
&lt;web-app&gt;
  &lt;resource type="com.caucho.resources.rmi.RmiRegistry"&gt;
    &lt;init&gt;
      &lt;server&gt;127.0.0.1&lt;/server&gt;
      &lt;port&gt;1099&lt;/port&gt;

      &lt;rmi-service service-name="HelloWorld" service-class="example.HelloWorldImpl"/&gt;
      &lt;rmi-service .... &gt;
    &lt;/init&gt;
  &lt;/resource&gt;
&lt;/web-app&gt;
</example>

<p>
When the Resin server starts, it will register the `HelloWorld' service with
the RMI Registry on the local machine.  Since the server is not `localhost',
Resin will not create a registry on the local machine.  When
the Resin server shuts down, or is restarted, the `HelloWorld' service will be
removed from the remote registry.
</p>

</section>

</section> <!-- scenarios -->

</body>
</document>

