Compilar el Programa de Ejemplo

En un escenario del mundo real donde se desarrollara un servicio como el del motor de cálculo, un desarrollador querría crear un fichero JAR que contenga los interfaces Compute y Task para que los implementan las clases servidor y para que los utilicen los programas clientes.

Luego, un desarrollador (quizás el mismo que creo el fichero JAR con los interfaces) escribiría una implementación del interface Compute y desarrollaría ese servicio en una máquina disponible para los clientes.

Los desarrolladores de los programas clientes pueden utilizar los interfaces Compute y Task (contenidos en el fichero JAR) e independientemente desarrollar una tarea y un programa cliente que utilice un servicio Compute.

En esta página, aprenderemos cómo crear un fichero JAR, las clases del servidor, y las clases del cliente. Veremos como la clase Pi será descargada al servidor durante la ejecución. También veremos como el stub remoto ComputeEngine será descargado desde el servidor hasta el cliente durante la ejecución.

El ejemplo separa los interfaces, la implementación de los objetos remotos y el código del cliente en tres paquetes diferentes:

Primero construiremos el fichero JAR para proporcionar los interfaces del servidor y del cliente a los desarrolladores.

Construir un Fichero JAR con las Clases de Interfaces

Primero necesitamos compilar los ficheros fuente de los interfaces del paquete compute que construir un fichero JAR que contenga los ficheros class. Supongamos que el usuario waldo ha escrito estos interfaces particulares y ha situado los ficheros fuente en c:\home\waldo\src\compute (en UNIX sería, /home/waldo/src/compute). Con estos paths podemos utilizar los siguientes comandos para compilar los intefaces y crear el fichero JAR


Detalles específicos de la Plataforma: Construir un Fichero JAR

Windows:

cd c:\home\waldo\src
javac compute\Compute.java 
javac compute\Task.java
jar cvf compute.jar compute\*.class

UNIX:

