Helloworld • Un servicio de saludos (helloworld): – Recibe: Hello world versión Jini • Un string (ejemplo: ‘Juan’) • Una constante que define el idioma (ejemplo: francés) – Retorna [email protected] • Un string que saluda en el idioma seleccionado (ejemplo: ‘Bonjour Juan’) Departamento de Ciencias de la Computación Universidad de Chile Tecnología Intranet Helloworld • 2 Helloworld • El cliente Jini: Activación y funcionamiento del servicio: – Realiza un búsqueda de los lookup service disponible en la red 1. Busca un lugar para publicarse: el lookup service 2. Se realiza un búsqueda por multicast 3. Por cada lookup service encontrado, publica un proxy que implementa la interfaz de programación – La búsqueda es realizada mediante unicast (primer ejemplo) y multicast (segundo ejemplo) (HelloInterface) • – Por cada lookup service encontrado, se busca el servicio que implementa una interfaz de programación (HelloInterface) Para la comunicación, entre el proxy y el servicio, se usa RMI (remote method invocation) Tecnología Intranet 3 Tecnología Intranet Helloworld: Las clases Servicio Main Interfaz HelloInterface RMIServer Jini en Cli Cliente Main te 5 patrón de búsqueda lookup 7 4 copia del proxy Client RMIHelloImpl JiniUnicastClient RMIJiniServer JiniMulticastClient 6 8 proxy 2 3 1 Serv icio (RunnableClient) Tecnología Intranet 4 5 Tecnología Intranet 6 1 Servicio Jini (interfaz) Servicio Jini (interfaz) package hello.common; • La interfaz de programación // La interfaz de programación usada // por el cliente y el servicio public interface HelloInterface public interface HelloInterface { • Es parte de un paquete java public static int frances = 1; public static int ingles = 2; public static int espanol = 3; /** * @param message el texto que es pasado el servicio * @param idioma el idioma de saludo * @return Una saludo en el idioma señalado */ package hello.common; • Contiene único método: public String sayHello(String mensaje, int idioma) • Como la comunicación será hecha a través de RMI, este método genera un excepción de tipo remota: public String sayHello(String mensaje, int idioma) throws java.rmi.RemoteException public String sayHello(String mensaje, int idioma) throws java.rmi.RemoteException; } Tecnología Intranet 7 Tecnología Intranet Servicio Jini (interfaz RMI) • • Servicio Jini (main) • • Es necesario extender la interfaz para ser usada bajo RMI Esta extensión no requiere nuevos métodos package hello.server; import java.rmi.Remote; import hello.common.HelloInterface; public interface RMIServer extends HelloInterface, Remote { // Ok para el acceso por RMI } Tecnología Intranet 9 Servicio Jini (implementación 01/02) package hello.server; import java.lang.SecurityException; import java.net.InetAddress; import java.net.UnknownHostException; import java.rmi.server.UnicastRemoteObject; import hello.server.RMIServer; public class RMIHelloImpl extends UnicastRemoteObject implements RMIServer { // El constructor sin parámetros usado por RMI public RMIServerImpl() throws java.rmi.RemoteException { } // sigue... Tecnología Intranet 8 11 Main: Una clase de inicialización Realiza una instanciación del servidor que instalará el servicio package hello.server; import hello.server.RMIJiniServer; public class Main { public static void main(String argv[]) { // Activación del servicio new RMIJiniServer(); } } Tecnología Intranet 10 Servicio Jini (implementación 02/02) // continuación… // La implementación de la interfaz hello.common.HelloInterface public String sayHello(String mensaje, int idioma) throws java.rmi.RemoteException { String text = "Hello "; switch (idioma) { case RMIServer.ingles: text = "hello "; break; case RMIServer.france: text = “bonjour "; break; case RMIServer.espanol: text = "hola "; break; } text = text + mensaje; System.out.println("> " + this.getClass().getName() + ": sayHello(): Sending= " + text); return text; } } // fin implementación Tecnología Intranet 12 2 Servicio Jini (publicación 01/06 Jini package hello.server; import…; import java.io.*; import hello.server.RMIServerImpl; public class RMIJiniServer implements DiscoveryListener // para escuchar los lookup encontrados LeaseListener // Para ser advertido de una falla en la reinscripción { private LeaseRenewalManager leaseManager = new LeaseRenewalManager(); private ServiceID serviceID = null; private RMIServerImpl rmiServerImpl = null; public RMIJiniServer() { try { rmiServerImpl = new RMIServerImpl(); } e ent Cli lookup multicast 1 Serv icio catch (java.rmi.RemoteException re) { System.err.println("Error: " + this.getClass().getName() + ": JiniServer(): " + re.toString()); System.exit(1); } Tecnología Intranet 13 Tecnología Intranet Servicio Jini (publicación 02/06) 14 Jini //… en Cli System.setSecurityManager(new RMISecurityManager()); LookupDiscovery discover = null; try { te lookup discover = new LookupDiscovery(LookupDiscovery.ALL_GROUPS); } catch(Exception e) { System.err.println("Discovery failed " + e.toString()); System.exit(1); } 3 // Se inscribe para ser advertido de los lookup service discover.addDiscoveryListener(this); } // Fin del constructor RMIJiniServer Tecnología Intranet 15 Tecnología Intranet 16 Servicio Jini (publicación 04/06) public void discovered(DiscoveryEvent evt) { // se carga el ID del servicio (puede no existir ==> null) ServiceID serviceID = loadServiceID(); ServiceRegistrar[] registrars = evt.getRegistrars(); // Para cada uno de los lookup encontrados... for (int i = 0; i < registrars.length; i++) { ServiceItem item = new ServiceItem(serviceID, // ID del servicio rmiHelloImpl, // el proxy null); // arreglo de Entry ServiceRegistrar registrar = registrars[i]; ServiceRegistration reg = null; try { // Se registra el servicio reg = registrar.register(item, Lease.FOREVER); } //… catch(java.rmi.RemoteException e) { System.err.println("Error: " + ":discovered(): Register exception: " + e.toString()); continue; } Tecnología Intranet 1 Serv icio Servicio Jini (publicación 03/06) // ... proxy 2 17 System.out.println("discovered(): Service registered with id= " + reg.getServiceID()); // Solicita una inscripción infinita con el lookup service leaseManager.renewUntil(reg.getLease(), Lease.FOREVER, this); // Se graba el servicio ID if (serviceID == null) { // Se recupera el ID asignado al servicio serviceID = reg.getServiceID(); // se graba en un archivo. Es un método privado de esta clase saveServiceID(serviceID); } } // fin del for } // fin del método discovered // ... Tecnología Intranet 18 3 Servicio Jini (publicación 05/06) Servicio Jini (publicación 06/06) // … public void discarded(DiscoveryEvent evt) { } // Aquí se debería tomar la medidas por problemas // con la reinscripción public void notify(LeaseRenewalEvent evt) { System.out.println("Lease expired " + evt.toString()); } //... Tecnología Intranet // Los metodos privados private ServiceID loadServiceID() { ServiceID serviceID = null; try { DataInput din = new DataInputStream(new FileInputStream("Classifier.id")); serviceID = new ServiceID(din); } catch(Exception e) { } // error ignorado return serviceID; } private void saveServiceID(ServiceID serviceID) ´{ // Se intenta almacenar en un archivo try { DataOutputStream dout = new DataOutputStream( new FileOutputStream("Classifier.id")); serviceID.writeBytes(dout); dout.flush(); } catch(Exception e) { } // error ignorado 19 } } // fin de la clase RMIJiniServer Cliente Jini: main package hello.client; import hello.client.JiniUnicastClient; import hello.client.JiniMulticastClient; • Acepta tres parámetros de entrada: class Main { /** * @param argv[0] un texto que será enviado * y retornado por el servidor * @param argv[1] el idioma de saludo. * @param argv[2] la dirección del lookup service. * Si argv.length es 2, se crea un cliente multicast. * Ejemplo de una dirección de lookup service: * jini://lookup.jini.com */ – 1er parámetro: un texto – 2do parámetro: el idioma, señalado por un entero (1, 2, 3) – 3er parámetro: dirección del lookup service (jini://lookup.jini.com). Es opcional. • Con 2 parámetros se activa una búsqueda multicast del lookup • Con 3 parámetros la búsqueda es unicast 21 Tecnología Intranet Cliente Jini (main 02/03) 22 Cliente Jini (main 03/03) // … public static void main(String[] argv) { if (argv.length == 3) { JiniUnicastClient jiniUnicastClient = new JiniUnicastClient(argv[0], Integer. parseInt(argv[1]), argv[2] ); } else if (argv.length == 2) { JiniMulticastClient jiniMulticastClient = new JiniMulticastClient(argv[0], Integer. parseInt(argv[1]) ); } else { … // Ups! Un error. } Tecnología Intranet 20 Cliente Jini (main 01/03) • Main: Una clase de entrada de la aplicación Tecnología Intranet Tecnología Intranet 23 //… // Se espera el tiempo suficiente // para recibir una respuesta try { Thread.currentThread().sleep(50000L); // 50 seg } catch(java.lang.InterruptedException e) { // nada se hace } } } // Fin de la clase Main Tecnología Intranet 24 4 Cliente Jini (client 01/02) Cliente Jini (client 02/02) • La clase Client: // ... public void writeMessage(String mensaje, int idioma) { try { String text = service.sayHello(mensaje, idioma); – Recibe una instancia que haya implementado la interfaz HelloInterface package hello.client; import hello.common.HelloInterface; } public class Client { private HelloInterface service = null; public Client(HelloInterface service) { this.service = service; } //... System.out.println("> " + this.getClass().getName() + ": writeMessage(): " + text); catch(java.rmi.RemoteException e) { } System.err.println("Error: " + this.getClass().getName() + ": run(): " + e.toString()); } } // Fin de la clase Client Tecnología Intranet 25 Tecnología Intranet Jini: Cliente versión Unicast en Cli 26 Cliente Jini (unicast 01/04) package hello.client; te 5 import … ; import hello.common.HelloInterface; import hello.client.Client; lookup public class JiniUnicastClient { 4 public JiniUnicastClient(String mensaje, int idioma, String jiniServerName) { LookupLocator lookup = null; try { // Para localizar el Lookup service lookup = new LookupLocator(jiniServerName); } proxy 3 catch (java.net.MalformedURLException mue) { System.err.println("Error: " + this.getClass().getName() + ": JiniUnicastClient()1: " + mue); System.exit(1); } Serv icio Tecnología Intranet 27 Tecnología Intranet Cliente Jini (unicast 02/04) Jini //… System.setSecurityManager(new RMISecurityManager()); en Cli ServiceRegistrar registrar = null; try { // Se recupera la interface del lookup service registrar = lookup.getRegistrar(); } catch (java.io.IOException ioe) { System.err.println("Error: " + this.getClass().getName() + ": JiniUnicastClient()2: " + ioe); System.exit(1); } catch (java.lang.ClassNotFoundException cnfe) { System.err.println("Error: " + this.getClass().getName() + ": JiniUnicastClient()3: " + cnfe); System.exit(1); } //... Tecnología Intranet 28 patrón de búsqueda te lookup 7 copia del proxy 6 proxy 3 Serv icio 29 Tecnología Intranet 30 5 Cliente Jini (unicast03/04) Jini // … // La interface del servicio que se desea buscar Class [] classes = new Class[] {HelloInterface.class}; // Se prepara el template para buscar el servicio ServiceTemplate template = new ServiceTemplate(null, // ID del servicio. 128 bits. classes, // La interfaz buscada null); // Un arreglo de Entry. Service service = null; try { service = (HelloInterface) registrar.lookup(template); } e ent Cli lookup copia del proxy Tecnología Intranet Serv icio 31 Tecnología Intranet Cliente Jini (unicast 04/04) en Cli if (service == null) { System.err.println("Error: " + this.getClass().getName() + ": discovered(): service not found"); System.exit(1); } else { System.out.println("> :" + this.getClass().getName() + ": The service was found!"); Client client = new Client(service); client.writeMessage(mensaje, idioma); } } // Fin del constructor JiniUnicastClient } // Fin de la clase JiniUnicastClient te lookup multicast 4 proxy 3 Serv icio 33 Tecnología Intranet Cliente Jini (multicast 01/03) 34 Cliente Jini (multicast 02/03) //… package hello.client; public void discovered(DiscoveryEvent evt) { import … ; import hello.common.HelloInterface; import hello.client.Client; // La interface del servicio que se desea buscar Class [] classes = new Class[] {HelloInterface.class}; // Se prepara el template para buscar el servicio ServiceTemplate template = new ServiceTemplate(null, // ID del servicio. 128 bits. classes, // La interfaz buscada null); // Un arreglo de Entry. HelloInterface service = null; // Se recupera la interface de los lookup service ServiceRegistrar[] registrars = evt.getRegistrars(); for (int i = 0; i < registrars.length && service == null; i++) { ServiceRegistrar registrar = registrars[i]; try { // se busca el servicio dentro de este lookup service public class JiniMulticastClient implements DiscoveryListener { private String mensaje; private int idioma; public JiniMulticastClient(String mensaje, int idioma) { this. mensaje = mensaje; this.idioma = idioma; System.setSecurityManager(new RMISecurityManager()); LookupDiscovery discover = null; try { discover = new LookupDiscovery(LookupDiscovery.ALL_GROUPS); } catch(Exception e) { System.err.println("Error: " + this.getClass().getName() + ": JiniMulticastClient(): " + e.toString()); System.exit(1); } } 32 Jini: cliente versión Multicast // … Tecnología Intranet proxy 3 catch(java.rmi.RemoteException e) { service = null; e.printStackTrace(); System.exit(1); } //... 8 // Se pone a la escucha de los lookup service que hay en la red discover.addDiscoveryListener(this); Tecnología Intranet 35 } } service = (HelloInterface) registrar.lookup(template); catch(java.rmi.RemoteException e) { service = null; System.err.println("Error: " + this.getClass().getName() + ": discovered(): " + e.toString()); continue; } // end for Tecnología Intranet 36 6 Cliente Jini (multicast 03/03) //… Cliente Jini Multicast: Corrección if (service == null) { if (service == null) System.err.println("Error: " + this.getClass().getName() + ": discovered(): service not found"); { System.err.println("Error: " + this.getClass().getName() + ": discovered(): service not found"); } } else { else { System.out.println("> :" + this.getClass().getName() + ": discovered(): The service was found!"); System.out.println("> :" + this.getClass().getName() + ": discovered(): The service was found!"); Client client = new Client(service); client.writeMessage(mensaje, idioma); } } // Fin método discovered Puede quedar bloqueado public void discarded(DiscoveryEvent evt) { // empty } } // Fin de la clase JiniMulticastClient Tecnología Intranet RunnableClient client = new RunnableClient(service, mensaje, idioma); new Thread(client).start(); } } public void discarded(DiscoveryEvent evt) { // empty } 37 } // Fin de la clase JiniMulticastClient Tecnología Intranet Cliente Jini RunnableClient (01/02) Cliente Jini RunnableClient (02/02) package hello.client; public void run() { writeMessage(mensaje, idioma); } import hello.common.HelloInterface; public class RunnableClient implements Runnable { private HelloInterface service = null; private String mensaje; private int idioma; public void writeMessage(String mensaje, int idioma) { try { String text = service.sayHello(mensaje, idioma); System.out.println("> " + this.getClass().getName() + ":writeMessage(): " + text); } catch(java.rmi.RemoteException e) { System.err.println("Error: writeMessage(): " + e.toString()); } } public RunnableClient(HelloInterface service, String message, int idioma) { this.service = service; this. mensaje = mensaje; this.idioma = idioma; } Tecnología Intranet 38 39 Compilación del cliente } Tecnología Intranet 40 Compilación del servicio @echo off @echo off set JINIHOME=C:\Program Files\jini1_1 set JINILIB=%JINIHOME%\lib\jinicore.jar;%JINIHOME%\lib\jini-ext.jar% set CLASSPATH=-classpath ".;..;..\..;%JINILIB%" set JINIHOME=C:\Program Files\jini1_1 set JINILIB=%JINIHOME%\lib\jini core.jar;%JINIHOME%\lib\jini-ext.jar% set CLASSPATH=-classpath ".;..;..\..;%JINILIB%" @echo on cd src\hello\server javac %CLASSPATH% *.java cd ..\..\.. @echo on cd src\hello\client javac %CLASSPATH% *.java cd ..\..\.. Tecnología Intranet 41 Tecnología Intranet 42 7 RMIC Jar @echo off cd src set BASEDIRECTORY=.;.. set CLASS01=hello\common\HelloInterface.class set CLASS02=hello\server\RMIServerImpl_Stub.class jar -cvf server.jar %CLASS01% %CLASS02% set CLASSPATH=-classpath "%BASEDIRECTORY%" @echo on cd src rmic -v1.2 -d . %CLASSPATH% hello.server.RMIServerImpl cd .. Tecnología Intranet copy server.jar D:\Apache\service-dl\helloworld\server.jar cd .. 43 Tecnología Intranet Activando el servicio 44 Activando el cliente @echo off @echo off set JINIHOME=C:\Program Files\jini1_1 set JINILIB=%JINIHOME%\lib\jini-core.jar;%JINIHOME%\lib\jini-ext.jar% set CLASSPATH=-classpath ".;.\src;%JINILIB%" set JINIHOME=C:\Program Files\jini1_ set JINILIB=%JINIHOME%\lib\jini-core.jar;%JINIHOME%\lib\jini-ext.jar% set POLICY=-Djava.security.policy=policy.all set CLASSPATH=-classpath ".;.\src;%JINILIB%" set JARFILEINWEBSERVER=http://leon/service-dl/helloworld/server.jar set RMISERVER=-java.rmi.server.codebase=%JARFILEINWEBSERVER% set POLICY=-Djava.security.policy=policy.all @echo on java %CLASSPATH% %POLICY% hello.client.Main %1 %2 %3 @echo on java %CLASSPATH% %POLICY% %RMISERVER% hello.server.Main Tecnología Intranet 45 Tecnología Intranet 46 8