3- Le langage IDL Le contrat IDL Un « esperanto » pour les objets Client d ’objets Fournisseur d ’objets Stub IDL Bus CORBA Squelette IDL Une interface OMG IDL correspond à l ’abstraction d ’un type d ’objet, C ’est l ’API que l'on veut rendre publique. Elle contient donc les opérations exportées et utilisées par les autres objets mais pas forcément toutes les méthodes implantés par la classe d'objet. Ce contrat isole le client des détails d ’implantation des objets et du langage choisi pour leur implantation. Objets Corba - 1 - 17 17
Le langage IDL Interface Definition Language Description Le langage IDL Interface Definition Language langage de spécification d’interfaces, supportant l’héritage multiple; indépendant de tout langage de programmation ou compilateur (langage pivot entre applications); langage utilisé pour générer les stubs, les squelettes et pour définir les interfaces du Référentiel d’interface; la correspondance IDL-langage de programmation est fournie pour les langages C, C++, Java, Smalltalk, Ada, Cobol. La norme internationale ODP à adopté IDL comme standard pour la description de ses propres objets. Description de type indépendante d ’un langage de programmation. - 2 - 17 17
IDL versus C++ Grammaire IDL : sous ensemble de la grammaire ANSI C++ Description IDL versus C++ Grammaire IDL : sous ensemble de la grammaire ANSI C++ avec constructions supplémentaires Nouveaux mots clés : attribute interface module oneway readonly sequence any Même commentaires qu’en C++ // et :/* */ Distinction entre majuscules et minuscules (myObject myOBJECT); Toute définition IDL se termine par « ; ». - 3 - 20 20
Exemple 3. IDL interface attribut opérations exception opérations Description Exemple interface account { readonly attribute float balance; attribute string description; void credit (in float f); void debit (in float f); }; interface currentAccount : account { readonly attribute float overdraftLimit; interface bank { exception reject {string reason;}; account newAccount (in string name) raises (reject); currentAccount newCurrentAccount (in string name, in float limit) void deleteAccount (in account a); }; interface attribut opérations exception opérations - 4 - 19 19
3. IDL Description Eléments IDL Une spécification IDL définit un ou plusieurs types, constantes, exceptions, interfaces, modules,... pragma constantes types de base au format binaire normalisé nouveaux types (typedef, enum, struct, union, array, sequence) exceptions types de méta-données (TypeCode, any) Les pragmas IDL sont des directives permettant au précompilateur IDL de générer et créer des identifiant globaux (Utile pour avoir des espaces de nommage) La norme définit les 3 pragmas : prefix : utilisé dans la génération des identifiants version :permet d ’associer un numéro de version à un identifiant IDL ID : fixer précisément l ’identifiant associé à une def IDL. #pragma prefix « omg.org » module ServiceDate { IDL:omg.org/ServiceDate typedef unsigned short Mois; #pragma version Mois 1.2; IDL:omg.org/ServiceDate/Mois:1.2 typedef unsigned short Annee; #pragma ID Annee « IDL:monde/Annee:2.3 » IDL:monde/Annee:2.3 constantes : nom symbolique à des valeurs particulières : const Ident = expression types de base au format binaire normalisé : élémentaires : entiers, flottants, booleans, caractères, chaînes, types composés composés : énumérations, structures, union, tableaux, séquences des types dynamiques auto-déscriptifs (TypeCode et any). nouveaux types permet de créer un nouveau type de donnée. (typedef (aussi dit alias) , enum, struct, union, array, sequence) par exemple typedef sequence<Positif> Des entiersPositifs; typedef unsigned long EntierPositif; que l ’on retrouve dans l ’interface Premier permet de manipuler des jours plus clairement qu ’avec un entier de 16bits exception : chaque exception définir un type de données structuré constitué d ’un ens. de champs typé - 5 - 18 18
3. IDL Description Eléments IDL Un module permet de limiter la validité des identificateurs Interface : ensemble d’opérations et de types =>classe C++ Syntaxe : Interface | [<héritage>] { <interface Body>}; opération (synchrone ou asynchrone sans résultat) attribut (possibilité de lecture seule) Surcharge Interdite Réutilisation de spécifications existantes (#include) - 6 - 18 18
Exemple 3. IDL module définitions de type interface opérations Description Exemple module unService { typedef unsigned long EntierPositif; typedef sequence<Positif> desEntiersPositifs; interface Premier { boolean est_premier ( in EntierPositif nombre); desEntiersPositifs nombres_premiers (in EntierPositif nombre); }; module monApplication { interface MonService { unService::EntierPositif prochainPremier(..); module définitions de type interface opérations Le concept d ’interface est l ’équivalent des interface Java, ou des classes abstraites C++. Les typedef permettent de créer des alias, en général utilisés dans un but de lisibilité des contrats IDL. - 7 -
Exemple 3. IDL Description Description d’un service pour manipuler des dates. La notion de modules permet de regrouper des définitions communes à un ou plusieurs services. Ici on trouve des définitions de types et 3 définitions d’interfaces. Jour et années sont représentés par des entiers positifs. - 8 - 19 19
Attribut IDL Définition d’attribut interface account { Equivaut à : Description Attribut IDL Définition d’attribut interface account { readonly attribute float balance; attribute string description; ... }; Equivaut à : float get_balance(); string get_description(); void set_description(in string s); La notion d’attributs IDL ne doit pas être confondue avec les attributs d’instances. Ce n’est qu’une construction syntaxique pour exprimer simplement une paire d’opérations d’accès à une propriété d’un objet. Il faut ensuite implanter ces opérations. . - 9 - 22 22
Operations (1/2) Paramètres nommés void op1 (in long input, 3. IDL Description Operations (1/2) <uneOpération> ::= <modeInvocation> <typeRetour> <identificateur> ‘ (‘ <paramètres> ‘ ) ’ <clausesExceptions><clausesContextes> Paramètres nommés et associés à un mode Opérations bloquantes par défaut void op1 (in long input, out long output, inout long both); interface account; interface bank { account newAccount (in string name); void deleteAccount (in account old); }; Client uneBanque L’identificateur d’une opération est unique. Liste des paramètres in : transport du client vers l’objet out : transport en retour de l’objet vers le client in out : dans un sens puis dans l’autre. Le type de retour est void quand rien n’est retourné. Mode d ’invocation : par défaut synchrone. Le client attend la fin d ’exécution de l ’opération pour reprendre la suite de son activité. Exceptions : indique optionnellement les exceptions pouvant être déclenchées par cette opération. Contextes : variables d ’environnement du client vers l ’objet. Très peu utilisée, car on préfère passer des informations telles que le contexte d ’exécution du client via des paramètres. newAccount calcul retours - 10 - 23 23
Opérations (2/2) oneway void notify (in string message); 3. IDL Description Opérations (2/2) oneway void notify (in string message); Opération non bloquante Pas de paramètre de type out, inout ou d’exceptions Valeur de retour : void Pas d ’exceptions déclenchées. Client uneBanque notify(«ok ») méthode finie - 11 - 24 24
Exceptions Gestion explicite de la part du client 3. IDL Description Exceptions exception reject {string reason;}; account newAccount (in string name) raises (reject); exception DateErronnee { String raison; }; CORBA::Exception CORBA::UserException CORBA::SystemException Des exceptions CORBA standardisées UNKNOWN NO_PERMISSION BAD_PARAM NO_IMPLEMENT COM_FAILURE OBJECT_NOT_EXIST INV_OBJREF ………. Similaire à la définition d ’une structure elles peuvent avoir plusieurs champs de valeurs typées. Ce qui permet d ’informer le client sur le contexte et les raisons qui ont provoqué l ’exception. Les exception Systeme ne doivent pas être précisées parmi les exceptions qui peuvent être déclenchées par une opération: leur déclaration est implicite. Gestion explicite de la part du client - 12 -
Définitions circulaires 3. IDL Description Définitions circulaires module Circulaire { interface B; interface A { void utiliséB(in B unB); } interface B { void utiliséA(in A unA); - 13 - 25 25
Types de base et autres types 3. IDL Description Types de base et autres types Types de base short long unsigned short unsigned long float double char boolean octet …... Types construits struct union enum Types génériques array sequence string MétaTypes Types de données dynamiques et auto-descriptifs any TypeCode - 14 - 21 21
Type Any interface PileDeChaines { readonly attribut string sommet; 3. IDL Description Type Any interface PileDeChaines { readonly attribut string sommet; void poser(in string valeur); string retirer(); }; interface PileGénérique { readonly attribut Any sommet; readonly attribut TypeCode typeDesValeurs; void poser(in Any valeur); Any retirer(); }; MetaType : des types de données contenant une valeur et une info décrivant le type de celle-ci. TypeCode : permet de stocker la description de tout autre type IDL. Par ex. S ’il contient une structure, il en contiendra le nom et la liste de tous ses champs (leur nom et TypeCode associé). Any permet de stocker n ’importe quelle valeur IDL et son TypeCode associé. Utilisé dans tous les contextes où il est nécessaire de transporter des valeurs dont le type n ’est pas encore connu au moment des phases de conception IDL ou pour définir des opérations dont l ’un des paramètres est polymorphe. Ces types sont à la base des mécanismes dynamiques du bus CORBA. - 15 -
Projection vers un langage de programmation 3. IDL Projection Projection vers un langage de programmation Definitions IDL Client Serveur Précompilateur IDL Objet implementation C++ Java Methodes Adaptateur d'objet Stubs Squelettes C++ Java Noyau ORB - 16 - 26 26
Mapping C++ des modules 3. IDL Projection Mapping C++ des modules traduit en namespace C++ les modules CORBA contiennent des types prédéfinis des interfaces et des opérations // IDL module M { // définitions }; // C++ namespace M { // définitions }; - 17 - 28 28
Mapping Java des modules 3. IDL Projection Mapping Java des modules traduit en package Java // IDL module M { // définitions }; // Java package M { // définitions }; - 18 - 28 28
Projections de types élémentaires 3. IDL Projection Projections de types élémentaires Les types simples en C++ sont désignés par des alias car le format de ces données peut changer d ’un compilateur à l ’autre. Projetés directement en Java vers les types natifs car les spec de ce langage assure une représentation unique quelque soit l ’architecture matérielle cible. - 19 -
Projections en C++ et Java 3. IDL Projection Projections en C++ et Java énumération : enum en C++ ; constantes encapsulées dans une classe dont le nom est celui du type énuméré en Java séquences: encapsulées dans une classe qui contrôle les débordements en C++; des tableaux dynamiques en Java tableaux : tels que. Interface : classe C++ ; interface Java interface J:I {…} class J : public virtual I interface J extends I {…} Opérations : méthodes Attributs : une ou deux méthodes d ’accès - 20 -
Projection en Java d’une énumération IDL : enum Mois {Janvier, Fevrier, ….} Java généré : public final class Mois { public static final int _Janvier = 0; public static final Mois Janvier = new Mois(_Janvier); public static final int _Fevrier = 1; public int value() {…} public static Mois from_int(int value) {…} Utilisation : Mois m = Mois.Janvier; switch (m.value()) { case Mois._Janvier : …;} m = Mois.from_int(7); if (m == Mois.Aout) { …} - 21 -
Projection en Java : définitions contenues dans une interface Génération d ’un package contenant la traduction des définitions imbriquées IDL : interface UneInterface{ struct uneStructure {…};} Java généré : package UneInterfacePackage; public final class UneStructure{ …} Utilisation : UneInterfacePackage.UneStructure s = …; - 22 -
Passage de paramètres en java 3. IDL Projection Passage de paramètres en java paramètres en out ou inout : utilisation de Holder en Java final public class XHolder { { public X value; public XHolder(){ } public XHolder(Grid initial) { value = initial; } final public class BooleanHolder { { public Boolean value; public BooleanHolder(){ } public BooleanHolder(Grid initial) Classes Holder pour les types élémentaires - 23 -
Passage de paramètres en java 3. IDL Projection Passage de paramètres en java // OMG IDL interface Modes { long operation ( in long inArg, out long outArg, inout long inoutArg); } //Java int operation(int inArg, org.omg.CORBA.IntHolder outArg, org.omg.CORBA.IntHolder inoutArg); //Utilisation Modes m = …; IntHolder argSortie = new IntHolder(); IntHolder argES = new IntHolder(131); int result = m.operation(57,argSortie,argES); …. argSortie.value….. - 24 -
Mapping C++ des références objet 3. IDL Projection Mapping C++ des références objet interface A { void op1 (in long param); }; Interface traduit en classes C++ traduit en deux types C++ A_var Référence sur un objet (instance de classe A) avec gestion automatique de la mémoire. A_ptr Similaire aux pointeurs C++. // C++-used A_ptr aPtr; A_var aVar; aVar->op1(2); aPtr->op1(5); Si en java on n’a pas a se préoccuper de problème de gestion mémoire en C++, la norme definit des règles et fournit des mécanismes pour pallier ce manque. En C++, le précompilateur génère des classes assurant automatiquement et de manière transparente la désallocation de la mémoire dynamique qui n’est plus utilisée. Par convention ces classes sont désignés par la concaténation du nom du type et du suffixe _var. Il se comporte comme un pointeur Intelligent sur un objet de Type suffixe. - 25 - 29 29
Gestion mémoire : pointeurs en C++ En C++ Gestion difficile car les clients et les serveurs sont dans des processus différents. Problèmes : Qui fait l’allocation de la mémoire ? (malloc, new) Qui fait la désallocation de la mémoire ? (delete) interface T { string op1() }; char* T_i::op1() { char* tmp = CORBA::string_alloc(6); strcpy(tmp, «hello»); return tmp; }; c tmp «hello» «hello» Client Serveur - 26 -
3. IDL Projection Exceptions (1/3) Définition d'un ensemble d'exception système standardisées : UNKNOWN, BAD_PARAM, NO_MEMORY, etc ...; Possibilité de définir des exceptions propres à l'utilisateur; Exceptions propagées de l'objet implémentation vers le client; CORBA::Exception CORBA::UserException CORBA::SystemException exceptions définies dans les IDL autres exceptions système standard du bus CORBA CORBA::UNKNOWN - 27 - 30 30
Mapping C++ des exceptions (3/3) 3. IDL Projection Mapping C++ des exceptions (3/3) Interface IDL interface bank { exception reject {string reason;}; account newAccount (in string name) raises (reject); ... } Client bank_var b; ... try { a = b->newAccount("Bill"); } catch (const bank::reject& r) { // actions catch(...) { Objet Implémentation void bank_i::newaccount (const char* name, CORBA::Environnement&) { ... throw bank::reject ("Impossible to create a new account"); }; - 28 - 31 31
Mapping C++ 3. IDL Serveur Compilateur IDL Client Projection interface room { attribute string name; attribute long number; ... } class room _i : public virtual roomImpl, public SDAroom { ... CORBA::String* name() { return SDAroom::name();} void name (const CORBA::String& s) { SDAIroom::name(s);} CORBA::Long number() { return SDAroom::number();} void number(const CORBA::Long l) { SDAIroom::number(l);} } Compilateur IDL Client class roomImpl : public virtual room { ... virtual CORBA::String* name()=0; virtual void name (const CORBA::String&)=0; virtual CORBA::Long number()=0; virtual void number(const CORBA::Long)=0; } class room : public virtual CORBA::Object { ... } - 29 - 27 27
Utilisation à partir de C++(1) 3. IDL Utilisation Utilisation à partir de C++(1) interface Calendrier { attribute Annee anneeCourante; IDL exception DateErronnee {String raison; }; boolean verifierUneDate(in Date d); void leJourSuivant(inout Date d); Date convertirChaine (in String uneChaine) raises (DateErronnee); Calendrier_var monCalendrier = … référence; Annee anneeATraiter = monCalendrier -> anneeCourante(); monCalendrier -> anneeCourante(anneeATraiter +1); if (monCalendrier -> verifierDate (uneDate)) { monCalendrier -> leJourSuivant(date); CORBA::String chaine = monCalendrier -> convertirDate (uneDate); try { date = convertirChaine (¨31 fevrier 1998 ¨); } catch (DateErronnee& exception) { cout << exception.raison}; - 30 -
Utilisation à partir de C++(2) 3. IDL Utilisation Utilisation à partir de C++(2) interface Calendrier { …. } IDL typedef sequence <Date> desDates; interface CalendrierFerie : Calendrier { void lesJoursFeries (in Annee UneAnnee, out desDates dates);} CalendrierFerie_var monCalendrierFerie = CalendrierFerie::_narrow (tonCalendrier); desDates datesRepos; monCalendrierFerie -> lesJoursFeries (1998, datesRepos); for (CORBA::Ulong i=0; i< datesRepos.length(); i++){ CORBA::String_var chaine; chaine = monCalendrierFerie -> convertirChaine(datesRepos[i]); } Convertir un type en un sous-type est une opération de narrowing ce qui permet d ’invoquer sur un objets des opérations définies sur un sous-type. Il n ’y a bien sur vérification qu ’à l ’exécution. Dans notre exemple l ’objet tonCalendrier doit être du type CalendrierFerie ou d ’un de ses sous-types. - 31 -
ORBacus ORBACUS is an Object Request Broker (ORB) that is compliant with the Common Object Request Broker Architecture (CORBA) specification (2.4 + features 3) • Full CORBA IDL support • C++ and Java language mappings • Simple configuration and bootstrapping • Portable Object Adapter • Objects by Value • Portable Interceptors • Single- and Multi-threaded • Active Connection Management • Fault Tolerant Extensions • Dynamic Invocation and Dynamic Skeleton Interface •Dynamic Any • Interface and Implementation Repository • Pluggable Protocols • IDL-to-HTML and IDL-RTF documentation tools • Includes Naming, Trading, Event, Notify, Property Services,balancing,… - 32 -
Étapes de mise en oeuvre Spécification interface IDL Compilation interface IDL Implantation des objets Corba Implantation du serveur Implantation du client Enregistrement du serveur Côté client Côté serveur Utilisation du service Nommage - 33 -
Spécification interface IDL (1/2) 1- Exemple introductif Spécification interface IDL (1/2) Un objet grid est un tableau contenant des valeurs. Les valeurs sont accessibles grâce aux opérateurs get et set qui peuvent être invoqués à distance. objets grid Appel de get et set sur l'objet grid distant Processus client Processus serveur - 34 -
Spécification interface IDL (2/2) 1- Exemple introductif Spécification interface IDL (2/2) interface Grid { readonly attribute short height; readonly attribute short width; void set (in short n, in short m, in long value); long get(in short n, in short m); void copyIn(inout Grid g); }; - 35 -
Compilation interface IDL 1- Exemple introductif Compilation interface IDL Grid.idl jidl … Grid.idl A écrire Compilateur IDL/Java Généré Répertoire grid Répertoire grid Répertoire grid Répertoire grid Client Serveur GridOperations.java _GridStub.java GridPOA.java I Grid.java Client.java Grid_Impl.java GridHelper.java Serveur.java GridHolder.java - 36 -
Hiérarchie Java des classes <<Abstraite>> org.omg.CORBA.portableObjectImpl Org.omg.PortableServer.Servant <<Interface>> GridOperations étend étend Implémente <<Interface>> Grid <<abstract>> GridPOA étend _GridStub <<Interface>> Org.omg.CORBA.Object Grid_Impl Standard Généré À implémenter - 37 -
L ’interface Java générée 1- Exemple introductif L ’interface Java générée // Extrait fichier grid.java public interface Grid extends GridOperations, … org.omg.CORBA.Object {} public interface GridOperations{ short height(); void set(short n, short m, int value); short width(); void copyIn(GridHolder g); } Sans readonly :+ void height(short val); - 38 -
Les classes Java communes générées 1- Exemple introductif Les classes Java communes générées Sont également générées les classes : // Classe utilitaire pour le type Grid final public class GridHelper { public static Grid narrow(org.omg.CORBA.Object obj) { …} …..} conversion de type, insertion dans un Any, extraction, obtenir le TypeCode, .. // Classe utilitaire pour le passage out et inout final public class GridHolder implements org.omg.CORBA.portable.Streamable { public Grid value; public gridHolder(Grid initial) { value = initial;} … - 39 -
Les classes Java Stubs et Squelettes 1- Exemple introductif Les classes Java Stubs et Squelettes implantation du stub public class _GridStub extends… implements Grid envoie de requêtes invisible par le programmeur instanciée automatiquement par GridHelper (narrow) Utilise le DII pour assurer la portabilité du binaire implantation du squelette public abstract class GridPOA extends ... implements GridOperations reçoit et décode des requêtes doit être héritée par l’implantation - 40 -
Implémentation de l'interface (Classes servants) 1- Exemple introductif Implémentation de l'interface (Classes servants) Ecrire une classe Java qui hérite de la classeGridPOA public class Grid_impl extends GridPOA { public int [][] valeur; public Grid_impl(short width, short height) { valeur = new int [width] [height]; …….} public int get(short n, short m) { return valeur[n][m]; } public short height(){ return (short) valeur[1].length;} public void copyIn(GridHolder g) ….. g.value.set(i,j,this.valeur[i][j]) ; …} - 41 -
Implémentation du serveur (1) 1- Exemple introductif Implémentation du serveur (1) 1. Initialiser le bus CORBA obtenir l’objet ORB 2. Initialiser l’adaptateur d’objets obtenir le POA 3. Créer les implantations d’objets (servants) 4. Enregistrer les implantations par l’adaptateur 5. Diffuser leurs références afficher une chaîne codifiant l’IOR 6. Attendre des requêtes venant du bus 7. Destruction du Bus - 42 -
Implémentation du serveur (2) 1- Exemple introductif Implémentation du serveur (2) public class ServeurDeGrilles{ public static void main(String args[]) throws Exception { // Propriétés nécessaires à l’utilisation d’ORBACUS java.util.Properties props = System.getProperties(); props.put("org.omg.CORBA.ORBClass", "com.ooc.CORBA.ORB"); props.put("org.omg.CORBA.ORBSingletonClass", "com.ooc.CORBA.ORBSingleton"); // Initialisation du bus CORBA pour un processus serveur. int status = 0; org.omg.CORBA.ORB orb = null; try { orb = org.omg.CORBA.ORB.init(args, props); (1) status = run(orb); (2,3,4,5,6) } catch(Exception ex) { ex.printStackTrace(); status = 1; } if(orb != null) { try { orb.destroy(); (7) } catch(Exception ex) { ex.printStackTrace(); } - 43 -
Implémentation du serveur (3) 1- Exemple introductif Implémentation du serveur (3) public class ServeurDeGrilles{ … static int run(org.omg.CORBA.ORB orb) throws org.omg.CORBA.UserException { org.omg.PortableServer.POA rootPOA = org.omg.PortableServer.POAHelper.narrow( orb.resolve_initial_references("RootPOA")); (2) org.omg.PortableServer.POAManager manager = rootPOA.the_POAManager(); Grid_Impl grilleImpl = new Grid_Impl(100,100); // (3) « création de servants » Grid Grille = Grid_Impl._this(orb); (4) « activation de servants » try { // Obtenir sous forme textuelle l'IOR de l'objet. String chaineIOR = orb.object_to_string (grille); // (5) // . . . diffuser la chaîne . . System.out.println("IOR : " + chaineIOR);. // Mettre le serveur en attente des requêtes venant du bus CORBA. manager.activate(); orb.run(); // (6) } - 44 -
Implémentation du client 1- Exemple introductif Implémentation du client 1. Initialiser le bus (objet ORB) 2. Créer les souches des objets à utiliser 2.a. obtenir les références d’objet (IOR) 2.b. convertir vers les types nécessaires narrow contrôle le typage à travers le réseau 3. Réaliser les traitements Rem. : éviter l’opérateur bind (2.a + 2.b) spécifique à chaque produit donc non portable - 45 -
Implémentation du client en Java 1- Exemple introductif Implémentation du client en Java public class ClientDeGrille { public static void main(java.lang.String[] args) { //………… Comme le serveur avec status = run(orb, args[0]); //IOR est ici passé en argument … static int run(org.omg.CORBA.ORB orb, String ref) { try { org.omg.CORBA.Object obj = orb.string_to_object(ref); // (2.a) Grid grille = GridHelper.narrow(objet); // (2.b) System.out.println(grille.height()); System.out.println(grille.width()); grille.set((short) 2, (short) 4, 123); System.out.println("grid[2,4] is " + grille.get((short)2, (short)4)); } - 46 -
Activation des servants Informer l’ORB de l’existence d’un servant comme « représentant » d’un objet CORBA particulier. L’activation d’un servant lui affecte un object identifier utilisé dans les références qui seront créées. La valeur de IdAssignmentPolicy du POA permet de laisser le POA ou le code de l’application serveur affecter l’Identificateur. La valeur de ImplicitActivationPolicy permet de choisir entre une activation active et une activation passive (NO_IMPLICIT_ACTIVATION/ IMPLICIT_ACTIVATION) Servants must be activated in order to receive requests from clients. Servant activation informs the ORB run time which particular servant represents (or incarnates) a particular CORBA object. Activation of a servant assigns an object identifier to the servant. That object identifier is also embedded in every object reference that is created for an object and serves to link the object reference with its servant. The POA’s IdAssignmentPolicy value controls whether object IDs are assigned by the POA or the server application code. The SYSTEM_ID policy value directs the ORB to assign a unique object identifier to the CORBA object represented by the servant; the USER_ID policy value requires the server application code to supply an ID that must be unique within the servant’s POA. Servants can be activated implicitly or explicitly. Implicit activation takes place when you create the first object reference for a servant. Explicit activation requires a separate API call. Typically, you will use implicit activation for transient objects and explicit activation for persistent objects. To activate a servant, we need the ORB. A servant in Java must be associated with an ORB, and cannot be associated with multiple ORBs. The first call to _this() must supply the ORB reference; subsequent calls to _this() for the same servant can omit the ORB reference. - 47 -
Activation Implicite Si le POA de l’objet servant a les politiques : RETAIN,IMPLICIT_ACTIVATION, et SYSTEM_ID : L’activation implicite est réalisée lors de la première création d’une référence sur le servant: Grid Grille = GridImpl._this(orb); Le nouveau servant est activé (en utilisant le POA renvoyé par _default_POA), qui par défaut renvoie le RootPOA The default implementation of _default_POA always returns the Root POA. If you use POAs other than the Root POA, you must override _default_POA in the servant class to return the correct POA for the servant. If you forget to override _default_POA, calls to _this and several other functions will return incorrect object references and implicitly register the servant with the Root POA as a transient object. Always override _default_POA for servants that do not use the Root POA! If you use multiple ORBs, override it for all servants! - 48 -
Activation explicite de servants Quand le POA d’un Servant est défini avec les politiques : NO_IMPLICIT_ACTIVATION // The code instantiates a servant. I_mpl impl = new I_impl(); // To activate a servant, we need the servant’s POA. orb.omg.PortableServer.POA poa = impl._default_POA(); Et SYSTEM_ID //creates a unique ID for the servant poa.activate_object(impl); Et USER_ID byte[] id = "MyObjectName".getBytes(); poa.activate_object_with_id(id, impl); - 49 -
Désactivation de servants org.omg.PortableServer.POA poa = impl._default_POA(); byte[] id = poa.servant_to_id(impl); poa.deactivate_object(id); A servant can be deactivated. Deactivating a servant breaks the association between the CORBA object and the servant; requests that arrive from clients thereafter result in an OBJECT_NOT_EXIST exception (or a TRANSIENT exception, if the server is down at the time a request is made). - 50 -
Le cycle de vie des objets Problème actuellement, 1 grille = 1 serveur pas de création/destruction d’objets à distance seulement invocation d’opérations Solution notion de fabrique d’objets exprimée en OMG-IDL C’est un canevas de conception : Design pattern voir aussi le service LifeCycle Autres usages de la fabrique : - gestion de droits, load-balancing, polymophisme, … - 51 -
L’implantation de la fabrique creerGrille Grille Grille Fabrique - 52 -
L’implantation de la fabrique Grille Grille Fabrique detruireGrille - 53 -
Interface IDL d ’une fabrique de Grilles module grilles { . . . interface Fabrique { Grid newGrid(in short width,in short height); }; }; - 54 -
Implantation Java de la fabrique de grilles import grille.*; public class Fabrique_impl extends FabriquePOA { org.omg.CORBA.ORB orb_; public Fabrique_Impl (org.omg.CORBA.ORB orb) { orb_=orb; . . .} public Grid newGrid(int width,int height){ Grid_impl gi = new Grid_Impl(width,height); return gi._this(orb_);} } - 55 -
Références interface A{}; interface B { A getA(); } B b = ... // Get a B object reference somehow A a = b.getA(); public class B_impl extends BPOA { org.omg.CORBA.ORB orb_; A_impl a_; public B_impl(org.omg.CORBA.ORB orb) { orb_ = orb; a_ = new A_impl();} A getA() { return a_._this(orb_);} } - 56 -
Références et strings Service de nommage Vous pouvez convertir toute référence en une string et inversement pour par exemple: le serveur créé un objet et écrit sa référence dans un fichier String ref = orb.object_to_string(grille); String refFile = « Grid.ref » ; FileOutputStream file = new FileOutputStream(refFile); PrintWriter out = new PrintWriter(file); out.println(ref); out.flush(); file.close(); Le client lit le fichier et utilise la référence pour accéder à l’objet. FileInputStream file = new FileInputStream(refFile); string ref = new BufferedReader ( new InputStreamReader(file)).readLine(); file.close(); org.omg.CORBA.Object obj = orb.string_to_object(ref); Stockage dans une BD Service de nommage - 57 -
Référence et URL 1 // Java 2 import java.io.*; 3 import java.net.*; 4 5 String location = "http://www.mywebserver/object.ref"; 6 org.omg.CORBA.ORB orb = ... // Get a reference to the ORB somehow 7 8 URL url = new URL(location); 9 URLConnection conn = url.openConnection(); 10 BufferedReader in = new BufferedReader( 11 new InputStreamReader(conn.getInputStream())); 12 String ref = in.readLine(); 13 in.close(); 14 It is sometimes inconvenient or impossible for clients to have access to the same file system as the server in order to read a stringified object reference. A more flexible method is to publish the reference in a file that is accessible by clients as a URL. Your clients can then use HTTP or FTP to obtain the contents of the file, freeing them from any local filesystem requirements. This strategy only requires that your clients know the appropriate URL, and is especially suited for use in applets. Note: This example is shown only in Java because of Java’s built-in support for URLs, but the strategy can also be used in C++. - 58 -
Références et strings Les références sous la forme de string sont « interopérables » et peuvent être échangées entre des clients et serveurs utilisant différents ORBs. Les références Nil peuvent être mises sous forme de string. Vous devez les considérer comme « opaques » : Ne jamais les comparer pour déterminer si elles correspondent à un même objet Ne pas les utiliser comme des clefs dans une BD Mais vous pouvez : Les stocker pour les retrouver plus tard, Les reconvertir en référence par string_to_object - 59 -
Services initiaux : références Services initiaux : ensemble de services uniques dont la référence peut être obtenue par l’opération resolve_initial_references : // IDL module CORBA { interface ORB { typedef string ObjectId; exception InvalidName {}; Object resolve_initial_references( in ObjectId identifier) raises(InvalidName);}; }; Noms standardisés par exemple: NameService et TradingService. - 60 -
Scénario d ’obtention de la référence du service de nommage Client ou Serveur ORB resolve_initial_references ("NameService"); CosNaming:: NamingContext conversion ajout,retrait,lecture,... - 61 -
Obtenir le service de Nommage en Java import org.omg.CosNaming.*; ... //retrouver la référence de l ’objet notoire « NameService » org.omg.CORBA.Object objRef = null; try { objRef = orb.resolve_initial_references ("NameService"); } catch( org.omg.CORBA.ORBPackage.InvalidName e ) { outils.ARRET ("Le service initial NameService est inconnu"); } //la convertir en une référence à un objet //de type CosNaming::NamingContext NamingContext nsRef = NamingContextHelper.narrow(objRef); if ( nsRef == null ) { outils.ARRET ("Le service initial 'NameService' n'est pas un objet CosNaming::NamingContext"); SERVICES INTIAUX : NameService, PropertyService, EventService - 62 -
Notion de chemin d’accès - 63 -
Créer un nom/chemin en Java import org.omg.CosNaming.*; //créer un chemin simple NameComponent[] nsNom = new NameComponent [1]; nsNom[0] = new NameComponent( "grilleA ", ""); //créer un chemin composé NameComponent[] nsNom = new NameComponent [2]; nsNom[0] = new NameComponent( "appli", ""); nsNom[1] = new NameComponent( "grille ", ""); - 64 -
Enregistrer un objet Opération pour publier un Objet en général, opération réalisée par le serveur Scénario Type 1. Créer un objet 2. Construire un chemin d ’accès (Name) 3. Appeler l ’opération « bind » ou « rebind » avec le chemin et la référence de l ’objet void bind (in Name n, in Object obj) raises (NotFound, CannotProceed, InvalidName, AlreadyBound); - 65 -
Enregistrer un objet en Java //créer un chemin NameComponent[] nsNom = new NameComponent [1]; nsNom[0] = new NameComponent("MONOBJET",""); //enregistrer l ’objet try { nsRef.bind (nsNom, uneRefObjet); } catch (org.omg.CosNaming.NamingContextPackage.NotFound enf) { . . . } catch(org.omg.CosNaming.NamingContextPackage.AlreadyBound eab){ } catch(org.omg.CosNaming.NamingContextPackage.CannotProceed ecp){ } catch(org.omg.CosNaming.NamingContextPackage.InvalidName ein) { - 66 -
Retrouver un objet Opération réalisée par un client ou un serveur Scénario type : construire un chemin d ’accès (Name) appeler l ’opération « resolve » avec le chemin convertir la référence obtenue dans le bon type Object resolve (in Name n) raises (NotFound, CannotProceed, InvalidName) - 67 -
Retrouver un objet en Java //créer un chemin NameComponent[] nsNom = new NameComponent [1]; nsNom[0] = new NameComponent("MONOBJET",""); //retrouver l ’objet org.omg.CORBA.Object objRef = null; try { objRef = nsRef.resolve (nsNom); } catch (org.omg.CosNaming.NamingContextPackage.NotFound enf) { . . . } catch(org.omg.CosNaming.NamingContextPackage.CannotProceed ecp){ } catch (org.omg.CosNaming.NamingContextPackage.InvalidName ein) { } //convertir la référence Grille uneRefObjet = GrilleHelper.narrow (objRef); - 68 -
Une application d’administration de la fabrique Création d’une nouvelle fabrique de grilles et mise à disposition par le service Nommage 1. Initialiser le bus CORBA 2. Initialiser l’adaptateur d’objets 3. Créer la fabrique 4. Obtenir le service Nommage (NS) 5. Créer un répertoire (contexte) 6. Enregistrer le couple fabrique/répertoire dans le NS - 69 -
Serveur Java de la fabrique import org.omg.CORBA.*; // le bus CORBA. import org.omg.CosNaming.*; // le service Nommage. public class ServeurFabrique { public static void main(String args[]) throws Exception { … (1) (2) status = run(orb); } static int run(org.omg.CORBA.ORB orb)… {FabriqueImpl fabrique = new FabriqueImpl(); // (3) NamingContext nc = NamingContextHelper.narrow( // (4) orb.resolve_initial_references ("NameService")); NameComponent[] nom = new NameComponent[1]; // (5) nom[0] = new NameComponent("FABRIQUE", ""); nc.rebind(nom,fabrique); // (6) - 70 -
Client de la fabrique public class Administration { public static void main(String args[]) throws Exception { ORB orb = ORB.init (args,null); // (1) NamingContext nc = NamingContextHelper.narrow( // (2) orb.resolve_initial_references ("NameService")); NameComponent[] nsNom = new NameComponent [1]; nsNom[0] = new NameComponent("FABRIQUE",""); org.omg.CORBA.Object objet=nc.resolve(nsNom); //(3.a) Fabrique fabrique=FabriqueHelper.narrow(objet);//(3.b) Grid g = fabrique.newGrid( 4,4); // (4) nsNom[0] = new NameComponent( "Grille4x4",""); nc.bind (nsNom, g); // (5) } - 71 -
Conclusion CORBA : ça marche et c’est simple Choisir son langage d’implantation C++ : complexe et moins portable Java : portable et plus lent Choisir son bus 1 bus = 1 bibliothèque mixer les bus : c’est possible Expérimentez en TPs ! - 72 -
Disponibilité de Orbacus Bus CORBA: ORBacus <URL:http://www.ooc.com> MICO <URL:http://www.vsb.cs.uni-frankfurt.de/~mico/> Environnements systèmes : Sun Solaris, Linux, SGI IRIX, HP-UX, AIX, W95/NT …, JDK 1.1.x et 1.2,1.3…1.4… Gratuit avec les sources C++ et java URL : http://corbaweb.lifl.fr - 73 -
3. IDL OMG-IDL : évaluation Bon langage de spécification d’interfaces d’objets Facile à apprendre types de base figés interdiction de sous-typer ou étendre une structure ou union interdiction de surcharge à l’intérieur d ’un module pas de passage d’objets par valeur (disponible en 3.0) pas de sémantique des objets (contraintes, assertions, …) Pas d ’expression possible de la qualité de service pas de notion d’architecture logicielle - 74 - 31 31