cd /home/waldo/src
javac compute/Compute.java 
javac compute/Task.java
jar cvf compute.jar compute/*.class
El comando jar muestra la siguiente salida (debido a la opción -v):
added manifest
adding: compute/Compute.class (in=281) (out=196) 
    	(deflated 30%)
adding: compute/Task.class (in=200) (out=164) 
    	(deflated 18%)

Ahora podemos distribuir el fichero compute.jar a los desarrolladores de las aplicaciones del cliente y del servidor para que puedan hacer uso de los interfaces.

En general, cuando cosntruimos las clases del servidor o del cliente con los compiladores javac y rmic, necesitaremos especificar donde deberían residir los ficheros de clase resultantes para que sean accesibles a la red. En este ejemplo, esta localización es, para Unix, /home/user/public_html/classes porque algunos servidores web permiten el acceso a public_html mediante una URL HTTP construida como http://host/~user/. Si nuestro servidor web no soporta esta convención, podríamos utilizar un fichero URL en su lugar. El fichero de URL toma la forma file:/home/user/public_html/classes/ en UNIX, o file:/c:\home\user\public_html\classes/ en Windows. También se puede seleccionar otro tipo de URL apropiado.

La accesibilidad en la red de los ficheros de clases permite al sistema RMI descargar código cuando sea necesario. En vez de definir su propio protocolo para descargar código, RMI utiliza un protocolo URL soportado por Java (por ejemplo, HTTP) para descargar el código. Observa que un servidor web completo y poderoso no necesita realizar esta descarga de fichero class. De hecho, un sencillo servidor HTTP proporciona toda la funcionalidad necesaria para hacer que las clases estén disponibles para su descarga en RMI mediante HTTP, puedes encontrar uno en:

ftp://java.sun.com/pub/jdk1.1/rmi/class-server.zip

Construir las Clases del Servidor

El paquete engine sólo contiene la implementación de la clase del lado del servidor, ComputeEngine, la implementación del objeto remoto del interface Compute. Como ComputeEngine es una implementación de un interface remoto, necesitamos generar un stub para el objeto remoto para que los clientes puedan contactar con él.

Digamos que, ana, la desarrolladora de la clase ComputeEngine, ha situado ComputeEngine.java en el directorio c:\home\ana\src\engine, y ha colocado el fichero class para que lo usen los clientes en un subdirectorio de su directorio public_html, c:\home\ana\public_html\classes (en UNIX podría ser /home/ana/public_html/classes, accesible mendiante algún servidor web como http://host/~ana/classes/).

Asumamos que el fichero compute.jar esta localizado en el directorio c:\home\ana\public_html\classes. Para compilar la clase ComputeEngine, nuestro path de clases debe incluir el fichero compute.jar y el propio directorio fuente.


Una nota sobre el path de clases: Normalmente, recomendamos seleccionar el path de clases en la linea de comandos utilizando la opción -classpath. Sin embargo, por varias razones, este ejemplo utiliza la variable de entorno CLASSPATH (porque tanto javac como rmic necesitan un path de clases y la opción -classpath se trata de forma diferente en el JDK 1.1 y el JDK 1.2). Recomendamos que no selecciones el CLASSPATH en un fichero de login o de arranque y que los desactives después de haber terminado con este ejemplo.

Para más información sobre CLASSPATH puedes visitar http://java.sun.com/products/jdk/1.2/docs/install.html


Aquí podemos ver cómo seleccionar la variable de entorno CLASSPATH:


Detalles Específicos de la Plataforma: Selecionar el CLASSPATH

Windows:

set CLASSPATH=c:\home\ana\src;c:\home\ana\public_html\classes\compute.jar

Unix:

setenv CLASSPATH /home/ana/src:/home/ana/public_html/classes/compute.jar

Ahora compilamos el fichero fuente ComputeEngine.java y generamos un stub para la clase ComputeEngine y coloca el stub accesible a la red. Para crear el stub (y opcionalmente los ficheros esqueleto) ejecutamos el compilador rmic sobre los nombres totalmente cualificados de las clases de implementación de los objetos remotos que deberían encontrarse en el path de clases. El comando rmic toma uno o más nombres de clase como entrada y produce, como salida, ficheros de clases con la forma ClassName_Stub.class (y opcionalmente ClassName_Skel.class). El fichero esqueleto no será generado si llamamos a rmic con la opción -v1.2. Esta opción sólo debería utilizarse si todos nuestros clientes van a utilizar el JDK 1.2 o posterior.


Detalles Específicos de la Plataforma: Compilar el Motor de Cálculo y sus Stubs

Windows:

cd c:\home\ana\src
javac engine\ComputeEngine.java
rmic -d . engine.ComputeEngine
mkdir c:\home\ana\public_html\classes\engine
cp engine\ComputeEngine_*.class
    c:\home\ana\public_html\classes\engine

Unix:

cd /home/ana/src
javac engine/ComputeEngine.java
rmic -d . engine.ComputeEngine
mkdir /home/ana/public_html/classes/engine
cp engine/ComputeEngine_*.class
    /home/ana/public_html/classes/engine

La opción -d le dice al compilador rmic que situe los ficheros de clases generados, ComputeEngine_Stub y ComputeEngine_Skel, en el directorio c:\home\ana\src\engine. También necesitamos poner estos ficheros accesibles en la red, por eso debemos copiarlos en el área public_html\classes.

Como el stub de ComputeEngine implementa el interface Compute, que referencia al interface Task, también necesitamos poner estas clases disponibles en la red. Por eso, el paso final es desempaquetar el fichero compute.jar en el directorio c:\home\ann\public_html\classes para hacer que los interfaces Compute y Task estén disponibles para su descarga.


Detalles Específicos de la Plataforma: Desempaquetar el Fichero JAR

Windows:

cd c:\home\ana\public_html\classes
jar xvf compute.jar

Unix:

cd /home/ana/public_html/classes
jar xvf compute.jar

El comando jar muestra esta salida:

created: META-INF/
extracted: META-INF/MANIFEST.MF
extracted: compute/Compute.class
extracted: compute/Task.class

Construir las clases del Cliente

Asumamos que el usuario jones ha creado el código del cliente en el directorio c:\home\jones\src\client y colocará la clase Pi (para que sea descargada por el motor de cálculo) en el directorio accesible a la red c:\home\jones\public_html\classes (también disponible mediante algunos servidores como http://host/~jones/classes/). Las dos clases del lado del cliente están contenidas en los ficheros Pi.java y ComputePi.java en el subdirectorio client.

Para construir el código del cliente, necesitamos el fichero compute.jar que contiene los interfaces Compute y Task que utiliza el cliente. Digamos que el fichero compute.jar está situado en c:\home\jones\public_html\classes. Las clases del cliente se pueden construir así:


Detalles Específicos de la Plataforma: Compilar el Cliente

Windows:

set CLASSPATH=c:\home\jones\src;c:\home\jones\public_html\classes\compute.jar
cd c:\home\jones\src
javac client\ComputePi.java
javac -d c:\home\jones\public_html\classes client\Pi.java

UNIX:

setenv CLASSPATH /home/jones/src:/home/jones/public_html/classes/compute.jar
cd /home/jones/src
javac client/ComputePi.java
javac -d /home/jones/public_html/classes client/Pi.java

Sólo necesitamos situar la clase Pi en el directorio public_html\classes\client (el directorio client lo crea el javac si no existe). Esto es así por esta clase es la única que necesita ser desacargada por la máquina virtual del motor de cálculo.

Ahora podemos ejecutar el servidor y luego el cliente.


Ozito