RESUMEN PARA CREAR UNA APLICACIÓN RMI

 

1.- Crear la interfaz remota RMI, la cual “describe” la lógica del negocio. La interfaz remota DEBE SER CONOCIDA tanto por el cliente RMI como por el servidor RMI.

 

package ejsRMI;

import java.rmi.*;

public interface GestorBilletes extends Remote

{

  public static final int numPuerto=1099; // Puerto por defecto para RMI 

  public int getBillete(String nom) throws RemoteException;

}

 

2.- Implementar la lógica del negocio: el servidor RMI que implementa la interfaz remota

 

package ejsRMI;

import java.rmi.*;

import java.sql.*;

import java.io.*;

import ejsRMI.GestorBilletes;

import java.rmi.server.UnicastRemoteObject;

import java.util.*;

public class ServidorGestorBilletesBD

        extends UnicastRemoteObject

        implements GestorBilletes

{       private static  Connection conexion;

        private static  Statement sentencia;

        public ServidorGestorBilletesBD() throws RemoteException{

        try {

        Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

        conexion=DriverManager.getConnection("jdbc:odbc:Billetes");

        conexion.setAutoCommit(false);

        sentencia=conexion.createStatement();

        }

        catch(Exception e)

          { System.out.println("Se ha producido un error:"+e.toString());}

        }

        public int getBillete(String nom)

          throws RemoteException {

          // Devuelve nº billete, -1 si no hay, -2 si hay problemas

          String pregSQL = "SELECT NUMERO FROM BILLETES"+

                          " WHERE ESTADO='LIBRE'";

          try{ ResultSet rs = sentencia.executeQuery(pregSQL);

            if (rs.next()) {

                String num = rs.getString("NUMERO");

                int act = sentencia.executeUpdate("UPDATE BILLETES"+

                                " SET ESTADO='OCUPADO', NOMBRE = '"+nom+

                                "' WHERE NUMERO="+num+" AND ESTADO='LIBRE'");

                conexion.commit();

              int n= Integer.parseInt(num);

              if (act>0) return n; // Núm. billete asignado

              return -2; } // Otro ya ha OCUPADO ese billete

            else return -1; } // No había ninguno libre

          catch (SQLException e)

              {System.out.println("Error: "+e.toString());}

          return -2; // Que prueben otra vez a llamar

}

public static void main(String[] args) {

       // CONTINUA

}

 

3.- Lanzar el servidor de nombres (rmiregistry), registrar el servidor RMI en el rmiregistry y establecer el gestor de seguridad de RMI.

 

public static void main(String[] args) { // Por ej. en el main del servidor RMI

        int numPuerto = GestorBilletes.numPuerto;

              // Usamos el puerto por defecto (1099)   

        System.setSecurityManager(new RMISecurityManager());

        try { java.rmi.registry.LocateRegistry.createRegistry(numPuerto);

                // Crear RMIREGISTRY

        } catch (Exception e)

              {System.out.println(e.toString()+"Rmiregistry estaba lanzado.");}

        try {

        ServidorGestorBilletesBD objetoServidor =

                new ServidorGestorBilletesBD();

        String maquina = "//localhost"+":"+numPuerto; 

                 // Sólo se puede hacer registrar en el localhost                                          

       String servicio = "/gestorBilletes";          

        String servicioRemoto = maquina+servicio;

        // Registrar el servicio remoto

        Naming.rebind(servicioRemoto,objetoServidor);

        }catch (Exception e)

         {System.out.println("Error al lanzar el servidor: "+e.toString());}}}

 

 

4.- Definir el cliente RMI (un Frame o un Applet), que obtiene la lógica del negocio (probablemente en el constructor de la clase) y la almacena en una variable cuyo tipo es la interfaz remota. También establece el gestor de seguridad de RMI.

 

    try

    {

       GestorBilletes gestorBilletes;

        String servicio = "/gestorBilletes";

 

      System.setSecurityManager(new RMISecurityManager());

      int numPuerto = ejsRMI.GestorBilletes.numPuerto;

      String maquina = “URL DEL SERVIDOR O BIEN localhost”;

    

gestorBilletes =

        (GestorBilletes)Naming.lookup("rmi://"+maquina+":"+numPuerto+servicio);

    }

    catch(Exception e) {…}

 

