Está en la página 1de 8

3.

3 Desarrollo e implementación
de una aplicación RMI
Como se ha comentado a lo largo de este documento, una aplicación
RMI típicamente está compuesta por un proceso servidor y otro cliente.
Un proceso servidor crea una serie de objetos remotos, hace accesibles
referencias a los mismos y queda a la espera de la invocación de sus
métodos por parte de los clientes.

Por otra parte, un cliente obtiene una referencia remota a algún objeto
del servidor, e invoca sus métodos [13].

En este apartado veremos cómo se lleva este proceso a la práctica.

3.3.1 Interfaces, objetos y métodos remotos


Una aplicación distribuida desarrollada utilizando RMI, como cualquier
aplicación Java, está compuesta por interfaces y clases. Los interfaces
definen métodos, mientras que las clases implementan los métodos
definidos en los interfaces (también puede definir 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 desde máquinas virtuales
localizadas en otros ordenadores, son los objetos remotos.

Un objeto se convierte en remoto implementando un interfaz remoto,


que tenga estas características.

 Un interfaz remoto extiende a java.rmi.Remote.


 Cada método del interfaz debe soportar la
excepción java.rmi.RemoteException, además de cualquier
excepción específica de la aplicación.

El stub de un objeto remoto implementa el mismo conjunto de


interfaces que el objeto. En consecuencia, y haciendo uso de las
propiedades básicas del lenguaje de programación Java, como son la
herencia y el polimorfismo, se permite la conversión de tipos del stub a
cualquiera de esas interfaces. Un cliente podrá recibir siempre
su stub aprovechando este mecanismo, que en la práctica se realizará a
través de la interfaz Remote ya presentada. Además, sólo aquellos
métodos definidos en una interfaz remota están disponibles para ser
llamados en la máquina virtual destino, lo cual permite aislar a los
objetos remotos y sólo hacerlos accesibles a determinados métodos.

3.3.2 Diseñar e implementar los componentes


de la aplicación distribuida
Podemos dividir la creación de una aplicación con objetos distribuidos
RMI en una serie de pasos descritos en los apartados siguientes:

 Diseñar e implementar los componentes de nuestra aplicación


distribuida
 Compilar los fuentes y generar los stubs
 Hacer las clases accesibles a la red
 Arrancar la aplicación

Primero, decidimos la arquitectura de nuestra aplicación y


determinamos qué componentes son objetos locales y cuáles accesibles
remotamente. Este paso incluye:

 Definir los interfaces remotos. Un interfaz remoto especifica los


métodos que pueden ser llamados remotamente por un cliente.
 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. Para implementar un cliente que
solicite servicio a un objeto remoto, de este último sólo es
necesario conocer su interfaz. En el código del cliente se
instancian las llamadas RMI a los objetos remotos mediante dichas
interfaces.

3.3.2.0.1 Compilar los fuentes y generar los stubs.

Este es un proceso de dos pasos. En el primer paso, se compilan los


ficheros fuentes de Java usando javac, los cuales contienen las
implementaciones de los interfaces remotos y las clases del servidor y
del cliente. En el segundo paso se utiliza el compilador rmic para crear
los stubs de los objetos remotos.

3.3.2.0.2 Hacer accesibles las clases en la red.

Si se va a permitir que la aplicación descargue, en tiempo de ejecución,


los ficheros de las clases Java asociadas a los interfaces remotos,
los stubs, u otras clases que necesitemos; se deben hacen accesibles,
por ejemplo, a través de un servidor web. El mecanismo que lo permite
es la carga dinámica de clases, que será estudiada posteriormente.

3.3.2.0.3 Arrancar la aplicación.

Arrancar la aplicación incluye ejecutar el registro de objetos remotos de


RMI (rmiregistry), el servidor y el cliente, en este orden.

El apéndice A de este documento muestra, con un ejemplo, los pasos


para elaborar una aplicación con RMI. El ejemplo (apéndice  ),
presenta un servicio que acepta peticiones de tareas concretas
especificadas por parte de los clientes. Es decir, cada cliente puede
especificar la tarea que desea que el servidor le realice, utilizando para
ello el paso de objetos serializados.

3.4 Carga dinámica de clases


utilizando RMI
Normalmente, tanto el cliente como el servidor disponen de las clases
que necesitan para su funcionamiento. RMI permite mayor flexibilidad
con la carga dinámica de clases. De esta forma se permite que los
clientes puedan acceder a nuevos servicios ofrecidos sin necesidad de
hacerles llegar las nuevas clases cada vez que sea necesario.

En el lenguaje de programación Java, el proceso por el que se


instancian objetos a partir de las clases que los definen, es realizado
por el cargador de clases. En consecuencia, el cargador de clases
debería disponer, a priori, de las clases que implementan los objetos
involucrados.

En el lado cliente, el cargador de clases debería disponer de los


archivos .class de los siguientes elementos: La interfaz remota, el stub
que implementa la interfaz remota, las clases del servidor cuyas
instancias usa el cliente y las clases propias del cliente.

En el lado servidor, el cargador de clases debería disponer de los


archivos .class de los siguientes elementos: La interfaz remota y, si
procede, la interfaz de objetos pasados como parámetro, la clase que
implementa la interfaz remota, el skeleton asociado a la
implementación (en el caso de tratarse de JDK 1.1), el stub que
implementa la interfaz remota y las clases propias del servidor

La figura 3.8 muestra la distribución (en lado cliente y servidor) de


clases para un ejemplo hipotético.

Figura: Distribución de archivos en una aplicación RMI

Mediante la carga dinámica de clases, RMI proporciona un mecanismo


que facilita la separación entre la implementación del lado cliente y la
del servidor. Un cambio realizado en, por ejemplo, un servidor (que
implicaría un cambio en el stub); no sería necesario notificarlo al
cliente, ya que la carga dinámica de clases le permite, en tiempo de
ejecución, descargar las nuevas clases. La
propiedad java.rmi.server.codebase permite indicar al cargador de
clases desde qué ubicaciones remotas puede descargar las clases. Esta
información se incluye en los datos serializados que se intercambian en
una aplicación RMI.

Cuando un proceso trata de extraer de los datos serializados algún


objeto (bien sea un objeto pasado como parámetro o el propio stub), los
pasos que se dan son los siguientes:

 Se lee la descripción de la clase incluida en el flujo


 El cargador de clases de Java busca esa clase en el directorio
actual
 Si no lo encuentra, busca en el CLASSPATH
 Si tampoco lo encuentra, comprueba si se ha incluido
el codebase en los datos serializados.

De esta forma, ubicando las clases necesarias en un lugar común y


especificando adecuadamente esta propiedad java.rmi.server.codebase,
los clientes y servidores pueden acceder a ellas aunque no las tengan en
sus respectivas máquinas. En consecuencia, podrán estar accesibles los
archivos .class de los stub, que son necesarios tanto para el cliente
como para el servidor y las interfaces implicadas (las del lado servidor y
las del lado cliente, si procede, como ocurría en el ejemplo anterior).

La configuración más típica es ubicar estas clases en un servidor web y


configurar la propiedad java.rmi.server.codebase con la URL
correspondiente.

Existen otras alternativas para implementar la carga dinámica de clases.


Una posibilidad es usar applets para el lado cliente, que no necesitan la
ubicación local de las clases implicadas. Usando applets la ejecución del
cliente se realizará mediante un navegador web. Las peticiones de
carga dinámica de clases (por ejemplo de los stubs) pasarán por el
navegador, que las convertirá en peticiones HTTP y las enviará al
servidor web. Éste enviará las clases (el bytecode) y, al ejecutarse las
llamadas a objetos remotos, serán redirigidas a los objetos servidores
RMI.

Destacar que cuando se inicia el rmiregistry hay que asegurarse de que


los stubs no estén accesibles en el directorio actual o en el CLASSPATH,
puesto que si es así, el servidor de registros de RMI ignorará la
propiedad java.rmi.server.codebase. En consecuencia, no pasará esta
información a los clientes cuando soliciten los stubs. Por lo tanto, estos
clientes no podrán localizar las clases del stub y demás objetos, con lo
que lanzarán una excepción java.lang.ClassNotFound. Es decir, si el
cliente no tienen accesible la clase, no puede interpretar el objeto que
instancia la misma, obtenido de los datos serializados recibidos.

En definitiva, si desarrollamos una aplicación RMI en la que queremos


que los clientes descarguen dinámicamente las clases de los stubs,
habría que hacerlo de la siguiente forma:

En el lado servidor.-
java -Djava.rmi.server.codebase=http://url/directorio/
-Djava.security.policy=mi_archivo_de_seguridad.policy Servidor

Suponiendo, claro está, que tanto el archivo que define las políticas de
seguridad como la clase servidora se encuentran en el directorio actual.

En el lado cliente.-
java -Djava.security.policy= mi_archivo_de_seguridad.policy
Cliente

La figura 3.9 muestra un esquema del funcionamiento de la descarga de


clases desde un servidor web.

Figura: Esquema para descarga de clases


Los pasos a seguir son los siguientes:

1. Se ejecuta el cliente, indicando con la


propiedad java.rmi.server.codebase el servidor web que permite
la descarga de las clases
2. Se localizan los objetos remotos
3. El cliente recibe el objeto remoto (el stub) serializado
4. Se busca la definición de la clase del objeto remoto en el servidor
web especificado
5. Se recibe la clase
6. Se ejecutan los métodos remotos requeridos

3.5 Resumen
RMI proporciona un mecanismo para la elaboración de aplicaciones con
objetos Java distribuidos. Al estar integrado dentro de la jerarquía de
paquetes oficiales del lenguaje de programación Java, se adapta
perfectamente al modelo de programación del mismo.

RMI facilita la elaboración de aplicaciones que sigan el modelo cliente-


servidor. Dada su naturaleza, resulta muy sencillo integrar RMI con la
versión empresarial del lenguaje Java (J2EE); con el objetivo de
desplegar, po ejemplo, los muy extendidos servicios web.

Para concluir, RMI presenta una serie de ventajas e inconvenientes:

Entre sus principales ventajas destaca su sencillez, con RMI los objetos
remotos se manejan como si fueran locales. Por otro lado, al existir una
separación entre interfaces e implementaciones, en una aplicación con
objetos distribuidos se pueden aprovechar las ventajas de la
programación orientada a objetos. Además, la carga dinámica de clases
permite, por ejemplo, que los clientes se conviertan
en applets interpretados en un navegador. RMI proporciona un servicio
de registro, rmiregistry, que facilita la localización por nombre de los
servicios. Por último, existe la posibilidad de añadir a las
comunicaciones RMI protocolos de seguridad, como SSL o HTTPS.

En contrapartida, uno de sus principales inconvenientes es el uso


exclusivo de Java; problema parcialmente resuelto con la posibilidad,
incorporada en las últimas versiones, de trabajar con nuevos protocolos
que proporcionan interoperatiblidad. Por otro lado, RMI no proporciona
metainformación, es decir, no dispone de un sistema que informe de los
servicios disponibles y sus APIs (nombre de métodos, valores de retorno,
etc.). Cierta consideración merece el hecho de que, al realizar el paso
de objetos por valor, cuando se serializa un objeto hay que hacerlo
junto con todos aquellos de los que tiene referencias. Cuanto mayor sea
el tamaño de estos objetos, mayor será el tráfico entre máquinas. Por
último, no existe un mecanismo que controle las transacciones
realizadas y actúe cuando no se completen.

     
Siguiente: 4. JGroups Subir: 1 MEMORIA Anterior: 2.
Antecedentes   Índice General
Luis Hernandez

También podría gustarte