1 8. Notion d’adaptateur d’objet
1
8. Notion d’adaptateur d’objet
c 2003 - Raphaël Marvie
2
Principe
Rendre plusieurs objets (Servant) disponibles dans un serveur Chaque objet est associé à une clé unique dans le
serveur Une référence inclut désormais la clé de l’objet
Adaptateur d’objet Aiguillage et lien entre le réseau et les objets Gère les clés associées aux objets et leurs
références Raffinement du Manager
Adaptateur : lien référence / objet d’implémentation Squelette : décodeur de requête pour un objet
c 2003 - Raphaël Marvie
3
Architecture version 8
Proxy
Réseau
ObjectAdaptateur
Servant
Client
Contrat
Servant
Squelette Squelette
c 2003 - Raphaël Marvie
4
Interactions version 8
c 2003 - Raphaël Marvie
5
Côté serveur
Adaptateur d’objet Gestion du accept et du routage des requêtes Connecte les objets et crée leurs références
Squelette de service Défini par rapport au contrat de Servant Décodeur de messages réseau pour un Servant particulier Définition de deux squelettes
Programme serveur Crée un adaptateur d’objet Crée deux squelettes et servants, les enregistre Active l’adaptateur d’objet
c 2003 - Raphaël Marvie
6
Contrats
interface ServiceA {public String hello (String msg) throws Exception ;
public String lower (String msg) throws Exception ;
public String upper (String msg) throws Exception ;
}
interface ServiceB {public boolean isprime (int a) throws Exception ;
public int sqr (int a) throws Exception ;
}
c 2003 - Raphaël Marvie
7
Code Server
public class Server {
public void run () throws Exception {
ObjectAdapter oa = ObjectAdapter.init () ;
SkeletonA skel_a = new SkeletonA (new ServantA ()) ;
oa.register (skel_a) ;
System.out.println (oa.obj2ref (skel_a)) ;
SkeletonB skel_b = new SkeletonB (new ServantB ()) ;
oa.register (skel_b) ;
System.out.println (oa.obj2ref (skel_b)) ;
oa.start () ;
} // rest is unchanged
c 2003 - Raphaël Marvie
8
Code ObjectAdapter (i)
public class ObjectAdapter extends Thread {private static ObjectAdapter ref ;private ServerSocket asock ;private Vector skeletons ;protected ObjectAdapter () throws Exception {
this.skeletons = new Vector () ;this.asock = new ServerSocket (0) ;
}public static ObjectAdapter init () throws Exception {
if (ObjectAdapter.ref == null)ObjectAdapter.ref = new ObjectAdapter () ;
return ObjectAdapter.ref ;}
c 2003 - Raphaël Marvie
9
Code ObjectAdapter (ii)
public String obj2ref (Skeleton obj) {int key = this.skeletons.indexOf (obj) ;if (key == -1)
return null ;String host = null ;try {
host = InetAddress.getLocalHost () .getHostAddress () ;} catch (UnknownHostException uhe) {
return null ;}int port = this.asock.getLocalPort () ;return host + ":" + port + ":" + key ;}
c 2003 - Raphaël Marvie
10
Code ObjectAdapter (iii)
public void run () {try {
while (true) {Socket sock = this.asock.accept () ;BufferedReader in = ...String msg = in.readLine () ;if (msg == null) { // no more to be read
sock.close () ;continue ;
}int key = Integer.parseInt (msg.substring (0,1)) ;
c 2003 - Raphaël Marvie
11
Code ObjectAdapter (iv)
try {Skeleton skel =(Skeleton)this.skeletons.elementAt (key) ;skel.init (sock) ;new Thread (skel) .start () ;} catch (ArrayIndexOutOfBoundsException e) {
sock.close () ;}
}} catch (Exception e) {
return ;}
}}
c 2003 - Raphaël Marvie
12
Interface Skeleton
interface Skeleton extends Runnable {void init (Socket sock) throws Exception ;
}
c 2003 - Raphaël Marvie
13
Code SkeletonA (i)
public class SkeletonA implements Skeleton {private ServantA ref ;public SkeletonA (ServantA s) throws Exception {
this.ref = s ;}public void init (Socket sock) throws Exception {
this.in = ...this.out = ...
}
c 2003 - Raphaël Marvie
14
Code SkeletonA (ii)
public void run () {try {
while (true) {String msg = this.in.readLine () ;if (msg == null) // no more to be read
break ;String res ;switch (msg.charAt (0)) { case ’0’:
res = this.ref.hello (msg.substring (1)) + "\n" ; break ; // etc.
}
c 2003 - Raphaël Marvie
15
Côté client
Modification du proxy Prise en compte des clés d’objets Connexion en deux temps au squelette
Définition d’un Proxy pour chacun des services Deux chaînes Proxy / Skeleton / Servant Fourniture de la référence comme une propriété
Définition de deux programmes clients Chacun utilise un proxy pour un service particulier
c 2003 - Raphaël Marvie
16
Code ProxyA (changes)
public class ProxyA implements ServiceA {private Socket sock ;private BufferedReader in ;private DataOutputStream out ;public ProxyA (String host, int port, String key)
throws Exception {this.sock = new Socket (host, port) ;this.in = ...this.out = ...this.out.writeBytes (key + "\n") ;
}}
c 2003 - Raphaël Marvie
17
Code ClientA (changes i)
public class ClientA {private ServiceA ref ;public ClientA () throws Exception {
this.ref = (ServiceA) this.ref2proxy () ;}public void run (String msg) throws Exception {
System.out.println (this.ref.hello (msg)) ;System.out.println (this.ref.lower (msg)) ;System.out.println (this.ref.upper (msg)) ;
}
c 2003 - Raphaël Marvie
18
Code ClientA (changes ii)
public ProxyA ref2proxy () throws Exception {Properties props = System.getProperties () ;String ref = props.getProperty ("service.reference") ;if (ref == null)
throw new Exception ("no server reference given") ;String parts[] = ref.split (":") ;if (parts.length < 3)
throw new Exception ("malformed reference") ;String host = parts [0] ;int port = Integer.parseInt (parts [1]) ;String key = parts [2] ;return new ProxyA (host, port, key) ;}
}
c 2003 - Raphaël Marvie
19
Bénéfices et limitations
Bénéfices Serveur multi-services et multi-threadé (Skeleton) Identification complète d’un service –
adresse:port:clé Les références sont créées au niveau du serveur
Limitations Comment définir et utiliser des exceptions
applicatives ? Comment simplifier la traduction de référence en
Proxy ?
20
9. Exceptions et traduction référence vers Proxy
c 2003 - Raphaël Marvie
21
Principe
Exceptions Ajout d’un code dans les messages de retour 0 : OK; sinon un numéro d’exception...
Traduction automatique de références en Proxy Extension des références pour contenir le type des
références Contrôle du typage lors de la création du proxy Instanciation et initialisation automatique du Proxy
c 2003 - Raphaël Marvie
22
Architecture version 9
Proxy
Réseau
ObjectAdaptateur
Servant
Client
Contrat
Servant
Squelette Squelette
c 2003 - Raphaël Marvie
23
Interactions version 9
c 2003 - Raphaël Marvie
24Chargement automatique de proxy
Motivations Transformation d’une référence de service distant en proxy Contrôler la conformité entre le type du proxy et du service
Modifications des implémentations Extension des références
Ajout du type du service dans la référence : adresse:port:clé:type Règles de nommage des classes
NomDuServiceProxy, NomDuServiceSkeleton, NomDuServiceServant
Les squelettes fournissent le type du service (pour construire la référence)
Interface de base Proxy implémentée par tous les proxy (pour init )
c 2003 - Raphaël Marvie
25
Opération ref2proxy (i)
public class Util {public static Proxy ref2proxy (String ref)
throws Exception {String parts[] = ref.split (":") ;if (parts.length < 4)
throw new Exception ("malformed reference") ;String host = parts [0] ;int port = Integer.parseInt (parts [1]) ;String key = parts [2] ;String type = parts [3] ;
c 2003 - Raphaël Marvie
26
Opération ref2proxy (ii)
// instanciation du bon proxy (présent dans classpath : convention de nommage)
Class pclass = Class.forName (type + "Proxy") ;
Proxy p = (Proxy) pclass.newInstance () ;
// initialisation
p.init (host, port, key) ;
return p ;
}
}
c 2003 - Raphaël Marvie
27
Interface Proxy
interface Proxy {
public void init (String host, int port, String key) throws Exception ;
}
c 2003 - Raphaël Marvie
28
Côté serveur
Gestion des exceptions Définition des exceptions dans le contrat du service Modification des squelettes pour transférer les
exceptions Ajout de try catch pour les exceptions applicatives Ajout d’un code en début de message réponse réseau
Typage des références Modification des squelettes : fourniture du type du
servant Modification de l’opération obj2ref dans l’adaptateur
d’objet
c 2003 - Raphaël Marvie
29
Contrat ServiceB
public class DivByZero extends Exception {}
interface ServiceB {public boolean isprime (int a) throws Exception;public int sqr (int a) throws Exception ;public int div (int a, int b) throws Exception, DivByZero;
}
c 2003 - Raphaël Marvie
30
Interface Skeleton
interface Skeleton extends Runnable {
void init (Socket sock) throws Exception ;
String type () ;
}
c 2003 - Raphaël Marvie
31
Code ServiceBSkeleton (modifs)
public String type () {return "step9.ServiceB" ;
}public void run () {
…// managing isprime method from ServiceBcase ’0’:
int val0 = Integer.parseInt (msg.substring (1)) ;res = "0" + this.ref.isprime (val0) + "\n" ;break ;
c 2003 - Raphaël Marvie
32Code ServiceBSkeleton (changes ii)
// managing div method from ServiceBcase ’2’:
String args [] = msg.substring (1) .split (" ") ;int arg0 = Integer.parseInt (args [0]) ;int arg1 = Integer.parseInt (args [1]) ;try {
res = "0" + this.ref.div (arg0,arg1) + "\n" ;} catch (DivByZero e) {
res = "1\n" ; // first exception raised}break ;
// etc.}
c 2003 - Raphaël Marvie
33
Code ObjectAdapter
public String obj2ref (Skeleton obj) {int key = this.skeletons.indexOf (obj) ;if (key == -1) return null ;String host = null ;try {
host = InetAddress.getLocalHost () .getHostAddress () ;} catch (UnknownHostException uhe) {
return null ;}int port = this.asock.getLocalPort () ;return host + ":" + port + ":" + key + ":" + obj.type () ;
}
c 2003 - Raphaël Marvie
34
Côté client
Modification des proxy Gestion des exceptions Si code interne supérieur à 0 alors lever
l’exception équivalente Modification des clients
Utilisation de l’opération ref2proxy Plus besoin de préciser le nom du Proxy Utiliser le proxy avec le type de son
interface
c 2003 - Raphaël Marvie
35
Code ServiceBProxy (changes i)
public boolean isprime (int val) throws Exception {
// automatic conversion of int to string
out.writeBytes ("0" + val + "\n") ;
String res = in.readLine () ;
return Boolean.valueOf( res.substring (1))
.booleanValue () ;
}
c 2003 - Raphaël Marvie
36
Code ServiceBProxy (changes ii)
public int div (int a, int b)
throws Exception, DivByZero {
out.writeBytes ("2" + a + " " + b + "\n") ;
String res = in.readLine () ;
if (res.charAt (0) == ’1’)
throw new DivByZero () ;
return Integer.parseInt (res.substring (1)) ;
}
c 2003 - Raphaël Marvie
37
Code ClientB (changes)
public ClientB () throws Exception {
Properties props = System.getProperties() ;
String ref = props.getProperty("service.reference") ;
this.refB = (ServiceB) Util.ref2proxy (ref) ;
}
Exécution avec -D"service.reference=localhost:12345:1:step9.ServiceB"
c 2003 - Raphaël Marvie
38
Bénéfices et limitations
Bénéfices Bénéfices des exceptions sur le code produit Contrôle du typage à l’utilisation des références
Limitations Partage des références compliqué et réduit au
fichier Utiliser facilement plusieurs services dans un
même client ?
39
10. Service de désignation
c 2003 - Raphaël Marvie
40
Principe
Désignation des objets par des noms symboliques
Association : nom symbolique / références Les serveurs enregistrent une référence
avec un nom Les clients recherchent une référence avec
un nom Service notoire : l’annuaire
c 2003 - Raphaël Marvie
41
Architecture version 10
Proxy
Réseau
OAdap…
NommageServant
Client
Contrat
ServiceServant
Squelette Squelette
OAdap…
c 2003 - Raphaël Marvie
42
Interactions version 10
c 2003 - Raphaël Marvie
43
Annuaire
Service au même titre qu’un autre Défini par une interface Hébergé par un serveur Accessible au travers d’un Proxy
Particularités Serveur dédié initialisé sur un port prédéfini
Connaître la machine = point d’entrée du système
Proxy particulier pour simplifier l’utilisation Patron de conception Singleton
c 2003 - Raphaël Marvie
44
Contrat NameService
interface NameService {
public void export (String name, String ref)
throws Exception ;
public String lookup (String name)
throws Exception ;
}
c 2003 - Raphaël Marvie
45
Proxy Naming (extrait)
public class Naming implements NameService {private static Naming ref ;private Naming () throws Exception {
Properties props = System.getProperties () ;String host = props.getProperty ("naming.host") ;// etc.
}public static Naming init () throws Exception {
if (Naming.ref == null)Naming.ref = new Naming () ;
return Naming.ref ;// etc.} // etc.
}
c 2003 - Raphaël Marvie
46
Côté serveur
Diffusion des références Plus d’affichage sur la ligne de commande Export des références de services
Vers une application répartie Le serveur est client du service de nommage Utilisation du proxy de ce dernier
Unique point d’entrée : référence du service de nommage
$ javac -Dnaming.host=localhost step9.Server
c 2003 - Raphaël Marvie
47
Code Server (changes)
public void run () throws Exception {Naming ns = Naming.init () ;ObjectAdapter oa = ObjectAdapter.init () ;ServiceASkeleton skel_a =
new ServiceASkeleton (new ServiceAServant ()) ;oa.register (skel_a) ;ns.export ("ServiceA", oa.obj2ref (skel_a)) ;ServiceBSkeleton skel_b =
new ServiceBSkeleton (new ServiceBServant ()) ;oa.register (skel_b) ;ns.export ("ServiceB", oa.obj2ref (skel_b)) ;oa.run () ;
}
c 2003 - Raphaël Marvie
48
Côté client
Récupération des références Plus de lecture de fichiers texte Lookup des références de service
Vers une application répartie Client est client des services A, B et Nommage Utilisation des proxy de ces trois services
Unique point d’entrée : référence du service de nommage
$ javac -Dnaming.host=localhost step9.Client
c 2003 - Raphaël Marvie
49
Code Client (changes)
public class Client {public Client () throws Exception {Naming ns = Naming.init () ;String ref_a = ns.lookup ("ServiceA") ;this.refA = (ServiceA) Util.ref2proxy (ref_a) ;String ref_b = ns.lookup ("ServiceB") ;this.refB = (ServiceB) Util.ref2proxy (ref_b) ;}// merge of previous clients’ code
}
c 2003 - Raphaël Marvie
50
Bénéfices et limitations
Bénéfices Unique point d’entrée dans le système Partage simplifié des références de services
Limitations On écrit un peu toujours la même chose... On risque à chaque fois de faire des erreurs
(skel/proxy)
51
11. Génération automatique du code technique
c 2003 - Raphaël Marvie
52
Principe
Ne pas écrire ce qui peut être généré On ne va pas toujours écrire la même chose Un proxy et un squelette suivent toujours le même
schéma Quelques mises en oeuvre possibles
Générateur réflexif (par rapport aux interfaces Java)
Réalisation uniforme (mono-langage) Implémentation assez technique
Génération par rapport à des contrats XML implémentation relativement directe (DOM) Permet de gérer plusieurs langages cibles
c 2003 - Raphaël Marvie
53
Règles de génération
Un contrat de service XXX devient 3 classes XXXProxy
Une méthode init pour la connexionUne méthode par méthode du contrat
XXXSkeletonUne méthode run avec un switchUne entrée par méthode du contrat
XXXServantLes méthodes du contrat à compléter
c 2003 - Raphaël Marvie
54
Bénéfices et limitations
Bénéfices : Contrat + générateur Rapidité de développement Proxy, Skeleton,
Servant Il ne reste plus qu’à écrire le code fonctionnel Moins d’erreurs (correspondances, …)
Limitations Ce n’est toujours pas parfait : implémentation
basique Passage de références d’objets distants ? Passage d’objets sérialisés ?
55
Début de conclusions
c 2003 - Raphaël Marvie
56
Constat
Progressivement nous venons de définir un bus logiciel Sa structuration Son utilisation
Un bus logiciel repose essentiellement sur deux concepts La désignation d’un service (les références) La liaison avec un service distant (établir
une connexion)
c 2003 - Raphaël Marvie
57Architecture générale d’un bus logiciel
c 2003 - Raphaël Marvie
58
Premières Conclusions
Bénéfices Abstraction de la préoccupation communication d’une
application Génération du code technique de la préoccupation
automatisable Et maintenant ?
Raffiner le code pour l’optimiser et le rendre plus fiable meilleure structuration des messages réseau (définition d’un
protocole) dépasser la limitation de 10 méthodes par interface permettre le passage de types complexes et références en
paramètres Développement de services de base (comme l’annuaire)
c 2003 - Raphaël Marvie
59
Et après …
Création des objets accessibles à distance
Pool d’objets Assemblage dynamique Adaptabilité Persistance des informations …
c 2003 - Raphaël Marvie
60
Classes d’intergiciels
Objets répartis Java RMI, CORBA, DCOM, .NET
Composants répartis Java Beans, Enterprise Java Beans, CCM
Message-Oriented Middleware (MOM) Message Queues, Publish-Subscribe
Intégration d’applications Web Services
Coordination Accès aux données, persistance Support d’applications mobiles
c 2003 - Raphaël Marvie
61
Propriétés à prendre en compte
Hétérogénéité Hardware Langages Ressources Contexte d’usage
Désignation/localisation Migration Mobilité Ubiquité
Mireille Blay-Fornarino
DistributionEquilibrage de chargeParallelisationDecentralisation
Prise de décision Contrôle de l’accès concurrentClients simultanésServeurs parallèlesDonnées réparties synchronisation de l'accès aux ressources, Gestion des transactions
c 2003 - Raphaël Marvie
62
Propriétés à prendre en compte
Sécurité authentification (certificats) sécurisation des communications (cryptage) contrôle d’accès (autorisation)
Dimensionnement croissance du nombre de clients
« duplication des serveurs », « gestion de caches » gigantesque quantité de données
Tolérance aux fautes site en panne ou inaccessible « redondance des serveurs » « fonctionnement en mode dégradé »
Mireille Blay-Fornarino
c 2003 - Raphaël Marvie
63
Bibliographie
École d’été sur les Intergiciels et sur la Construction d’Applications Réparties : Patrons et Canevas pour l’IntergicielSacha Krakowiak, ICAR 2003
Dis papa, c’est quoi un bus logiciel réparti [email protected] – IRCICAEquipe GOALDécembre 2003