CORBA: concetti chiave e terminologia 1 Object Manager Group (OMG): è una organizazzione no-profit che promuove l’uso di tecnologie orientate a oggetti. OMG ha definito gli standard CORBA e UML. Dell’OMG fanno parte circa 600 membri sparsi per il mondo (Università, aziende, utenti). 2 ORB (Object Request Broker): supporta l’interazione tra client e server in esecuzione su macchine diverse. Lato client gli stub invocano l’ORB che si preoccupa di inoltrare le richieste al server. Lato server l’ORB usa gli skeleton per decodificare le richieste proveniente lato client ed invocare il metodo appropriato dell’oggetto remoto (servant). Quando il metodo ritorna, lo skeleton spedisce i risultati al client attraverso l’ORB. 3 IIOP (Internet Inter-ORB Protocol) protocollo che consente a ORB differenti su host differenti di comunicare. Massimo Merro Programmazione di Rete 222 / 247 4 CORBA (Common ORB Architecture) è uno standard per la programmazione di ORB (Object Request Broker), una versione object-oriented di RPC in cui client e server remoti interagiscono, indipendentemente dalla piattaforma (SO e HW) e dal linguaggio di programmazione usato. CORBA viene spesso riferito come un middleware o integration software poichè consente di intgrare applicazioni esistenti con nuove. Altri middleware sono Java RMI, IBM MQ Series, Microsoft’s DCOM e .NET, SOAP, and TIBCO Rendezvous, etc. CORBA nasconde la complessità del sistema distribuito. Oggetti remoti sono accessibili da programma come se fossero locali (Location Transparency). 5 Interface Definition Language (IDL) IDL è un linguaggio per definire l’interfaccia fornita da un oggetto remoto in un processo server. Un’interfaccia IDL definisce il tipo di un oggetto CORBA e descrive come client e server interagiscono. Un’interfaccia IDL è concettualmente molto simile ad un’interfaccia remota Java RMI. Massimo Merro Programmazione di Rete 223 / 247 6 Server: Nella terminologia CORBA un server è un processo che contiene l’implementazione di una o più interfacce IDL. Il server deve registrare tutte le implementazioni (oggetti servant) con l’ORB. Questo perchè l’ORB sappia dove spedire le invocazioni ricevute dagli skeletons. 7 Interoperable Object Reference (IOR): l’interoperabilità implica che una referenza ad un server CORBA rimane valida al variare delle implementazioni del server (ovvero dei servanti). 8 Servizi Corba. CORBA è dotato di un insieme di librerie, funzioni, traduttori, etc: Servizio di naming Concurrency Control Service: fornisce primitive di lock, unlock, etc Event Service: Supporta comunicazioni molti a molti. Transaction Service: (commit, abort, etc) Licensing Service Security Service Trader Service Etc Massimo Merro Programmazione di Rete 224 / 247 Vantaggi di CORBA 1 Standard aperto CORBA è uno standard aperto poichè non è proprietario. Gli utenti possono scegliere una implementazione tra vari possibili “vendors” (o scegliere una implementazione freeware). La maggior parte dei middleware proprietari, per loro natura, forniscono un supporto limitato per l’integrazione con altre tecnologie. CORBA, al contrario, affronta esplicitamente l’integrazione con TMN, SOAP, Microsoft DCOM, etc. Inoltre, molti concetti in J2EE sono stati ispirati da CORBA, rendendo la loro integrazione più facile. 2 Supporta numerose piattaforme: IBM OS/390 and Fujitsu GlobalServer mainframes, numerosi varianti di UNIX (Linux incluso), Windows, AS/400, Open VMS, Apple’s OS X e parecchi sistemi operativi embedded. Massimo Merro Programmazione di Rete 225 / 247 3 Supporta numerosi linguaggi di programmazione IDL è utilizzata per definire l’API pubblica utilizzata da server CORBA. I server sono comunque scritti in altri linguaggi. Perciò affinchè l’interfaccia IDL possa essere utilizzata lo standard CORBA definisce i mapping di IDL nei seguenti linguaggi di programmazione: C, C++, Java, Ada, COBOL, PL/I, LISP, Pythin, e IDLScript. I compilatori sopra indicati sono ufficiali, cioè approvati dall’OMG. Esistono comunque altri compilatori per Eiffel, Tcl e Perl. 4 Efficienza L’infrastruttura del protocollo on-the-wire di CORBA garantisce che i messaggi client/serve vengano trasmessi marshallizzando i dati in maniera molto efficiente. Altri middleware utilizzano formati di trasmissione compatti simili a quelli usati da CORBA. Vi sono, comunque, alcune eccezioni di rilievo. SOAP utilizza XML per rappresentare i dati da trasmettere. La prolissità di XML diminuisce l’efficienza nella trasmissione. Inoltre vi è un notevole carico di CPU nella formattazione dei tipi usati nei linguaggi di programmazione in XML, e viceversa per fare il parsing dei tipi all’interno di file XML. Massimo Merro Programmazione di Rete 226 / 247 5 Interoperabilità L’Obiettivo di CORBA è di integrare in una singola applicazione distribuita più applicazioni scritte in linguaggi differenti, ed in esecuzione su macchine differenti. Per fare ciò CORBA ha bisogno di un meccanismo per stabilire come comunicano i programmi coinvolti, come vengono passati i valori tra programmi, e che protocolli utilizzano. CORBA provvede alla creazione di interfacce scritte in un linguaggio ben preciso (OMG IDL), facile da comprendere, e che possono essere facilmente tradotte nei vari linguaggi di programmazione disponibili. L’interoperabilità di CORBA è piuttosta rara. J2EE, per esempio, supporta solo Java. In SOAP, sebbene potenzialmente si potrebbero usare una varietà di linguaggi, in pratica l’unica mappatura definita è quella per Java. 6 Scalabilità: consente di sviluppare server che possono facilmente scalare dalla gestione di pochi oggetti ad un numero elevato di oggetti. Massimo Merro Programmazione di Rete 227 / 247 Sviluppo di una applicazione Per progettare un’applicazione CORBA ci si affida al paradigma Client-Server. Per implementare l’applicazione occore scrivere il codice seguente: Interfaccia IDL Codice Servant (l’implementazione del server) Codice Server Codice Client Deployment: fare in modo che queste componenti possano interagire tra loro. Massimo Merro Programmazione di Rete 228 / 247 Scrivere un’applicazione CORBA in Java Java fornisce un ORB CORBA e due modelli di programmazione CORBA che utilizzano l’ORB CORBA e il protocollo IIOP (Internet Inter-ORB Protocol): RMI-IIOP. Per programmatori Java che usano interfacce Java RMI, e che vogliono usare il protocollo IIOP per aumentare l’interoperabilità; tali programmatori dovranno curarsi di fornire le interfacce IDL dei server programmati in Java RMI. Java IDL. Per programmatori CORBA, che vogliono programmare in Java basandosi sulle interfacce IDL precedentemente definite. Massimo Merro Programmazione di Rete 229 / 247 Scrivere un’applicazione CORBA in Java IDL Implementare interfacce IDL dei servant (Hello.idl) Generare stub, skeleton ed altre classi di servizio a partire dalle interfacce IDL, tramite un compilatore. Ad esempio, in Java: > idlj -fall Hello.idl Implementare classi servant (HelloImpl.java) Implementare classe server (HelloServer.java) Compilare, ad esempio in Java: > javac Helloimpl.java HelloServer.java Implementare il client (HelloClient.java) Compilare il client. Massimo Merro Programmazione di Rete 230 / 247 Esempio di applicazione: Hello Server Progettazione: un oggetto Hello (servant) in grado di fornire la data corrente oppure fare lo shut-down dell’ORB. I client non conoscono com’è implementato l’oggetto Hello, ma conoscono la sua interfaccia IDL Hello.idl: //IDL interface Hello.idl module HelloApp { interface Hello { string helloDate(); oneway void shutdown(); }; }; I moduli in OMG IDL corrispondono ai package in Java. “oneway” indica che quando si invoca shutdown() non si attende alcuna risposta. Non si garantisce il buon fine dell’operazione. Massimo Merro Programmazione di Rete 231 / 247 Output del compilatore idlj Il compilatore idlj genera a partire dall’interfaccia IDL codici Java. Con l’opzione -fall l’output è il seguente: HelloOperations.java. Questa interfaccia contiene i metodi di Hello.idl. Hello.java è la versione Java di Hello.idl. Estende l’interfaccia HelloOperations.java ed alcune interfacce che forniscono funzionalità CORBA. HelloPOA.java. Classe skeleton. Estende org.omg.PortableServer.Servant. Implementa HelloOperations.java. Il Servant estenderà la classe HelloPOA. HelloStub.java. Classe stub. Implementa Hello.java. HelloHelper.java. Fornisce una serie di funzionalità come ad esempio il metodo narrow per castare referenze CORBA nei corrispondenti tipi Java. HelloHolder.java. Altre funzionalità. Massimo Merro Programmazione di Rete 232 / 247 Vediamo alcuni codici generati da idlj //HelloOperations.java //Generato da idlj a partire da Hello.idl package HelloApp; public interface HelloOperations { String helloDate(); void shutdown(); }; --------------------------------------------------------//Hello.java //Generato da idlj a partire da Hello.idl package HelloApp; public interface Hello extends HelloOperations, org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity { }; Massimo Merro Programmazione di Rete 233 / 247 Programmazione lato Server Un server CORBA (object server) non un’entità fisica precisa, ma un’astrazione di uno o più oggetti remoti concreti, chiamati Servant, che implementano un servizio remoto in un qualche linguaggio di programmazione “ospite”: Java, C, etc. CORBA supporta almeno due modalità diverse per implementare interfacce IDL. Qui vediamo il “POA Inheritance model”. Un POA, Portable Object Adapter, è quella parte del runtime di CORBA che si occupa di rendere una referenza trasparente all’implementazione effettiva del server. Infatti le richieste inoltrate dai client attraverso gli stub vengono indirizzati al POA che la smista all’oggetto che implementa il servizio richiesto. In particolare il POA si preoccupa di demarshallizzare le richieste e marshallizzare le risposte. Massimo Merro Programmazione di Rete 234 / 247 Servant: HelloImpl.java Il servant deve estendere la classa astratta HelloPOA.java. Il nostro servant implementa i metodi di HelloPOA.java. In questo esempio, abbiamo anche un metodo per passare al servant una referenza all’ORB. package server; import HelloApp.* public class HelloImpl extends HelloPOA { private ORB orb; public void setORB(ORB orb_val) { orb = orb_val; } public String helloDate() {return (new Date()).toString();} public void shutdown() {orb.shutdown(false);} } Massimo Merro Programmazione di Rete 235 / 247 Server: HelloServer.java package server; import HelloApp.*; import org.omg.CosNaming.*; import org.omg.CosNaming.NamingContextPackage.*; import org.omg.CORBA.*; import org.omg.PortableServer.*; import org.omg.PortableServer.POA; import java.util.Properties; public class HelloServer { public static void main(String args[]) { try {//Crea ed inizializza il local ORB ORB orb = ORB.init(args, null); // Ottieni una referenza al POA e attiva il POAManager POA rootpoa = POAHelper.narrow(orb.resolve_initial_reference("RootPOA")); rootpoa.the_POAManager().activate(); // Creiamo il servant e gli passiamo una referenza all’ORB HelloImpl helloImpl = new HelloImpl(); helloImpl.setORB(orb); Massimo Merro Programmazione di Rete 236 / 247 // Attraverso il POA ottieni una CORBA object reference del servant org.omg.CORBA.Object ref = rootpoa.servant_to_reference(helloImpl); //Il metodo narrow() casta referenze CORBA sull’interfaccia Java Hello href = HelloHelper.narrow(ref); //Usando l’ORB ottieni una CORBA object reference del servizio di naming org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService") //castiamo la referenza per accedere al servizio di COS naming NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef); //Registriamo il servant nel servizio di naming con nome "Hello" NameComponent path[] = ncRef.to_name("Hello"); ncRef.rebind(path,href); System.out.println("CORBA Server Hello in esecuzione!"); //sospendi il thread corr. e passa al servant in attesa di invocazioni //una volta gestita una invocazione il server si rimette in attesa //ecco perche’ abbiamo lo shudown dell’ORB quando il client completa orb.run(); catch (Exception e) {}; } } Massimo Merro Programmazione di Rete 237 / 247 Client: HelloClient.java package client; import HelloApp.*; import org.omg.CosNaming.*; import org.omg.CosNaming.NamingContextPackage.*; import org.omg.CORBA.*; public class HelloClient { static Hello helloImpl; public static void main(String args[]) { try{ // crea ed inizializza l’ORB ORB orb = ORB.init(args, null); //Usando l’ORB ottieni una CORBA object reference del servizio di Naming org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService"); // Usa NamingContextExt invece di NamingContext. Questo e’ // parte dell’ Interoperable Naming Service. // casta la referenza prima di usarla NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef); Massimo Merro Programmazione di Rete 238 / 247 // ottieni la referenza al servant attraverso il COS Naming e castala helloImpl = HelloHelper.narrow(ncRef.resolve_str("Hello")); System.out.println("Ottenuta una referenza al server object: " + helloImpl); System.out.println(helloImpl.helloDate()); helloImpl.shutdown(); } catch (Exception e) { System.out.println("ERROR : " + e) ; e.printStackTrace(System.out); } System.out.println("HelloServer sta uscendo..."); } } Il nostro Client una volta terminato, invoca il metodo shutdown() per tirare giù l’ORB. Altrimenti resterebbe attivo. Massimo Merro Programmazione di Rete 239 / 247 Deployment Lato Server: Bisognerà lanciare l’ORB. Indicando la porta su cui si intende lanciare il servizio di naming messo a disposizione dall’ORB. Dopo aver lanciato l’ORB bisogna lanciare il server vero e proprio: > orbd -ORBInitialPort 1050 & > java server.Helloserver -ORBInitialPort 1050 & Lato Client: Bisognerà lanciare il client: > java client.HelloClient -ORBInitialPort 1050 -ORBInitialHost nameserver_host Massimo Merro Programmazione di Rete 240 / 247 Server CORBA Un server CORBA è caratterizzato da: Riferimento, ovvero una CORBA object reference Interfaccia IDL Implementazione (servant) Una CORBA object reference (IOR) È un handle che identifica un oggetto Permette all’ORB di localizzare l’oggetto Fa riferimento ad un singolo oggetto Un oggetto può avere più riferimenti È analogo ad un riferimento in Java. Massimo Merro Programmazione di Rete 241 / 247 Servant Rappresenta l’implementazione del server ed esegue le operazioni invocate dal client L’implementazione è basata su Ereditarietà (il servant eredita dalla classe POA) Delega (un server CORBA delega le operazioni ai metodi del servant) Può essere usato dai più server CORBA Fornisce un target per un oggetto CORBA Vive solo dentro un processo server. Massimo Merro Programmazione di Rete 242 / 247 Ancora sulle Interfacce IDL Costituisce il contratto offerto da un oggetto al client I client devono usare l’interfaccia IDL per specificare l’operazione da compiere su un oggetto. Definisce Un tipo IDL per un server CORBA Ciò che è implementato da un oggetto remoto. Può contenere Dichiarazioni di eccezioni Definizioni di costante Attributi (campi): possono essere usati solo per operazioni get/set Operazioni (metodi). I parametri di un’operazione possono specificare la direzione: IN (dal client al server); OUT (dal server al client); INOUT (entrambe). Le operazioni possono avere anche un valore di ritorno. Supporta ereditarietà multipla. Massimo Merro Programmazione di Rete 243 / 247 Un esempio di interfaccia IDL module Finance { typedef sequence<string> StringSeq; struct AccountDetails { string name; StringSeq address; long account_number; double current_balance; }; exception insufficientFunds { }; interface Account { void deposit(in double amount); void withdraw(in double amount) raises(insufficientFunds); readonly attribute AccountDetails details; }; }; Massimo Merro Programmazione di Rete 244 / 247 Vantaggi e Limiti di IDL IDL supporta Moduli Interfacce Operazioni Attributi Ereditarietà multipla Array, struct, enum, union Costanti Eccezioni IDL non supporta Puntatori Costruttori o distruttori Overloading e overriding delle operazioni Ereditarietà delle eccezioni Costrutti di controllo. Massimo Merro Programmazione di Rete 245 / 247 CORBA vs RMI CORBA e Java RMI rappresentano due framework per lo sviluppo di sistemi distribuiti ad oggetti. Facciamone un breve confronto. CORBA è progettato per garantire la massima interoperabilità per utilizzare applicazioni scritte usando linguaggi e piattaforme differenti. Esistono moltissime applicazioni sviluppate usando CORBA. Le performance delle applicazioni CORBA sono in generale molto buone. Se invece consideriamo Java RMI: In Java RMI, client e server devono necessariamente essere sviluppati in Java. Java RMI è un linguaggio più semplice ed è quindi più facile da usare per sviluppare grossi sistemi. Il codice per descrivere un sistema in Java RMI può essere molto inferiore a quello per descrivere il medesimo sistema in CORBA. Le prestazioni di Java RMI sono in generale inferiori a quelle di CORBA. Massimo Merro di Rete 246 / 247 di Infine, Java RMI, al contrario Programmazione di CORBA, supporta un meccanismo Conclusioni CORBA Riduce la complessità e le difficoltà dello sviluppo di sistemi distribuiti Permette l’interoperabilità tra oggetti implementati su piattaforme e linguaggi diversi CORBA non affronta Bilanciamento del carico Mobilità di codice. Per ulteriori dettagli guardare: http://java.sun.com/j2se/1.5.0/docs/guide/idl/index.html oppure http://www.ciaranmchale.com/corba-explained-simply/index.html Massimo Merro Programmazione di Rete 247 / 247