Java RMI Java RMI - Dipartimento di Informatica

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