y la utiliza (probablemente en algún método de atención a un evento)

 

  void jButton1_actionPerformed(ActionEvent e)

  {

    try {

        String nombre = jTextField1.getText();

        int res = gestorBilletes.getBillete(nombre);

        if (res>0) jTextArea1.append("Asignado. \nReferencia: "+res+"\n");

        else if (res==-1) jTextArea1.append("No hay billetes libres\n");

        else if (res==-2) jTextArea1.append("Error: Inténtelo otra vez.\n");

    }

    catch (Exception ex) {jTextArea1.append("Error: "+ex.toString()+"\n");}

  }


5.- Crear los STUB a partir de la clase servidora RMI

 

A continuación se muestra el contenido de un fichero de comandos (crearStubs.bat) que crea el stub y skeleton (y los deja en un directorio del CLASSPATH del cliente y del servidor) para el ejemplo anterior donde:

 

a) ejsRMI.ServidorGestorBilletesBD es la clase servidora RMI (hay que llamarla anteponiendo el nombre del paquete ejsRMI al de la clase ServidorGestorBilletesBD)

 

b) E:\jdev9i es el directorio donde se encuentra el JDeveloper 9i. El compilador de rmi (rmic) se encuentra en el subdirectorio jdk1.3\bin

 

c) E:\alfredo\EjsJava\jdev9\classes es el directorio a partir de donde el compilador de rmi va a encontrar la clase servidora RMI ejsRMI.ServidorGestorBilletesBD, y también es el directorio donde se van a escribir los ficheros STUB y SKELETON: ejsRMI.ServidorGestorBilletesBD_Stub y ejsRMI.ServidorGestorBilletesBD_Skel. Hay que tener en cuenta que el directorio exacto donde se encontrarán las clases servidora RMI, STUB y SKELETON será E:\alfredo\EjsJava\jdev9\classes\ejsRMI: se añade el subdirectorio ejsRMI por ser el paquete donde se encuentran las clases.

 

crearStubs.bat

 

@echo off

echo Ejecutando el compilador de RMI (rmic)...

echo -----------

echo El formato del comando es el siguiente:

echo RMIC -classpath DIRCLASSPATH -d DIRSTUBS SERVIDOR_RMI

echo -----------

echo RMIC es la ruta donde se encuentra el rmic

echo DIRCLASSPATH es el directorio raíz donde se encuentra la clase servidora RMI

echo DIRSTUBS es el directorio donde va a escribirse el stub y el skeleton

echo SERVIDOR_RMI es el nombre de la clase servidora RMI (incluyendo el paquete)

echo -----------

echo on

"E:\jdev9i\jdk1.3\bin\rmic" -classpath E:\alfredo\EjsJava\jdev9\classes -d E:\alfredo\EjsJava\jdev9\classes ejsRMI.ServidorGestorBilletesBD

 

 

6.- Crear el fichero con la política de carga de clases desde otras máquinas virtuales y, definir la opción Java para que al ejecutar el servidor RMI y el cliente RMI se utilice.

 

Contenido del fichero: E:\alfredo\ejsJava\jdev9\ejsRMI\java.policy

 

grant {

permission java.security.AllPermission;

};

 

 Añadir la opción Djava.security.policy= «nombre del fichero de política de seguridad” en las propiedades del proyecto:

 

 

NOTA: no dejar espacios en blanco en Djava.security.policy=nombreFichero. Si el nombre del fichero contiene espacios en blanco, entonces ponerlo entre comillas.

 

7.- Los parámetros definidos en métodos remotos y los resultados devueltos por los mismos deben ser siempre de clases SERIALIZABLES.

 

Si la interfaz fuera esta:

 

 package ejsRMI;

import java.rmi.*;

public interface GestorBilletes extends Remote

{

  public static final int numPuerto=1099; // Puerto por defecto para RMI 

  public Billete getBillete(Persona per) throws RemoteException;

 

entonces ambas clases tendrían que ser serializables.

 

...

import java.io.Serializable;

public class Persona implements Serializable

{  ... }

y

...

import java.io.Serializable;

public class Billete implements Serializable

{  ... }

 

 

8.- ¿Dónde colocar los STUBS?

 

Una vez creados, si se copian en el CLASSPATH del cliente NO HAY PROBLEMA

 

Existe la posibilidad de que el cliente obtenga los stubs de manera dinámica, usando la propiedad codebase al llamar al cliente. Si el STUB y la INTERFAZ REMOTA se han dejado en la url http://ji.ehu.es/iso/stubs/, entonces hay que pasar a la máquina virtual java que ejecuta el cliente la opción:

-Djava.rmi.server.codebase=http://ji.ehu.es/iso/stubs/

NOTA: Aseguraros de que la URL termina con el carácter /