Introduction à CORBA
Plan Introduction Architecture Services Développement d'une application Interface Definition Language (IDL) Exemple "Hello World!" 2
Bibliographie http://www.omg.org/ http://www.corba.org/ http://java.sun.com/developer/onlinetraining/corba/ J.-M. Geib, C. Gransart, P. Merle, "CORBA : des concepts à la pratique", 2 e édition, Dunod, 1999. ISBN 2100048066. A. Fron. "Architectures réparties en JAVA", Dunod 2007. J. Daniel, "Au cœur de CORBA avec Java", Vuibert, 2002. ISBN 2711786854. 3
Introduction CORBA (Common Object Request Broker Architecture) Ensemble de spécifications et de recommandations. Norme rédigée par l OMG. CORBA 3. Object Management Group (1989). Plus de 800 membres (Sun, IBM, Microsoft,...). http://www.omg.org 4
Introduction Objectif : communications indépendantes des langages de programmations, des plates-formes matérielles, logicielles, des réseaux de communication, des développeurs. C++ Invocation Smalltalk Java Ada Objet distant Masquer l hétérogénéité 5
Introduction Applications : Objets CORBA qui implémentent des interfaces définies en IDL (Interface Definition Language). Clients accèdent aux méthodes dans les interfaces des objets CORBA, moyennant RMI. Serveur Objet CORBA Client Serveur 6
Architecture de CORBA Vision globale Services Objets de domaines Annuaire Transaction Médecine Electronique Le bus C.O.R.B.A. Client Serveur Administration Impression Applications utilisateurs Utilitaires communs 7
Architecture de CORBA Client Serveur JAVA IDL Objet C++ Skeleton Stub ORB IIOP Object Adapter ORB 8
Composants Souche/Stub : talon client Squelette/Skeleton : talon serveur générés automatiquement Object Adapter : enregistrement des objets. ORB : passage de requêtes/messages. IIOP : Internet Inter-ORB Protocol. 9
Stub (souche) Rappels Code client. Interface entre objet et ORB. Traduit les invocations sur l objet serveur (servant). Marshalling. Traduit les messages en valeurs de retour. Unmarshalling. 10
Code serveur. Skeleton (squelette) Rappels Interface entre implémentation/servant et ORB. Traduit les invocations client vers l implémentation. Unmarshalling. Traduit la valeur de retour en message vers client. Marshalling. 11
Référence d un objet CORBA Références d objets distants CORBA : Format IOR (Interoperable Object Reference) Interface de l objet Protocole et détails d adresse Clé identifiant l objet Interface repository identifier IIOP Host domain name Port number Adapter name Object name Exemple d IOR "stringifiée" (sous forme d une chaîne de caractères) : IOR:000000000000001049444c3a5472697669616c3a312e300000000001000000000000 007c000102000000000d3135322e38312e342e3131300000048000000025abacab313130 3033383632313336005f526f6f74504f410000cafebabe3bd5b87800000000000000000000 01000000010000002c000000000001000100000004000100200001010900010100050100 0100010109000000020001010005010001 12
Object Adapter (OA) POA : Portable Object Adapter Gère un ensemble de servants ayant des caractéristiques communes Ces caractéristiques sont contrôlées par les stratégies du POA Durée de vie des objets, allocation des requêtes à différents threads, allocation des identifiants d objets Activation et désactivation des objets. Invocation des méthodes. Tout servant est associé à un POA. 13
Object Request Broker (ORB) Transporte les messages entre les objets. Relie les souches aux squelettes correspondants et vice-versa. Bus à objets. Communications inter-orbs : GIOP (General Inter-ORB Protocol). IIOP (Internet Inter-ORB Protocol) (GIOP on TCP/IP). 14
Services de CORBA Services de localisation d objets Service de nommage (Naming) Pour retrouver un objet par un nom. De type "pages blanches". Service vendeur (Trader) Pour retrouver un objet par des propriétés. De type "pages jaunes". 15
Services de CORBA Services de communications asynchrones Events, Notification, Messaging. Services de sûreté de fonctionnement Security, Transactions, Concurrence. Services concernant la vie des objets Life Cycle, Property, Relationship, Externalization, Persistent Object, Query, Collection, Versionning, Time, Licencing. 16
Développement d'une application Définir le contrat IDL (interface IDL). Compiler le contrat IDL (génération des talons). Créer la classe des servants (implémentation de l interface). Créer le serveur : Création et publication du servant (objet CORBA). Créer le client : Utilisation du servant. 17
Développement d'une application 18
Fichiers nécessaires Fichiers Client Serveur Souche X X Squelette X Code du serveur X Code du client X Librairie ORB X X 19
IDL de CORBA (Interface Definition Language) Langage neutre de spécification d interface. Définit les interfaces contractuelles d un composant avec ses clients. Aucun détail d implantation (langage, système d exploitation). Permet ensuite de générer des "squelettes" de programme dans les langages de programmation des applications. 20
IDL de CORBA Spécification IDL : définit un ou plusieurs types, constantes, exceptions, interfaces, modules. Mêmes règles syntaxiques que C++. Nouveaux mots-clés pour supporter la distribution (interface, attribute, oneway, readonly, in, out, ) Commentaires : par ligne : tout ce qui se trouve derrière // par bloque : /* pour le début, */ pour la fin Utilisation d un préprocesseur C : macros (#define, #ifdef, #ifndef, #endif); inclusion #include,... 21
IDL de CORBA module example { interface monexample { void methode1(); long methode2(); void methode3(in long param, out long result); }; }; Espace de nom C++ : namespace. Java : package. 22
IDL de CORBA Types d IDL : types de base void rien short entier 16 bits unsigned short entier 16 bits non signé long entier 32 bits unsigned long entier 32 bits non signé long long entier 64 bits unsigned long long entier 64 bits non signé float réel 32 bits (IEEE) double réel 64 bits (IEEE) long double réel 128 bits (IEEE) boolean booléen (TRUE, FALSE) octet opaque 8 bits char caractère 8 bits (ISO Latin 1) wchar caractère international 23
IDL de CORBA Types d IDL (suite): Types construits struct enum union string, wstring Types génériques sequence any typecode Types alias typedef 24
IDL de CORBA void methode(in long param, out long result); Méthodes : comme en C++ et Java, sauf in : paramètre utilisé en entrée (lu, non modifié). out : paramètre utilisé en sortie (non lu, modifié). inout : paramètre utilisé en entrée et en sortie (lu et modifié). 25
IDL de CORBA Une méthode est bloquante par défaut Long pgcd(in long a, in long b); Méthode non bloquante : Utilisation de l attribut oneway Pas de paramètre de type out, inout ou d exceptions Valeur de retour : void oneway void arret(in short delay); 26
IDL de CORBA Définition d exceptions : 0 ou N champs typés Indispensables pour prévoir les cas d erreurs exception ErreurInterne {}; // sans paramètres exception MauvaiseDate { Date UneDate; }; Type générique any : sert à stocker n importe quelle valeur IDL module MesPiles { }; interface PileGenerique { }; readonly attribute long sommet; void empiler(in any valeur); any depiler(); 27
IDL de CORBA Héritage : interface A {... }; // A est une interface interface B : A {... }; // B étend A interface C : A {... }; // C étend A interface D : B, C {...}; // D étend B et C // (héritage multiple) A Surcharge et redéfinition interdites. B D 28 C
IDL de CORBA Attributs IDL : opération(s) (lecture, écriture) liée(s) à une propriété interface article { readonly attribute float poids; // (lecture seule) attribute string description; // (lecture et écriture) }; Équivalent Java interface article { float poids(); // get_poids string description(); // get_description void description(string s); // set_description } 29
IDL de CORBA Exceptions d une opération IDL : informer l appelant des erreurs d exécution lors de l invocation d une méthode. Exceptions "système" Problèmes liés à l utilisation du bus CORBA. Explicitement spécifiées pour toutes les méthodes. Exceptions "utilisateur" Problèmes liés à une mauvaise utilisation de l objet. Explicitement spécifiées dans la signature des méthodes. 30
IDL de CORBA Quelques règles de la projection IDL vers Java IDL Type module interface const enum, struct, union sequence tableaux IDL typedef exception [readonly] attribute opération d une interface Java package interface static final classes Java ad hoc tableaux Java tableaux Java class sous-type de java.lang.exception méthodes Java de lecture/maj méthode Java 31
IDL de CORBA Projection des types de base IDL Type boolean (TRUE, FALSE) char wchar octet string wstring short unsigned short long unsigned long long long unsigned long long float double fixed long double Java boolean (true, false) char char byte java.lang.string java.lang.string short short int int long long float double java.math.bigdecimal Non supporté! 32
Exemple "Hello World!" /* Fichier "Hello.idl" */ module HelloApp { interface Hello { string sayhello(); }; }; 33
Exemple "Hello World!" Projection vers JAVA. idlj : compilateur IDL vers java Dans le JDK. Syntaxe : idlj -fall Hello.idl Les fichier suivants sont alors générées : _HelloStub.java, Hello.java, HelloOperations.java, HelloPOA.java, HelloPOATie.java, HelloHelper.java, HelloHolder.java 34
Exemple "Hello World!" Les classes générées Fichiers générés : Hello.java HelloOperations.java _HelloStub.java HelloHelper.java HelloHolder.java HelloPOA.java HelloPOATie.java Classe équivalente en Java pour chaque interface Classe souche Classes Helper et Holder Classe adaptateur d objets Classe adaptateur d objets (délégation ) 35
Exemple "Hello World!" La classe des futurs servants Classe qui implémente le contrat IDL. Doit dériver de "HelloPOA". class HelloImpl extends HelloPOA { private ORB orb; public void setorb(orb orb_val) { orb = orb_val; } public String sayhello() { return "\nhello World!\n"; } } 36
Exemple "Hello World!" Le serveur Création et initialisation de l ORB ; Récupération de la référence de l adaptateur d objets racine et activation du manager ; Création de l objet servant ; Récupération de la référence du servant ; Récupération de la référence de l objet du service de nommage en utilisant sa référence initiale "NameService" ; Conversion vers un type utilisable au moyen de la méthode narrow() de la classe NamingContextExtHelper ; Association d'un nom à la référence du servant, dans le service de nommage ; Mise en attente des requêtes. 37
Exemple "Hello World!" public class HelloServer { public static void main(string args[]) { try{ // create and initialize the ORB ORB orb = ORB.init(args, null); // get reference to rootpoa & activate the POAManager POA rootpoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA")); rootpoa.the_poamanager().activate(); // create servant and register it with the ORB HelloImpl helloimpl = new HelloImpl(); helloimpl.setorb(orb); 38
Exemple "Hello World!" // get object reference from the servant org.omg.corba.object ref = rootpoa.servant_to_reference(helloimpl); //Hello href = HelloHelper.narrow(ref); // get the root naming context ; NameService org.omg.corba.object objref = orb.resolve_initial_references("nameservice"); NamingContextExt ncref = NamingContextExtHelper.narrow(objRef); // bind the Object Reference in Naming String name = "Hello"; NameComponent path[] = ncref.to_name(name); ncref.rebind(path, ref); 39
Exemple "Hello World!" System.out.println("HelloServer ready and waiting..."); // wait for invocations from clients orb.run(); } catch (Exception e) { System.err.println("ERROR: " + e); e.printstacktrace(); } } 40
Exemple "Hello World!" Le client Création et initialisation de l ORB ; Récupération de la référence de l objet du service de nommage ; Récupération de la référence du servant grâce au service de nommage ; Conversion de la référence vers le type Hello en utilisant la méthode narrow() de la classe HelloHelper ; Invocation de méthodes distantes. 41
Exemple "Hello World!" public class HelloClient { static Hello helloimpl; public static void main(string args[]) { try{ // create and initialize the ORB ORB orb = ORB.init(args, null); // get the root naming context org.omg.corba.object objref = orb.resolve_initial_references("nameservice"); NamingContextExt ncref = NamingContextExtHelper.narrow(objRef); 42
Exemple "Hello World!" // resolve the Object Reference in Naming String name = "Hello"; helloimpl = HelloHelper.narrow(ncRef.resolve_str(name)); System.out.println(helloImpl.sayHello()); } } catch (Exception e) { System.out.println("ERROR : " + e) ; e.printstacktrace(system.out); } } 43
Exemple "Hello World!" L'exécution Service de nommage à lancer avant le serveur orbd -ORBInitialPort <port> Sous Windows : start orbd Lancer le serveur java HelloServer -ORBInitialPort <port> Lancer le client -ORBInitialHost <servermachinename> java HelloClient -ORBInitialPort <port> -ORBInitialHost <servermachinename> 44
JAVA RMI vs. CORBA JAVA RMI fait communiquer des composants 100% JAVA, alors que CORBA est multi-langage. JAVA RMI bénéficie des apports de JAVA, certaines difficiles, voire impossibles à réaliser avec CORBA (ex : téléchargement distant d un objet). JAVA RMI est plus facile à mettre en œuvre que CORBA. JAVA RMI est une technologie moins mûre que CORBA, et a donc moins de services auxiliaires (notamment en matière de sécurité, de transaction, ). Le choix entre JAVA RMI et CORBA dépend du type d application à développer. 45
Conclusion Solution non propriétaire. Standard. Libre choix de l implémentation et du langage. Solution fonctionnelle d interopérabilité. Plusieurs implémentations libres et opensource. 46
ANNEXE Comparatif des ORB CORBA Middleware Prix Système Concepteur ORBacus $ Unix/Win Object Oriented Concepts (OOC) Langages supportés Java/C++ Remarques Rapide, léger VisiBroker $ Unix/Win Borland Java/C++/Delphi Facilité d utilisation, performance ORBIX $ Unix/Win Iona Java/C++ MICO gnu Unix/Win Univ. Francfort C++ Jac Orb version C++ JDK free Unix/Win Sun Java Complet, évolution vers Open ORB JacORB gnu Unix/Win Univ. Berlin Java Jorba free 47
ANNEXE Comparatif d'intergiciels 48
ANNEXE Appel en retour (callback) Exemple "Bonjour" 49
Appel en retour : exemple "Bonjour" Interface module CallbackApp { interface BonjourCallback { }; void callback(in string message); interface Bonjour { void say(in BonjourCallback objref, in string message); }; }; 50
Appel en retour : exemple "Bonjour" Côté Serveur class BonjourServant extends BonjourPOA { } public void say(bonjourcallback callobj, String msg) { callobj.callback(msg); System.out.println("Servant : Callback effectué\n");} public class BonjourServer { public static void main(string args[]) { try{ ORB orb = ORB.init(args, null); POA rootpoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA")); rootpoa.the_poamanager().activate(); BonjourServant bonjourimpl = new BonjourServant(); org.omg.corba.object ref = rootpoa.servant_to_reference(bonjourimpl); Bonjour cref = BonjourHelper.narrow(ref); org.omg.corba.object objref = orb.resolve_initial_references("nameservice"); }} NamingContextExt ncref = NamingContextExtHelper.narrow(objRef); String name = "Bonjour"; NameComponent path[] = ncref.to_name(name); ncref.rebind(path, cref); orb.run();} catch(exception e) {System.err.println("ERROR:"+e); e.printstacktrace(system.out);} 51
Appel en retour : exemple "Bonjour" Côté Client class BonjourCallbackServant extends BonjourCallbackPOA { public void callback(string notification) { System.out.println("(appel de callback) -> "+ notification); }} public class BonjourClient { static Bonjour bonjourimpl; public static void main(string args[]) { try{orb orb = ORB.init(args, null); POA rootpoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA")); rootpoa.the_poamanager().activate(); org.omg.corba.object objref = orb.resolve_initial_references("nameservice"); NamingContextExt ncref = NamingContextExtHelper.narrow(objRef); String name = "Bonjour"; bonjourimpl = BonjourHelper.narrow(ncRef.resolve_str(name)); BonjourCallbackServant bonjourcallbackimpl = new BonjourCallbackServant(); org.omg.corba.object ref = rootpoa.servant_to_reference(bonjourcallbackimpl); BonjourCallback cref = BonjourCallbackHelper.narrow(ref); bonjourimpl.say(cref, "Bonjour!"); System.out.println("Fin du client");} catch(exception e){system.out.println("error:"+e); e.printstacktrace(system.out);} }} 52
ANNEXE Exemple "Hello world!" avec ORBacus serveur et client en C++ 53
"hello.idl" module HelloApp { interface Hello { string sayhello(); }; }; 54
"hello_impl.h" #include <hello_skel.h> // Implémentation par héritage du squelette class hello_impl : public POA_Hello, public PortableServer::RefCountServantBase { protected: int count; public: inline hello_impl() {count=0;} virtual ~hello_impl() {} virtual char* sayhello(); }; 55
"hello_impl.cc" #include <CORBA.h> #include <hello_impl.h> // Implémentation de sayhello() char* hello_impl::sayhello() throw(corba::systemexception) { } cout<<"appel de sayhello() #"<<(count+1)<<endl; ostringstream s; s<<"hello World #"<<++count<<"!"; return CORBA::string_dup( (const char*)s.str().c_str()); 56
"hello_server.cc" // initialisation de l ORB CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); // retrouve le Root POA CORBA::Object_var poaobj = orb -> resolve_initial_references("rootpoa"); PortableServer::POA_var rootpoa = PortableServer::POA::_narrow(poaObj.in()); // recuperation d'une reference sur le POA manager PortableServer::POAManager_var manager = rootpoa -> the_poamanager(); // creation de servants Hello_impl* a1p = new Hello_impl; Hello_var a1 = a1p -> _this(); // récupération du naming service CORBA::Object_var obj = orb -> resolve_initial_references("nameservice"); CosNaming::NamingContext_var nc = CosNaming::NamingContext::_narrow(obj); // creation et publication du nom CosNaming::Name a1name; a1name.length(1); a1name[0].id = CORBA::string_dup( Hello"); a1name[0].kind = CORBA::string_dup(""); nc -> bind(a1name, a1); // lancement manager -> activate(); // POA manager orb -> run(); } 57
"hello_client.cc" // Initialisation de l ORB CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); // récupération du naming service CORBA::Object_var obj = orb->resolve_initial_references("nameservice"); CosNaming::NamingContext_var nc = If(CORBA::is_nil(obj.in())) { cout << "'NameService' introuvable" << endl; return 1; } // Résolution d un nom CosNaming::Name aname; aname.length(1); aname[0].id = CORBA::string_dup("Hello"); aname[0].kind = CORBA::string_dup(""); CORBA::Object_var aobj = nc -> resolve(aname); Hello_var helloref = Hello::_narrow(aObj.in()); // appel d une methode de l objet CORBA::String_var dest = helloref->sayhello(); CosNaming::NamingContext::_narrow(obj.in()); cout<<"message de l'objet corba Hello: \""<<(char*)dest<<"\"."<<endl; 58
Compilation Génération des souches/squelettes C++ <ORB home>/bin/idl hello.idl Compilation C++ des sources applicatifs et générés gcc -o hello_skel.o c hello_skel.cc gcc -o hello_server hello_server.o hello_skel.o <librairies ORB> gcc -o hello_client hello_client.o <bibliothèques ORB> 59