## Introducción a las Aplicaciones RMI

Las aplicaciones RMI normalmente comprenden dos programas separados: un servidor y un cliente. Una aplicación servidor típica crea un montón de objetos remotos, hace accesibles unas referencias a dichos objetos remotos, y espera a que los clientes llamen a estos métodos u objetos remotos. Una aplicación cliente típica obtiene una referencia remota de uno o más objetos remotos en el servidor y llama a sus métodos. RMI proporciona el mecanismo por el que se comunican y se pasan información del cliente al servidor y viceversa. Cuando es una aplicación algunas veces nos referimos a ella como Aplicación de Objetos Distribuidos.

Las aplicaciones de objetos distribuidos necesitan:

Localizar Objetos Remotos
  Las aplicaciones pueden utilizar uno de los dos mecanismos para obtener referencias a objetos remotos. Puede registrar sus objetos remotos con la facilidad de nombrado de RMI rmiregistry. O puede pasar y devolver referencias de objetos remotos como parte de su operación normal.

Comunicar con Objetos Remotos
  Los detalles de la comunicación entre objetos remotos son manejados por el RMI; para el programador, la comunicación remota se parecerá a una llámada estándard a un método Java.

Cargar Bytecodes para objetos que son enviados.
  Como RMI permite al llamador pasar objetos Java a objetos remotos, RMI proporciona el mecanismo necesario para cargar el código del objeto, así como la transmisión de sus datos.

La siguiente ilustración muestra una aplicación RMI distribuida que utiliza el registro para obtener referencias a objetos remotos. El servidor llama al registro para asociar un nombre con un objeto remoto. El cliente busca el objeto remoto por su nombre en el registro del servidor y luego llama a un método. Esta ilustración también muestra que el sistema RMI utiliza una servidor Web existente para cargar los bytecodes de la clase Java, desde el servidor al cliente y desde el cliente al servidor, para los objetos que necesita.

El sistema RMI utiliza un servidor Web para cargar los bytecodes de la clase Java, desde el servidor al cliente y desde el cliente al servidor.

#### Ventajas de la Carga Dinámica de Código

Una de las principales y únicas características de RMI es la habilidad de descargar los bytecodes (o simplemente, código) de una clase de un objeto si la clase no está definida en la máquina virtual del recibidor. Los tipos y comportamientos de un objeto, anteriormente sólo disponibles en una sóla máquina virtual, ahora pueden ser transmitidos a otra máquina virtual, posiblemente remota. RMI pasa los objetos por su tipo verdadero, por eso el comportamiento de dichos objetos no cambia cuando son enviados a otra máquina virtual. Esto permite que los nuevos tipos sean introducidos en máquinas virtuales remotas, y así extender el comportamiento de una aplicación dinámicamente. El ejemplo del motor de cálculo de este capítulo utiliza las capacidad de RMI para introducir un nuevo comportamiento en un programa distribuido.

#### Interfaces, Objetos y Métodos Remotos

Una aplicación distribuida construida utilizando RMI de Java, al igual que otras aplicaciones Java, está compuesta por interfaces y clases. Los interfaces definen métodos, mientras que las clases implementan los métodos definidos en los interfaces y, quizás, también definen algunos métodos adicionales. En una aplicación distribuida, se asume que algunas implementaciones residen en diferentes máquinas virtuales. Los objetos que tienen métodos que pueden llamarse por distintas máquinas virtuales son los objetos remotos.

Un objeto se convierte en remoto implementando un interface remoto, que tenga estas caracterísitcas:

- Un interface remoto desciende del interface java.rmi.Remote.
- Cada método del interface declara que lanza una java.rmi.RemoteException además de cualquier excepción específica de la aplicación.

El RMI trata a un objeto remoto de forma diferente a como lo hace con los objetos no-remotos cuando el objeto es pasado desde una máquina virtual a otra. En vez de hacer una copia de la implementación del objeto en la máquina virtual que lo recibe, RMI pasa un stub para un objeto remoto. El stub actúa como la representación local o proxy del objeto remoto y básicamente, para el llamador, es la referencia remota. El llamador invoca un método en el stub local que es responsable de llevar a cabo la llamada al objeto remoto.

Un stub para un objeto remoto implementa el mismo conjunto de interfaces remotos que el objeto remoto. Esto permite que el stub sea tipado a cualquiera de los interfaces que el objeto remoto implementa. Sin embargo, esto también significa que sólo aquellos métodos definidos en un interface remoto están disponibles para ser llamados en la máquina virtual que lo recibe.

