Java RMI I lucidi che seguono sono stati prodotti sulla base dei seguenti riferimenti: - Sistemi Distribuiti Dip. Informatica Università di Bari (S.Pizzutilo) - Seminario Java RMI di G.Cozzolongo Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Java RMI: Remote Method Invocation Java Remote Method Invocation (RMI) è l’implementazione Java del modello ad oggetti distribuiti E’ un meccanismo che consente ad un oggetto su un JVM di invocare metodi di oggetti residenti in altre JVM La sintassi per le invocazioni remote è esattamente la stessa di quella delle invocazioni locali Possono essere passati argomenti, calcolati nel contesto della macchina chiamante Possono essere restituiti valori, calcolati nel contesto della macchina remota Gli elementi chiave sono serializzazione e dynamic class loading Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Remote Method Invocation Perche RMI? L’obiettivo è di permettere ad una applicazione in esecuzione su una macchina locale di invocare i metodi di un oggetto in esecuzione su un altro computer. Si definisce client il programma chiamante che ottiene riferimento all’oggetto remoto, server il programma che crea gli oggetti remoti. Tali applicazioni sono anche denominate distributed object application Quali vantaggi? • miglioramento delle prestazione complessive • semplicità nella gestione delle risorse distribuite • incremento della potenza operativa es: suddivisione di una computazione pesante in procedure più piccole, eseguite tutte su macchine diverse diminuendo in tal modo il tempo Sistemi Distribuiti Multiagente complessivo di esecuzione A.A.2010-11 Informatica Magistrale Università di Bari 1 Terminologia di base Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Semantica invocazioni remote • La semantica delle invocazioni remote non è uguale pero a quella delle locali... • Infatti, i tipi primitivi (int, float,...) sono sempre passati per valore (semantica Call By Value, CBV) • Il chiamato lavora una copia del tipo • Gli oggetti remoti sono sempre passati per riferimento (Call By Reference, CBR) • Il chiamato riceve un riferimento all’oggetto Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Semantica invocazioni remote Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari 2 Interface Definition Language Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Architettura dell’RMI Client Server (Interfaccia) (Implementazione) Stub Skeleton Remote Reference Layer Remote Reference Layer Transport Layer (Connessione TCP/IP) Un client è dotato dell'interfaccia dei metodi disponibili sul server remoto, ma tutta l'implementazione è lasciata sul lato server. Nel programma client i dettagli dell'implementazione dei metodi remoti sono quindi invisibili. Ciò che realmente collega il client e il server in un sistema RMI è una connessione stratificata, trasparente agli sviluppatori, effettuata dal sottosistema RMI delle due macchine virtuali coinvolte. Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Componenti base dell’RMI Stub: proxy locale su cui vengono fatte le invocazioni destinate all’oggetto remoto Skeleton: elemento remoto che riceve le invocazioni fatte sullo stub e le realizza effettuando le corrispondenti chiamate sul server (ormai solo per back compatibility) Remote Reference Layer:- -fornisce il supporto alle chiamate inoltrate dallo stub definisce e supporta la semantica dell’invocazione e della comunicazione Transport Layer: localizza il server RMI relativo all’oggetto remoto richiesto, gestisce le connessioni (TCP/IP, timeout) e le trasmissioni (sequenziali, serializzate), usando Java Remote Method Protocol (JRMP). Registry: servizio di naming che consente al server di pubblicare un servizio e al client di recuperarne il proxy Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari 3 The Stub and Skeleton A client invokes a remote method, the call is first forwarded to stub. The stub is responsible for sending the remote call over to the server-side skeleton The stub opening a socket to the remote server, marshaling the object parameters and forwarding the data stream to the skeleton. A skeleton contains a method that receives the remote calls, unmarshals the parameters, and invokes the actual remote object implementation. Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari The General RMI Architecture The server must first bind its name to the registry The client lookup the server name in the registry to establish remote references. The Stub serializing the parameters to skeleton, the skeleton invoking the remote method and serializing the result back to the stub. Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari The General RMI Architecture Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari 4 Architettura di RMI La struttura di un’applicazione RMI è organizzata in strati orizzontali sovrapposti RMI Client Simulazione locale sul client Java Virtual Machine Skeleton Stubs Remote Reference Layer Connessione virtuale Transport Layer RMI Server Connessione fisica Oggetto reale eseguito sul server Remote Reference Layer Transport Layer Il primo livello di questa connessione stratificata è rappresentato dagli stub (lato client) e gli skeleton (loto server) ai quali si riferiscono rispettivamente il client e il server senza occuparsi di ulteriori dettagli di più basso livello. A loro volta, gli stub e gli skeleton demandano l'esecuzione di ciascuna attività allo strato immediatamente sottostante: il remote reference layer (RRL) che gestisce i riferimenti delle variabili agli oggetti remoti, usando la connessione TCP/IP del Transport layer sottostante. Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Architettura di RMI Lo strato più alto è costituito da applicazioni (client e server) eseguite dalla Java Virtual Machine. Lo stub e lo skeleton forniscono la rappresentazione dell’oggetto remoto: lo stub gestisce la simulazione locale sul client e, agendo come proxy, consente la comunicazione con l’oggetto remoto; lo skeleton invece consente l’esecuzione dell’oggetto remoto sul server. Il client esegue i metodi dell’oggetto remoto in modo del tutto analogo alla chiamata locale: ris = OggettoRemoto.nomeMetodo(par1, par2,..) senza preoccuparsi dei dettagli della comunicazione. Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari La serializzazione Marshalling: processo di codifica di argomenti e risultati per la trasmissione. Unmarshalling: processo inverso di decodifica di argomenti e risultati ricevuti. In Java questo problema è risolto usando la serializzazione, che viene fatta in maniera trasparente dal supporto Serializzazione: trasformazione di oggetti complessi in semplici sequenze di byte=> metodo writeObject() su uno stream di output Deserializzazione: decodifica di una sequenza di byte e costruzione di una copia dell’oggetto originale=> metodo readObject() da uno stream di inputIn Java sono utilizzati in molti casi: per memoria anche esterna trasmissione tra macchine diverse(parametri e valori di ritorno in RMI) Esempio di storage http://lia.deis.unibo.it/Courses/cofimp/ Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari 5 La serializzazione Il meccanismo alla base utilizzato da RMI per la trasmissione dei dati fra client e server è quello della serializzazione che permette il flusso di dati complessi all’interno di stream (può venir usata indipendentemente da applicazioni RMI) • La serializzazione consiste nella trasformazione automatica di oggetti e strutture in sequenze di byte manipolabili coi vari stream del package java.io • Gli stream sono associabili sia a socket che a file es: Record record = new Record() ObjectOutputStream oos = new ObjectOutputStream(myos) oos.writeObject(record); Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari La serializzazione • Un oggetto è serializzabile se implementa l’interfaccia Serializable • Si possono serializzare oggetti con struttura e complessità arbitraria, senza particolari differenze, a patto che l’oggetto sia serializzabile (implementi cioè l’interfaccia Serializable) es: public class Record implements Serializable{ private String Nome; public Record(String Nome){this.Nome = Nome} } • La serializzazione è ricorsiva ( un oggetto serializzabile deve contenere oggetti serializzabili) • La maggior parte delle classi del JDK è serializzabile (eccetto alcune che adottano strutture dati binarie dipendenti dalla piattaforma) Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Passaggio parametri Shallow Copy vs. Deep Copy considerando un grafo di oggetti Passaggio per valore => Serializable Objects Passaggio per riferimento => Remote Objects Oggetti serializzabili: Oggetti la cui locazione non è rilevante per lo stato. Sono passati per valore: ne viene serializzata l’istanza che sarà deserializzata a destinazione per crearne una copia locale. Oggetti remoti: Oggetti la cui funzione è strettamente legata alla località in cui eseguono (server) Sono passati per riferimento: ne viene serializzato lo stub, creato automaticamente dal proxy (stub o skeleton) su cui viene fatta Sistemi Distribuiti Multiagente la chiamata in cui compaiono come parametri A.A.2010-11 Informatica Magistrale Università di Bari 6 Gli stub: quali azioni fanno? stub cliente: <ricerca del servitore> <marshalling argomenti> <send richiesta> <receive risposta> <unmarshallin grisultato> restituisci risultato fine stub cliente; stub servitore: <attesa della richiesta> <unmarshalling argomenti> invoca operazione locale ottieni risultato <marshalling del risultato> restituisci risultato fine stub servitore; In aggiunta, il controllo della operazione ed eventuali azioni di ritrasmissione (entro un tempo di durata massima) Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Stub e Skeleton Stub e Skeleton sono oggetti generati dal compilatore RMI che gestiscono marshalling/unmarshalling e comunicazione (socket) tra client e server Procedura di comunicazione: 1. 2. 3. Il client ottiene un’istanza dello stub Il client chiama metodi sullo stub Lo stub a. crea una connessione con lo skeleton (o ne usa una già esistente) b. marshalling delle informazioni associate alla chiamata (id del metodo e argomenti) c. invia le informazioni allo skeleton 4. Lo skeleton a. unmarshalling dei dati ricevuti b. effettua la chiamata sull’oggetto chei mplementa il server c. marshalling del valore di ritorno e invio allo stub 5. lo stub: - unmarshalling del valore di ritorno erestituzione del risultato al Sistemi Distribuiti Multiagente client A.A.2010-11 Informatica Magistrale Università di Bari Passaggio di parametri Qualsiasi classe, i cui oggetti devono essere trasmessi con una connessione RMI, deve essere dichiarata come tale indicando che deve implementare l'interfaccia java.io.Serializable. Ogni parametro passato o ritornato da un metodo remoto deve essere o un oggetto di una classe primitiva Java, o un tipo di dato primitivo oppure un oggetto che implementa l'interfaccia java.io.Serializable. Un client richiede al server un riferimento ad un oggetto usando lo stub sul lato client. Il server ottiene la richiesta dallo skeleton sul lato server. Tra i due c'è il remote reference layer che negozia le richieste convertendo gli oggetti in un formato trasmissibile attraverso la rete. Questa conversione è chiamata marshalling. Se i dati da trasmettere non sono né primitivi né serializzabili, lo stub lancerà un'eccezione MarshalException. Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari 7 Il passaggio dei parametri Percorso dei parametri Serializzati dalla Virtual Machine Inviati sotto forma di stream al server Deserializzati del server che li utilizza all’interno del corpo del metodo invocato Il risultato segue il percorso inverso fino ad arrivare al client Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Gli strati RRL e TL Si occupano della gestione “a basso livello” ( all’interno dell’architettura RMI) della comunicazione Il Remote Reference Layer (RRL) ha il compito di instaurare un connessione virtuale fra il client e il server ( esegue operazioni di codifica e decodifica dei dati). RRL adotta un protocollo generico e indipendente dal tipo di stub o skeleton utilizzato. Il Transport Layer esegue la connessione vera e propria tra le macchine utilizzando le specifiche standard di networking di Java, e quindi le socket con il protocollo TCP/IP. Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Il Transport Layer Il TL è responsabile del controllo dello stato delle vari connessioni I dati vengono visti come sequenze di byte da inviare o da leggere IL TL si incarica di localizzare il server RMI relativo all’oggetto remoto richiesto Esegue la connessione per mezzo di un socket Programmare con RMI Le classi e i metodi sono contenuti nei package java.rmi e java.rmi.server Si definisce oggetto remoto un oggetto che implementi l’interfaccia Remote i cui metodi possono essere eseguiti da un‘applicazione client posta su un’altra macchina virtuale Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari 8 Come trasformare un oggetto in un oggetto remoto? public class MyServer{ public String concat (String a, String b){ return a+b; } } public interface MyServerInterface extend Remote{ public String concat (String a, String b)throws RemoteException; } public class MyServerImpl implements MyServerInterface extends UnicastRemoteObject{ public MyServerImpl() throws RemoteException{} public String concat (String a, String b)throws RemoteException{ return a+b;} } Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Hello World con RMI: definire l’applicazione Di cosa ho bisogno? 1. Scrivere l’intefaccia dell’oggetto remoto : MessageWriter.java 2. Scrivere il server che implementa l’interfaccia e la rende accessibile : MessageWriterImpl.java da cui in seguito generare stub e skeleton 3. Scrivere il codice per la pubblicazione del server HelloServer.java 4. Scrivere il client che richiede l’accesso all’oggetto remoto : HelloClient.java una volta definite le classi posso passare alla compilazione e posso lanciare la mia applicazione RMI… Sistemi distribuiti A.A.2006-07 Informatica specialistica – Università di Bari Lanciare l’applicazione RMI Una volta definite le classi (interfaccia, server, registrazione e client) posso compilare e lanciare il mio codice RMI. Passi necessari: 5. Compilazione dei file .java 6. Generazione di stub e skeleton tramite il compilatore rmic 7. Avvio dell’RMI registry 8. Avvio dell’oggetto remoto (server) 9. Avvio del client Sistemi distribuiti A.A.2006-07 Informatica specialistica – Università di Bari 9 Hello World (1) Scrivere l’intefaccia dell’oggetto remoto : MessageWriter.java L’interfaccia remota deve dichiarare tutti i metodi che si vuole poter richiamare in maniera remota deve essere dichiarata public deve estendere l’interfaccia java.rmi.Remote ogni metodo deve dichiarare java.rmi.RemoteException nella sezione throws per proteggere l’applicazione da anomalie derivanti dall’utilizzo di risorse remote //l’interfaccia dell’oggetto remoto import java.rmi.*; public interface MessageWriter extends Remote { String writeMessage(String s) throws RemoteException; } Sistemi distribuiti A.A.2006-07 Informatica specialistica – Università di Bari Hello World: (2) Scrivere il server (oggetto remoto) MessageWriterImpl.java deve implementare almeno un’interfaccia remota deve definire i costruttori dell’oggetto remoto deve fornire l’implementazione dei metodi invocati da remoto creare e installare il security manager creare una o più istanza dell’oggetto Sistemi distribuiti A.A.2006-07 Informatica specialistica – Università di Bari Implementare l’interfaccia remota public class MessageWriterImpl extends UnicastRemoteObject implements MessageWriter { … } • dichiara che implementa l’intefaccia MessageWriter ( con tutti i sui metodi) • estende la classe UnicastRemoteObject per consentire la creazione di un oggetto remoto che • adotta i protocolli di comunicazione di default di RMI basata sui socket e TCP • rimane costantemente attivo Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari 10 Definire i costruttori public MessageWriterImpl() throws RemoteException { super(); } il metodo super() chiama il costruttore della classe UnicastRemoteObject che esegue le inizializzazioni necessarie per consentire di rimanere in attesa (listen) di richieste remote su una porta e poterle gestire (accept) potrebbe generare l’eccezione RemoteException se la connessione non fosse possibile Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Implementazione dei metodi remoti public String writeMessage(String s) throws RemoteException { return (s + " Ho ricevuto la tua stringa"); } devono essere implementati tutti i metodi dell’interfaccia gli argomenti dei metodi e i risultati restituiti devono essere oggetti serializzabili Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Implementazione dell’oggetto remoto MessageWriterImpl.java import java.rmi.*; import java.rmi.server.*; public class MessageWriterImpl extends UnicastRemoteObject implements MessageWriter { public MessageWriterImpl() throws RemoteException { super(); } public String writeMessage(String s) throws RemoteException { return (s + " Ho ricevuto la tua stringa"); } } Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari 11 Il security manager Chi garantisce che il codice scaricato da remoto non esegua operazioni pericolose? if(System.getSecurityManager() == null){ System.setSecurityManager(new RMISecurityManager()); } Il metodo main deve creare e installare un security manager, che può essere il RMISecurityManager o definito in altro modo Il S.M. garantisce che le classi che vengono caricate non eseguano operazioni per le quali non siano abilitate se il S.M non è specificato non è permesso nessun caricamento di classi da parte sia del client ( stub ) che del server Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari HelloWorld (3) Scrivere il codice per la pubblicazione del server HelloServer.java import java.rmi.*; public class HelloServer { public static void main (String args[]) throws Exception { MessageWriterImpl messageWriter = new MessageWriterImpl(); Naming.rebind("myservice",messageWriter); //pubblicazione interfaccia } } Nel metodo main si devono creare una o più istanze dell’oggetto che fornisce il servizio (oggetto remoto) Una volta creato, l’oggetto è pronto per accettare richieste remote Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Registrare l’oggetto remoto Naming.rebind("myservice",messageWriter); Il client deve poter ottenere un riferimento all’oggetto remoto: RMI fornisce un registry degli oggetti per creare un’associazione (bind) fra un nome URL-formatted e un oggetto l’RMI registry è un name-service che consente ai client di ottenere riferimenti agli oggetti: una volta registrato l’oggetto i client possono farne richiesta attraverso il nome e invocarne i metodi nessun protocollo deve essere specificato nel primo argomento la porta di default su cui risponde il RMIregistry è la 1099, ma può essere cambiata Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari 12 Registrare l’oggetto remoto (2) Un applicazione puo’ creare un’associazione solo sul RMIregistry del host locale I client possono invece eseguire la propria ricerca di oggetti su qualunque host L’operazione di registrazione può generare varie eccezioni AlreadyBoundException, se il nome logico è gia utilizzato MalformedURLException, per errori nella sintassi dell’URL RemoteException negli altri casi Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari RMI Registry Problema di Bootstrapping: un client in esecuzione su un macchina ha bisogno di localizzare un server a cui vuole connettersi, che è in esecuzione su un’altra macchina. Tre possibili soluzioni: - Il client conosce in anticipo dov’è il server - L’utente dice all’applicazone client dov’è il server (es. e-mail client) - Un servizio standard (naming service) in una locazione ben nota, che il client conosce, funziona come punto di indirezione Java RMI utilizza un naming service: - RMI RegistryMantiene un insieme di coppie {name, reference} - Name: stringa arbitraria non interpretata Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari HelloWorld (4) Scrivere il client che richiede l’accesso all’oggetto remoto : HelloClient.java Deve ottenere un riferimento all’oggetto remoto che vuole richiamare dal RMIregistry eseguito sul server, utilizzando un’istanza dello stub a cui passare hostname ( ed eventualmente porta) e nome dell’oggetto MessageWriter myWriter = (MessageWriter) Naming.lookup("myservice"); Richiama i metodi dell’oggetto secondo la sintassi solita String newstring = new String (myWriter.writeMessage("Hello, world!")); System.out.println(newstring); Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari 13 // il client per richiamare l’oggetto remoto Hello import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.RMISecurityManager; import java.rmi.*; public class HelloClient { public static void main(String args[]) throws Exception { MessageWriter myWriter = (MessageWriter) Naming.lookup("myservice"); String newstring = new String (myWriter.writeMessage("Hello, world!")); System.out.println(newstring); } } Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari (5) Compilazione • Compilare i file .java col javac per creare i file .class. (6) Generazione di stub e skeleton • Generare stub e skeleton col comando rmic sul file che contiene l’implementazione dell’oggetto remoto (HelloImpl.class) rmic hello.MessageWriterImpl questo genera i file HelloImpl_Stub.class e HelloImpl_Skel.class NB: skeleton non è più in uso per le versioni della JVM successive alla 1.2 Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari (7) Avvio dell’RMI registry Lanciare in background RMIregistry col comando rmiregistry Questo processo utilizza per default la porta 1099 (8) Avvio dell’oggetto remoto Lanciare il server - java HelloServer (9) Avvio del client Lanciare il client - Java HelloClient Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari 14 Esempio: Calcolatrice con RMI Implementazione dell’interfaccia import java.rmi.Remote; import java.rmi.RemoteException; public interface CalcolatriceServer extends Remote { int addizione(int a, int b) throws RemoteException; int sottrazione(int a, int b) throws RemoteException; } Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Esempio: Calcolatrice con RMI Implementazione dell’oggetto remoto import java.rmi.*; import java.rmi.server.*; public class CalcolatriceServerImpl extends UnicastRemoteObject implements CalcolatriceServer { //implementazione del costruttore public CalcolatriceServerImpl() throws RemoteException{ super(); } //implementazione dei metodi public int addizione(int a, int b) throws RemoteException { return a + b; } public int sottrazione(int a, int b) throws RemoteException { return a - b; } Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari } Esempio: Calcolatrice con RMI Registrazione del server import java.rmi.Naming; import java.rmi.*; import java.rmi.server.*; public class Registrazione { public static void main(String args[]){ try { CalcolatriceServerImpl obj = new CalcolatriceServerImpl(); Naming.rebind("calcolatrice", obj); } catch (Exception e) { e.printStackTrace(); } } } Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari 15 Esempio: Calcolatrice con RMI Implementazione del Client import java.rmi.Naming; import java.rmi.RemoteException; public static int sceltaMenu(){ boolean valoreCorretto = true; int s = 0; import java.util.InputMismatchException; import java.util.Scanner; public class CalcolatriceClient { public static void main(String[] arg){ try { CalcolatriceServer obj = (CalcolatriceServer) Naming.lookup("rmi://127.0.0.1/calcolatrice"); int risultato = 0; int scelta = 0; do {scelta = sceltaMenu(); switch (scelta) { case 1: System.out.println("addizione"); risultato = obj.addizione(1, 1); System.out.println ("1 + 1 = " + risultato); break; case 2: System.out.println("sottrazione"); risultato = obj.sottrazione(1,1); System.out.println ("1 - 1 = " + risultato); do{ Scanner input = new Scanner(System.in); System.out.println("Inserisci la tua scelta"); System.out.println("1 = addizione"); System.out.println("2 = sottrazione"); System.out.println("0 = exit"); try { s=input.nextInt(); valoreCorretto = false;} catch (InputMismatchException inputMismatchException) {input.nextLine(); // discard input so user can try again System.out.println("Scelta non valida. Inserisci un intero.\n");} } while (valoreCorretto); return s; } } break; case 0: break; default: System.out.println("Errore, ripeti la scelta");break; } //end switch} while (scelta!= 0); } catch (Exception e) {e.printStackTrace();} } Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Esempio:Implementare un Compute Engine • Un compute engine è un oggetto remoto che consente ad un server di ricevere dei task dai client, eseguirli e restituire il risultato. • Il task viene definito dal client ma viene eseguito sulla macchina del server. • Il task può variare indipendentemente dal server, l’importante è che rispetti una determinata interfaccia • Il compute engine scarica dal client il codice del task e lo esegue all’interno della propria Java virtual machine Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Interfacce utilizzate Per implementare un compute engine servono due interfacce • L’interfaccia Compute, che consenta ai client di inviare task all’engine • L’interfaccia Task, che consenta all’engine di eseguire i task Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari 16 Interfaccia Compute package compute; import java.rmi.Remote; import java.rmi.RemoteException; public interface Compute extends Remote { Object executeTask(Task t) throws RemoteException; } Questa intefaccia definisce i metodi che possono essere chiamati da altre virtual machine. Gli oggetti che implementano questa interfaccia diventano oggetti remoti. Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Interfaccia Task package compute; import java.io.Serializable; public interface Task extends Serializable { Object execute(); } Questa interfaccia è usata come argomento nel metodo executeTask dell’interfaccia Compute (definito precedentemente) e fornisce al Compute Engine il meccanismo per eseguire il task. Non è un interfaccia remota, quindi non è associata ad oggetti remoti. Il metodo execute deve essere presente in ogni implementazione di questa interfaccia. Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Implementazione del Compute Engine //oggetto remoto per l’esecuzione dei task package engine; import java.rmi.*; import java.rmi.server.*; import compute.*; public class ComputeEngine extends UnicastRemoteObject implements Compute { public ComputeEngine() throws RemoteException { super(); } public Object executeTask(Task t) { return t.execute(); } // metodo main } Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari 17 Metodo main del ComputeEngine public static void main(String[] args) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } String name = "//host/Compute"; try { Compute engine = new ComputeEngine(); Naming.rebind(name, engine); System.out.println("ComputeEngine bound"); } catch (Exception e) { System.err.println("ComputeEngine exception: ” + e.getMessage()); } } Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Implementazione del client package client; import java.rmi.*; import java.math.*; import compute.*; public class ComputePi { public static void main(String args[]) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMIS...()); } try { String name = "//" + args[0] + "/Compute"; Compute comp = (Compute) Naming.lookup(name); Pi task = new Pi(Integer.parseInt(args[1])); BigDecimal pi = (BigDecimal) (comp.executeTask(task)); System.out.println(pi); } catch (Exception e) { System.err.println("ComputePi exception: " + e.getMessage()); Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale }}} Università di Bari Implementazione dell’interfaccia Task package client; import compute.*; import java.math.*; public class Pi implements Task { /** costante usata nel calcolo di pi */ private static final BigDecimal ZERO = BigDecimal.valueOf(0); /** ...... ...... **/ public Pi(int digits) { this.digits = digits; } /*** Calcola pi.*/ //Poiché implementa l’interfaccia Task deve esserci questo public Object execute() { return computePi(digits); } public static BigDecimal computePi(int digits) { ...... } Sistemi Distribuiti Multiagente } A.A.2010-11 Informatica Magistrale Università di Bari 18 Riassunto degli elementi necessari Due interfacce : compute.java task.java Il server che implementa l’interfaccia compute e comprende il metodo main per l’esecuzione: ComputeEngine.java L’implementazione del task da far eseguire: Pi.java Il client che richiede l’esezuzione del task al server: ComputePi.java In più vengono generati i file per lo stub e lo skeleton: ComputeEngine_stub.java ComputeEngine_skel.java Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Esercizio Provate a svolgere l’esercizio precedente (calcolatrice) secondo modello illustrato per un generico Compute Engine Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari Altro esempio interessante dal web… http://lia.deis.unibo.it/Courses/cofimp/ Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari 19 Oltre a RMI per l’esecuzione remota RPC (Remote Procedure Call): rende possibile gestire procedure facenti parte di applicazioni remote rispetto al chiamante utilizzate soprattutto nei sistemi UNIX non si inseriscono nel contesto della programmazione ad oggetti DCOM (estensione di COM di Microsoft ) CORBA (Common Object Request Broker Architecture) Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari 20