#### Crear Aplicaciones Distribuidas utilizando RMI

Cuando se utiliza RMI para desarrollar una aplicación distribuida, debemos seguir estos pasos generales:

1. Diseñar e implementar los componentes de nuestra aplicación distribuida.
2. Compilar los Fuentes y generar stubs.
3. Hacer las clases Accesibles a la Red.
4. Arrancar la Aplicación.

#### Diseñar e implementar los componentes de nuestra aplicación distribuida.

Primero, decidimos la arquitectura de nuestra aplicación y determinamos qué componentes son objetos lcoales y cuales deberían ser accesibles remotamente. Este paso incluye:

- Definir los Interfaces Remotos. Un interface remoto especifica los métodos que pueden ser llamados remotamente por un cliente. Los clientes programan los interfaces remotos, no la implementación de las clases de dichos interfaces. Parte del diseño de dichos interfaces es la determinación de cualquier objeto local que sea utilizado como parámetro y los valores de retorno de esos métodos; si alguno de esos interfaces o clases no existen aún también tenemos que definirlos.

- Implementar los Objetos Remotos. Los objetos remotos deben implementar uno o varios interfaces remotos. La clase del objeto remoto podría incluir implementaciones de otros interfaces (locales o remotos) y otros métodos (que sólo estarán disponibles localmente). Si alguna clase local va a ser utilizada como parámetro o cómo valor de retorno de alguno de esos métodos, también debe ser implementada.

- Implementar los Clientes. Los clientes que utilizan objetos remotos pueden ser implementados después de haber definido los interfaces remotos, incluso después de que los objetos remotos hayan sido desplegados.

#### Compilar los Fuentes y Generar stubs.

Este es un proceso de dos pasos. En el primer paso, se utiliza el compilador javac para compilar los ficheros fuentes de Java, los cuales contienen las implementaciones de los interfaces remotos, las clases del servidor, y del cliente. En el segundo paso es utilizar el compilador rmic para crear los stubs de los objetos remotos. RMI utiliza una clase stub del objeto remoto como un proxy en el cliente para que los clientes puedan comunicarse con un objeto remoto particular.

#### Hacer accesibles las Clases en la Red.

En este paso, tenmos que hacer que todo - los ficheros de clases Java asociados con los interfaces remotos, los stubs, y otras clases que necesitemos descargar en los clientes - sean accesibles a través de un servidor Web.

#### Arrancar la Aplicación.

Arrancar la aplicación incluye ejecutar el registro de objetos remotos de RMI, el servidor y el cliente.

El resto de este capítulo muestra cómo seguir estos pasos para crear un motor de cálculo.

#### Construir un Motor de Cálculo Genérico

Esta sección se enfoca a una sencilla pero potente aplicación distribuida llamada motor de cálculo. Este motor de cálculo es un objeto remoto en el servidor que toma tareas de clientes, las ejecuta, y devuelve los resultados. Las tareas se ejecutan en la máquina en la que se está ejecutando el servidor. Este tipo de aplicación distribuida podría permitir que un número de máquinas clientes utilizaran una máquina potente, o una que tuviera hardware especializado.

El aspecto novedoso del motor de cálculo es que las tareas que ejecuta no necesitan estar definidas cuando se escribe el motor de cálculo. Se pueden crear nuevas clases de tareas en cualquier momento y luego entregarlas el motor de cálculo para ejecutarlas. Todo lo que una tarea requiere es que su clase implemente un interface particular. Por eso una tarea puede ser enviada al motor de cálculo y ejecutada, incluso si la clase que define la tarea fue escrita mucho después de que el motor de cálculo fuera escrito y arrancado. El código necesita conseguir que una tarea sea descargada por el sistema RMI al motor de cálculo, y que éste ejecute la tarea utilizando los recursos de la máquina en la que está ejecutando el motor de cálculo.

La habilidad para realizar tareas arbitrarias esta permitida por la naturaleza dinámica de la plataforma Java, que se extiende a través de la red mediante RMI. El RMI carga dinámicamente el código de las tareas en la máquina virtual del motor de cálculo y ejecuta la tarea si tener un conocimiento anterior de la clase que implementa la tarea. Una aplicación como ésta que tiene la habilidad de descargar código dinámicamente recibe el nombre de "aplicación basada en comportamiento". Dichas aplicaciones normalmente requieren infraestructuras que permitan agentes. Con RMI, dichas aplicaciones son parte del macanismo básico de programación distribuida de Java.

Ozito