1. Assemblage par vues de composants
logiciels
Alexis M ULLER
Mémoire de DEA Informatique - Équipe GOAL
Laboratoire d’Informatique Fondamentale de Lille
Alexis.Muller@lifl.fr
2.
3. Remerciements
Je tiens à remercier ici toutes les personnes qui m’ont permis de réaliser ce mémoire ainsi que toutes
celles qui le liront.
Je remercie donc Jean-Marc Geib, pour m’avoir permis d’effectuer mon stage de DEA dans son équipe.
Je tiens à remercier tout particulièrement mes responsables, Olivier Caron, Bernard Carré et Gilles Van-
wormhoudt pour ce qu’ils m’ont appris du métier de chercheur et pour toute la précieuse aide qu’ils m’ont
apporté.
Merci également à Jean-Luc Dekeyser pour m’avoir permis d’effectuer ce DEA.
Merci aussi à toute l’équipe GOAL, ceux de mon bureau (Jean-François Roos, Bassem Kosayba, Em-
manuel Renaux et Olivier Caron) et les autres, pour leur accueil et pour leur(s) machine(s) à café.
Enfin merci à mes camarades de DEA, particulièrement Florent Fareneau, Stéphane Patureau et Patrick
Tessier d’avoir supporté mes blagues à l’heure du midi, ainsi que Jérémie Hattat pour avoir été mon binome
au premier semestre et pour nos soirées passées à . . . travailler.
9. Introduction
Il existe aujourd’hui plusieurs modèles technologiques de composants : CCM (OMG), EJB, .NET, ...
Le problème de l’hétérogénéité de ces modèles se pose aujourd’hui et une recherche consiste à définir un
modèle abstrait commun de composants et d’assemblage par contrats, comportant des spécifications de
haut niveau, indépendantes des plates-formes technologiques.
Les moyens d’expression de l’assemblage, pour spécifier un système d’information dans son entier,
restent assez pauvres et l’assemblage n’est généralement pas représenté. Le contrat d’assemblage d’un
composant se limite souvent à une interface de services unitaires. Nous proposons ici une approche de la
problématique de l’assemblage, guidée par la conception par vues de systèmes d’information (SI).
Ce mode de conception favorise le découpage fonctionnel de SI en rapport avec un référentiel d’enti-
tés qui le caractérise. Chaque vue décrit une fonction du système. Par exemple, un système d’information
d’entreprise peut se décomposer en grandes fonctions : comptable, commerciale, décisionnelle, ... Les sys-
tèmes de vues ont été très étudiés dans le monde des bases de données à objets, en particulier dans l’équipe
[1]. Il s’agit ici de structurer modulairement le schéma du système d’information en schémas vues (corres-
pondant aux fonctions du système), d’en gérer la cohérence et les interactions. Une telle conception vise la
traçabilité des besoins fonctionnels (localisés dans les vues correspondantes) et l’évolution du système par
greffage de nouvelles vues.
Ces qualités sont pour beaucoup communes aux deux approches et l’idée consiste à faire le lien entre la
notion de vues fonctionnelles et la notion de composants métiers et d’appliquer les principes de composition
de vues au problème de l’assemblage de tels composants. Les bénéfices espérés sont réciproques. Les
composants apportent leurs propriétés d’autonomie, d’auto-description, de réutilisation et de dynamicité.
La conception par vues apporte quant à elle des règles d’assemblage de vues métiers pour former un SI
dans son entier.
Dans un premier temps nous présentons, brièvement, les notions de composants et de vues, position-
nons notre travail dans ce paysage et introduisons les notions de modèle, méta-modèle et l’approche MDA.
Nous détaillons ensuite, dans le deuxième chapitre, le modèle abstrait et le méta-modèle virtuel que nous
avons réalisés. Les chapitres suivants présentent respectivement leur mise en œuvre par le profil UML
correspondant et le ciblage de l’exemple vers les plates-formes EJB et CCM (IDL3). Enfin, nous discu-
tons des perspectives d’évolutions de notre approche que nous pouvons attendre du travail sur le MDA,
notamment la version 2.0 d’UML, qui doit introduire la notion de composant, ainsi que les techniques de
transformation de modèles.
5
11. Chapitre 1
Problématique et positionnement
1.1 Composants, ACCORD
L’origine des composants logiciels n’est pas nouvelle. Certains pensent qu’ils ont toujours existé sous
différentes formes pour la construction de systèmes logiciels [2]. Pour d’autres cette notion est apparue
dans les années 70 en réponse à la deuxième crise du logiciel afin de réduire les coûts et d’améliorer la
qualité des logiciels [3].
L’idée des composants logiciels s’inspire largement de ce qui existe dans les autres domaines industriels
(électronique, automobile...), le but est de pouvoir concevoir une application par assemblage comme on
assemble un téléviseur ou une voiture, à l’aide de composants existants en limitant les développements
spécifiques au strict minimum. Si cette capacité de réutilisation avait été attribuée à la programmation
objet, du fait du très bas niveau de mise en œuvre (celui du code source), elle n’a jamais pu être réellement
utilisée sauf pour des structures de données simples (listes, piles, ...) ou pour des traitements très “standard”
(comme les services objets communs de CORBA [4]) ainsi que dans le domaine des interfaces hommes-
machines (IHM). En se plaçant à un niveau de granularité beaucoup plus important, la conception par
composants logiciels doit permettre la réutilisation de structures plus complexes et ce de façon naturelle
en les rendant disponibles le plus tôt possible dans le cycle de vie. Ce type de composants, suffisamment
complexes pour contenir un certain “savoir faire”, est appelé composant métier. Ce sont eux qui nous
semblent le plus intéressant et que nous considérons dans notre approche.
Les bénéfices attendus sont multiples :
– Diminuer considérablement les coûts et le temps de conception en généralisant la réutilisation ou
l’achat de composants déjà réalisés.
– Augmenter la fiabilité des logiciels par l’utilisation de composants largement testés.
– Faciliter et réduire les coûts de maintenance et d’évolution des systèmes, par le remplacement de
composants.
– Enfin, rentabiliser les développements par la vente de COTS Component (Commercial-off-the-shelf
Component ou composants sur étagère).
Il n’y a pas encore de définition consensuelle dans le domaine des composants comme c’est le cas pour les
objets. Cependant, la vision minimale suivante est toujours retenue. Un composant logiciel est une unité qui
rend des services grâce à des interfaces externes et utilise d’autre services grâce à des interfaces requises.
Afin d’obtenir un système complet il faut donc assembler un certain nombre de composants en reliant leurs
interfaces externes et leurs interfaces requises.
C’est pour cette phase d’assemblage qu’il reste encore beaucoup de problèmes à résoudre. Comment
formaliser les connexions entre les composants ? Comment décrire un système dans son ensemble ? Il
existe pour répondre à ces questions plusieurs travaux de recherche notamment sur les ADL (Application
Definition Language) [5]. Cependant, ils imposent l’utilisation (et donc l’apprentissage) de leur propre
langage. D’autres problèmes sont à résoudre si l’on souhaite réellement profiter de la grande promesse
7
12. 8 Chapitre 1. Problématique et positionnement
des composants, c’est à dire la réutilisation. En effet, il faut être capable de choisir les composants qui
répondent à nos besoins et de savoir si ils sont “compatibles”. Actuellement, la description d’un composant
est le plus souvent résumée à la liste de ses interfaces, ce qui est insuffisant pour espérer “comprendre” le
composant. Il devient donc indispensable de développer la notion de contrat. Ces contrats doivent décrire
les besoins et capacités d’un composant, mais il n’existe pas encore de méthode formelle pour les spécifier.
De plus, les méthodes de conception actuelles ne sont pas adaptées [3], elles poussent le plus souvent à
spécifier des composants alors qu’ils sont, la plupart du temps, déjà disponibles.
Pour répondre à ces problèmes et du fait de l’hétérogénéité des modèles technologiques de composants,
une recherche consiste à définir un modèle abstrait commun de composants et d’assemblage par contrats.
L’équipe participe à ce titre à un projet national (RNTL ACCORD pour “Assemblage de Composants par
Contrats en environnement Ouvert et Réparti”) visant à définir un tel modèle abstrait et ses projections
technologiques, en particulier vers CCM et EJB.
Pour qu’un modèle de composants permette réellement la réutilisation, il doit fournir les moyens de
spécifier des composants génériques et de représenter leur configuration. La généricité est le concept par
lequel un composant peut être défini indépendamment des contextes dans lesquels il sera utilisé. La confi-
guration, au contraire, permet d’intégrer le composant dans un contexte particulier. Il apparaît donc que ces
deux concepts soient indissociables et indispensables.
1.2 Vues, SOP / AOP, Catalysis
Dans l’approche CROME [1] qui constitue le point de départ de ce mémoire, le mécanisme des vues
permet à chaque utilisateur de manipuler un système avec une vision qui lui est propre, adaptée en fonction
de ses besoins. Dans cette approche, le schéma de base correspond aux éléments communs aux différentes
fonctions du système. Les schémas vues quant à eux ajoutent au schéma de base un certain nombre d’élé-
ments propres à leur fonction. Cette approche permet de tenir compte de l’orthogonalité objets/fonctions.
En effet, pour un système donné les objets peuvent intervenir dans plusieurs fonctions et celles-ci peuvent
utiliser un certain nombre d’objets. Mais il est évident que tous les objets n’interviennent pas dans toutes les
fonctions de même les fonctions n’utilisent pas systématiquement tous les objets [6, 7]. Si l’approche objet
permet de découper naturellement le système en entités distinctes, elle ne permet pas de séparer les diffé-
rentes fonctions à l’intérieur des objets. Le mécanisme des vues ajoute ce découpage et rend ainsi possible
de concevoir les fonctions du système indépendamment des autres tout en garantissant leur compatibilité.
Pour illustrer cette orthogonalité, considérons l’exemple d’un système de location de voitures (cf figure
1.1). Grâce à l’approche objet, le découpage en entités distinctes est bien représenté, mais toutes les fonc-
tions sont confondues. L’activité de gestion des voitures (transfering, add, remove) , par exemple, n’a pas
d’intérêt à considérer la liste des clients. De même, l’activité consistant à rechercher à quelle agence est rat-
tachée un client ne doit pas être perturbée par la durée ou le nombre de locations de celui-ci. Une approche
“à la CROME” permet de séparer les fonctions du système et permet de les réaliser indépendamment les
unes des autres (cf figure 1.2). Les attributs communs à toutes les fonctions sont déclarés dans le plan de
base, les autres attributs et méthodes sont déclarés dans le plan où ils sont utilisés. Prenons en exemple la
classe Agency, les attributs Name et adresse, qui sont utiles à toutes les fonctions du système, sont déclarés
dans le plan de base. L’attribut capacity et les méthodes add, transfering et remove, qui ne servent qu’à la
gestion des ressources, sont déclarés dans le plan correspondant.
D’autres approches comme l’AOP [8] (Aspect-Oriented Progamming) ou le SOP [9] (Subject-Oriented
Programming) permettent de mieux découper les systèmes en “séparant les préoccupations” (sécurité, au-
thentification...). Elles suggèrent de développer séparément les différentes fonctions du système puis de
les assembler, cette étape est appelée le tissage. Contrairement à la conception par vues, qui s’applique au
niveau conception, la programmation par aspects (comme son nom l’indique) est destinée à être utilisée
au niveau des langages de programmation. Clarke [9] propose le découpage d’un système en activités au
niveau modèle, à l’aide du langage UML. Chaque activité est représentée par un paquetage indépendant.
Celui-ci contient uniquement les éléments nécessaires à son activité. Contrairement à l’approche par vues,
il n’y a pas de paquetage de référence, si un élément est utile à plusieurs paquetages, il est représenté dans
chacun d’eux. L’application complète peut être retrouvée par “l’assemblage” de tous les paquetages au
travers d’un jeu d’opérateurs de composition (override, merge, ...), la correspondance entre les différents
13. 1.2. Vues, SOP / AOP, Catalysis 9
Base
Agency Client
Name Name
adresse date
own 0..*
capacity phone
adresse
Client* findAll()
Car* findAll() Agency location()
void transfering(Client c) Client findByDate()
void add(Agency a) Client findByName()
void remove(Agency a) int nbRenting()
manage
0..*
reference
Car
immatriculation
0..*
date
constructor Rent
model From
Agency location() due_date
Car findByDate() contain return_date
0..*
Car findByImmatriculation()
int nbRenting()
bool free(date from, date to)
F IG . 1.1 – Location de voitures - Approche objet
14. 10 Chapitre 1. Problématique et positionnement
Agency Client Car Rent
att: Name, att: Name, att: date, model,
Plan de date, phone,
base adresse immatriculation,
adresse constructor
Plan de mth: findAll mth: location,
recherche findByDate,
client findByKey
Plan de mth: findAll mth: location,
recherche findByDate,
voiture findByKey
Plan de att: capacity
gestion des mth: add,
resources transfering,
remove
Plan de mth: free, att: att: From,
locations nbRenting maximum_ due_date,
duration return_date
mth: nbRenting
F IG . 1.2 – Location de voitures - Structuration par contextes
éléments étant indiquée grâce à un nommage identique dans les différents paquetages. Dans l’approche
Catalysis [10], il est également question de découpage fonctionnel. Elle propose le découpage d’un schéma
UML (par exemple, d’un système de ventes) en “composants à gros grains” (paiement, base de contact,
vente...). D’après les auteurs, avant de penser à réutiliser des composants existants, nous avons besoin d’un
modèle spécifiant ce qu’ils font. Malheureusement, actuellement ils ne sont jamais accompagnés d’un tel
modèle. L’approche Catalysis diffère de celles de CROME et de [9] par le fait que le découpage n’est pas
effectué au niveau des attributs et des méthodes, mais au niveau des classes dans leur intégralité. L’assem-
blage des composants est modélisé par les associations qui traversent les frontières des ces composants,
c’est à dire, par les associations entre des classes ne faisant pas partie du même composant.
Toutes ces approches permettent de mieux structurer le système en fonction de ses activités, mais
n’apportent rien au niveau de la généricité. Il n’y a pas de réutilisation dans ces méthodes, tout doit être
réévalué d’un système à l’autre.
1.3 Rapprochement vues/composants
Nous proposons de considérer les approches composants et vues dans un même modèle, la première
apportant le principe de généricité et de configuration, la seconde, une méthode de structuration cohérente
et plus riche que l’approche objet traditionnelle. Pour illustrer les bénéfices d’une telle approche, considé-
rons l’exemple d’une bibliothèque universitaire (cf figure 1.3). Il est possible de découper ce système en
contextes comme nous l’avons fait pour l’exemple précédent (cf figure 1.4). Il apparaît ici clairement qu’un
certain nombre de fonctions sont communes aux deux systèmes, même s’ils utilisent des noms différents,
et qu’il serait intéressant de pouvoir disposer de composants génériques pour les implémenter.
L’approche conception par vues permet de représenter un système à base de composants en associant à
chaque composant un schéma vue. Le schéma de base représente le système déjà en place auquel on sou-
haite ajouter des fonctions par application de composants. Dans le cas d’un nouveau système, le schéma de
base peut représenter le cœur de l’application, c’est à dire la partie “stable”, qui a peu de chance d’évoluer
dans le temps.
Notre modèle d’assemblage s’inspire donc largement de la notion de vues, cependant il diffère sur
15. 1.3. Rapprochement vues/composants 11
Base
Location Team
indentifiant name
adresse
capacity
Document* findAll()
void transfering(ResourceOwner o) Researcher
void add(Document r)
name
void remove(Document r)
arrival_date
publishes 1..*
0..* 0..*
Document Rent
Contain 0..*
title From
publication_date due_date
return_date
Location location()
Document findByDate()
Document findByKey()
0..*
int nbRenting()
reference
bool free(date from, date to)
Client
Book Periodical
name
ISBN number inscription_date
int nbRenting()
F IG . 1.3 – Bibliothèque universitaire - Approche objet
Location Client Document Rent
Plan de att: adresse, att: Name, att: title,
base identifiant inscription_ publication_date
date
Plan de mth: findAll mth: location,
recherche findByDate,
document findByKey
Plan de att: capacity
gestion des mth: add,
resources transfering,
remove
Plan de mth: free, att: att: From,
locations nbRenting maximum_ due_date,
duration return_date
mth: nbRenting
F IG . 1.4 – Bibliothèque universitaire - Structuration par contextes
16. 12 Chapitre 1. Problématique et positionnement
<<Component>> Search
<<ViewClass>>
<<ViewClass>> DateResource
Location
identifiant <<ViewAttibute>>
name <<ViewAttribute>> date <<ViewAttribute>>
adresse <<ViewAttribute>>
store 0..*
Location location()
DateResource* findAll()
DateResource findByDate()
DateResource findByKey()
F IG . 1.5 – Composant de recherche
certains points. Contrairement à un schéma vue qui “importe” systématiquement tous les éléments du
schéma de base, un composant vue doit préciser les éléments (classes, attributs, associations) du schéma
de base qu’il souhaite manipuler, il les contextualisent.
L’interface requise correspond donc à un “schéma requis”, celui-ci est matérialisé par les ViewClass,
ViewAttribute et ViewAssociation du composant (cf figure 1.5). Les éléments vues du compo-
sant Search indiquent que celui-ci ne pourra s’appliquer qu’à un schéma de base contenant une classe
(jouant le rôle de location) contenant au moins deux attributs pour matérialiser les ViewAttribute
Name et adresse, et une autre classe (jouant le rôle de DateRessource) avec des attributs matérialisant iden-
tifiant et date. Ces deux classes devant être liées par une association pour matérialiser la ViewAssociation
store. La définition formelle des éléments vues ainsi que les règles auxquelles ils sont soumis sont détaillées
dans le deuxième chapitre de ce mémoire. L’interface externe est quant à elle matérialisée par le schéma
constitué des éléments publiques du composant.
A partir des exemples précédents, il est possible d’extraire trois fonctions communes : recherche, ges-
tion des ressources et location, et d’en faire des composants. Pour cela, il faut les rendre génériques et
pouvoir les configurer afin de les appliquer aux deux exemples. Dans notre modèle, la généricité est intro-
duite par l’utilisation d’éléments “externes” et la phase de configuration est représentée par un mécanisme
de connexion.
Les modèles obtenus pour chacun des deux exemples sont représentés figure 1.6 pour l’agence de
location de voitures et 1.7 pour la bibliothèque universitaire. L’application d’un composant vue à la base se
fait par la connexion entre chaque ViewClass du composant et la classe de la base qui la matérialise. Ces
connexions sont représentées sur les figures par les flèches pointillées. Pour être complètes, les connexions
doivent également être effectuées entre chaque ViewAttribute et l’attribut de la base qui le matérialise,
de même pour les ViewAssociation et les associations (ces connexions ne sont pas représentées par
souci de clarté). Les connexions, pour être valides, doivent vérifier un certain nombre de contraintes. Celles-
ci sont détaillées pour chaque élément vue dans le deuxième chapitre.
On retrouve dans les deux exemples les mêmes composants fonctionnels Search, ResourceManager et
Renting, ce qui illustre leur réutilisation sur différentes bases. La généricité permet également d’utiliser le
même composant à plusieurs “endroits” de la même application, illustré ici par l’application du composant
Search entre Agency et Car et entre Agency et Client dans le premier exemple. De façon conforme à
l’approche par vues, les données spécifiques à une fonction particulière du système sont regroupées dans le
composant correspondant (la classe Rent par exemple fait partie du composant Renting et non de la base).
17. 1.3. Rapprochement vues/composants 13
<<Component>> Search
<<ViewClass>>
<<ViewClass>> DateResource
Location
identifiant <<ViewAttibute>>
name <<ViewAttribute>> <<ViewAssociation>> date <<ViewAttribute>>
adresse <<ViewAttribute>>
store 0..* Location location()
DateResource* findAll() DateResource findByDate()
DateResource findByKey()
<<Component>> Search <<Component>> ResourceManager
Base
<<ViewClass>>
<<ViewClass>>
ResourceOwner
Location Client
Agency
identifiant <<ViewAttribute>>
name <<ViewAttribute>> Name
Name own capacity
0..* date
adresse <<ViewAttribute>>
adresse
phone void transfering(ResourceOwner o)
DateResource* findAll()
adresse void add(Resource r)
<<ViewAssociation>>
void remove(Resource r)
store
manage
0..* <<ViewAssociation>>
0..*
<<ViewClass>> manage
Car
DateResource 0..*
immatriculation
identifiant <<ViewAttibute>>
date <<ViewClass>>
date <<ViewAttribute>>
constructor Resource
Location location() model identifiant <<ViewAttribute>>
DateResource findByDate()
DateResource findByKey()
<<Component>> Renting
Rent
From
due_date
return_date
0..* 0..*
contain reference
<<ViewClass>> <<ViewClass>>
Product Client
identifiant <<ViewAttribute>> identifiant <<ViewAttibute>>
maximum_duration
int nbRenting()
bool free(date from, date to) int nbRenting()
F IG . 1.6 – Location de voitures - Approche composants vues
18. 14 Chapitre 1. Problématique et positionnement
<<Component>> ResourceManager
<<ViewClass>>
ResourceOwner <<ViewClass>>
<<ViewAssociation>> Resource
identifiant <<ViewAttribute>>
capacity identifiant <<ViewAttribute>>
store 0..*
void transfering(ResourceOwner o)
void add(Resource r)
<<Component>> Search void remove(Resource r)
<<ViewClass>> Base
Location
name <<ViewAttribute>>
adresse <<ViewAttribute>> Location
Team
DateResource* findAll() indentifiant
adresse name
<<ViewAssociation>>
store
0..*
<<ViewClass>> 0..*
DateResource Researcher
Document
identifiant <<ViewAttribute>> name
title 0..* publishes 1..*
date <<ViewAttribute>> arrival_date AddToBase
publication_date
Location location()
Client
DateResource findByDate()
DateResource findByKey() name
inscription_date
Book Periodical
ISBN number
<<Component>> Renting
Rent
From
due_date
return_date
0..* 0..*
contain reference
<<ViewClass>>
<<ViewClass>>
Product
Client
identifiant <<ViewAttribute>>
identifiant <<ViewAttibute>>
int nbRenting()
int nbRenting()
bool free(date from, date to)
F IG . 1.7 – Bibliothèque universitaire - Approche composants vues
19. 1.4. Modèle, Méta-Modèle, MDA 15
Il existe des entités qui
Niveau M3 Méta-méta-modèle peuvent avoir des relations
entre elles
Une classe désigne un
Niveau M2 Méta-modèle ensemble d’objets qui peuvent
avoir des attributs
Une voiture a une couleur
Niveau M1 Modèle et une immatriculation
Cette voiture
Niveau M0 Instances rouge immatriclée
12 XY 59
F IG . 1.8 – Les quatre niveaux de modélisation
1.4 Modèle, Méta-Modèle, MDA
Nous décrivons notre modèle abstrait à l’aide d’un méta-modèle, nous introduisons donc ici les bases
des techniques de modélisation et de méta-modélisation avant de le détailler. Les méthodes de méta-
modélisations sont basées sur quatre couches [11] (cf figure 1.8). Chaque niveau est décrit à l’aide du niveau
supérieur. Le niveau M0 correspond à celui des instances, aux données réellement manipulées. C’est, par
exemple, à ce niveau qu’est décrit une voiture particulière, immatriculée ’12 XY 59’, de couleur rouge...
Le niveau M1 est celui des modèles, c’est lui qui est utilisé pour concevoir un logiciel. Un diagramme écrit
en UML correspond à ce niveau. Pour reprendre notre exemple, c’est le niveau qui définit le type voiture,
qu’elle doit avoir une immatriculation, une couleur... On ne décrit pas une voiture en particulier mais son
concept. Le niveau M2 est le niveau des méta-modèles, c’est par exemple à ce niveau qu’est décrite la
syntaxe du langage UML, le fait qu’une classe a un nom, qu’elle est composée d’attributs... Le dernier
niveau, M3, a la particularité de se décrire lui même. Il serait sinon possible d’avoir une infinité de niveaux.
Ce niveau est celui des méta-méta-modèles, c’est certainement le niveau le plus difficile à comprendre. Il
permet de décrire le niveau M2, qu’il existe des entités (classes, attributs...) qui peuvent avoir des relations
entre elles. Pour résumer, on peut dire que le niveau M0 correspond à une application en cours d’exécution,
le niveau M1 au schéma UML d’une application en particulier, le niveau M2 à la façon de représenter une
application en général et enfin le niveau M3 à introduire les concepts nécessaires au niveau M2.
Il existe deux grandes techniques de méta-modélisations, le MOF (Meta Object Facilities) [12] et les
profils UML. Le MOF est un langage de niveau M3, il permet donc d’introduire de nouveaux concepts pour
le niveau M2. La méta-modélisation par profils est une technique plus “légère” prévue par le langage UML,
elle ne permet pas vraiment d’introduire de nouveaux méta-concepts mais de spécialiser, en les étiquetant
par des “stéréotypes”, les méta-concepts existants.
L’approche MDA (Model Driven Architecture) [13, 14, 15] de l’OMG (Object Managment Group) [16]
définit une méthode de conception basée sur les modèles permettant d’obtenir à partir d’un schéma de base
unique sa réalisation sur n’importe quelle plate-forme (supportée par le MDA). La principale motivation
est de rester indépendant d’un système donné afin de suivre l’évolution des technologies et des intergiciels
sans perdre ce qui a déjà été réalisé.
Pour obtenir ce résultat, le MDA introduit deux types de modèles : les PIMs (Platform Independent
Model) qui doivent représenter l’application en utilisant uniquement des concepts indépendants de toutes
plates-formes, et les PSMs (Platform Specific Model) qui sont des projections des PIMs pour une plate-
forme donnée. Nous avons réalisé dans le cadre du projet ACCORD un état de l’art de l’approche MDA,
celui-ci est disponible en annexe de ce mémoire.
En proposant une approche qui définit un modèle de composants abstraits (PIM) tout en permettant sa
projection vers des plates-formes existantes (PSM), nous respectons la philosophie du MDA. De plus, en
utilisant l’UML et les profils, nous sommes “compatibles” avec les choix technologiques de l’OMG, ce
qui facilite l’utilisation de notre modèle (outils, XMI...). La figure 1.9 illustre l’articulation des différents
modèles dans notre approche. L’interconnexion de nos composants au niveau PIM permet l’interopérabilité
au niveau binaire.
20. 16 Chapitre 1. Problématique et positionnement
View UML Base UML
connexion
vérification
des contraintes
PIM
PSM
Modèle CCM
avec XML+
associations IDL Java XML
Binaire Binaire Base Binaire Base Binaire
CCM EJB(++) CCM EJB(++) BDR
F IG . 1.9 – Application de MDA
21. Chapitre 2
Le modèle abstrait
2.1 Le méta-modèle
La figure 2.1 représente les concepts du modèle de composant vues. Ce méta-modèle introduit la notion
de connexions entre un élément et sa vue, grâce aux associations viewOf et root.
Les sémantiques de ces deux types de relation sont différentes. Une association viewOf indique que
l’élément source (de type Component ou ViewClass) est une extension de l’élément qu’il désigne
(respectivement de type Package ou Class). Par contre, une association root signifie que l’élément
source (de type ViewAttribute ou ViewAssociation) n’est qu’une représentation de l’élément
désigné (respectivement de type Attribute ou Association).
Dans ce modèle, un composant est donc un ensemble de ViewClass et de Class que l’on peut
appliquer à un ensemble (Package) de Class. Grâce au mécanisme de connexions, un composant peut
être modélisé indépendamment des Package sur lesquelles il sera appliqué. Les seuls règles à suivre
lors de cette phase de modélisation sont décrites par les règles de conception, néanmoins pour que le
système obtenu par la “fusion” des Package et des Component soit cohérent, les règles de connexion
doivent être vérifiées. Ce découpage correspond respectivement aux phases de conception et d’assemblage
du composant. Les contraintes OCL sont présentées pour chacun des concepts à la fin de ce chapitre.
2.2 Description des éléments
Component Un Composant est une spécialisation de la méta-classe UML Package. Son rôle est de
regrouper toutes les ViewClass, Class ainsi que tout autre élément UML nécessaire à la modé-
lisation du composant.
ViewClass Une ViewClass est une spécialisation de la méta-classe UML Classifier. Une instance
de celle-ci peut contenir les mêmes éléments qu’un autre Classifier ainsi que des
ViewAttribute. L’association viewOf (entre une ViewClass et une Class) indique dans
quelle Class les Attribute racine (root) des ViewAttribute de la ViewClass doivent
se trouver.
Pour reprendre l’analogie avec la structuration par contextes, une Class correspond au plan de base
et, une ViewClass qui lui est connectée correspond à son extension dans un autre plan.
ExternalFeature et ExternalStructuralFeature Une ExternalFeature est un élément abstrait consti-
tuant d’un Classifier au même titre qu’une StructuralFeature ou qu’une
BehavioralFeature, son rôle est de désigner, par l’association root, une autre Feature.
L’élément ExternalStructuralFeature spécialise ExternalFeature en imposant une
StructuralFeature comme racine (root).
17
22. 18 Chapitre 2. Le modèle abstrait
Component Package (from UML)
0..*
+viewOf AssociationEnd (from UML)
0..* isNavigable
* Association (from UML)
ordering
Classifier (from UML)
+connection
aggreagation
+participant +association
targetScope
2..*
* * multiplicity
changeability
+specification +specifedEnd
visibility +root
0..1
0..*
0..*
+owner ViewAssociation
+type +feature
Feature (from UML)
ownerScope
ViewClass Class (from UML)
0..* visibility
isActive
+viewOf
connection
0..* +root
0..*
StructuralFeature (from UML)
ExternalFeature
multiplicity
changeability
targetScope
ExternalStructuralFeature
Attribute (from UML)
initialValue
ViewAttribute
F IG . 2.1 – Le méta-modèle
Ce sont les éléments de base de notre modèle, qui permettent “d’importer” des données de l’exterieur
et qui permettent ainsi la conception du composant.
ViewAttribute Un ViewAttribute est un ExternalStructuralFeature dont le lien racine
(root) ne peut porter que sur un Attribute. Un ViewAttribute ne peut appartenir qu’à
une ViewClass.
C’est le seul élément de type ExternalFeature qui ne soit pas abstrait, donc le seul à pouvoir
apparaître dans un modèle de conception.
ViewAssociation Une ViewAssociation est une spécialisation de la méta-classe UML Association.
Une instance de celle-ci permet de contextualiser une Association du Package auquel s’ap-
plique (par le lien viewOf) le Component.
Une ViewAssociation est utilisée dans un composant pour “imposer” et manipuler l’Association
conrrespondante entre les classes de la base.
2.3 Contraintes OCL
ExternalFeature et ExternalStructuralFeature
Contraintes de conception
[1] La racine d’un ExternalStructuralFeature doit être un StructuralFeature.
self.root.oclIsKindOf(StructuralFeature);
23. 2.3. Contraintes OCL 19
ViewClass
Contraintes de conception
[2] Toutes les ViewClass doivent être dans un Component.
self.package.oclIsKindOf(Context);
Contraintes de connexion
[3] Tous les ViewAttribute d’une ViewClass doivent avoir le même propriétaire de leur racine que la
viewOf.
self.allFeatures->select( f | f.oclIsKindOf(ViewAttribute) )
->forAll ( f : ViewAttribute | f.root.owner = self.viewOf );
ViewAttribute
Contraintes de conception
[4] Le propriétaire d’un ViewAttribute doit être une ViewClass.
self.owner.oclIsKindOf(ViewClass);
Contraintes de connexion
[5] Le propriétaire de la racine d’un ViewAttribute doit être une Class.
self.root.owner.oclIsKindOf(Class);
ViewAssociation
Contraintes de conception
[6] Une ViewAssociation ne peut être que dans un Component
self.namespace.oclIsKindOf(Context);
Contraintes de connexion
[7] S’il existe dans le Component une ViewClass dont la viewOf participe à ViewAssociation.root alors
cette ViewClass participe à la ViewAssociation.
self.namespace.allContents->select( v | v.oclIsKindOf(ViewClass) )
->forAll( v : ViewClass | self.root.allConnections->collect( type )
->includes(v.viewOf)
implies self.allConections->collect( type )
->includes(v));
Component
Contraintes de connexion
[8] Toutes les ViewClass d’un Component doivent avoir le même Package de leur viewOf que la viewOf
du Component.
self.allReferencedElements->select( v | v.oclIsKindOf(ViewClass) )
->forAll ( v : ViewClass | v.viewOf.package = self.viewOf );
[9] Il ne peut pas y avoir deux ViewClass de la même Class dans un Component
self.allReferencedElements->select( v | v.oclIsKindOf(ViewClass) )
->forAll ( v1, v2 : ViewClass | not v1.viewOf = v2.viewOf );
24. 20 Chapitre 2. Le modèle abstrait
[10] Si deux ViewClass (v1, v2) sont dans le même Component et qu’il y a une Association entre
v1.viewOf et v2.viewOf alors il y a une ViewAssociation entre v1 et v2
self.allReferencedElements->select( v | v.oclIsKindOf(ViewClass) )
->forAll ( v1, v2 : ViewClass |
v1.viewOf.allAssociations
->intersection(v2.viewOf.allAssociations)->size
= v1.allAssociations->intersection(v2.allAssociations)
->select( va | va.oclIsKindOf(ViewAssociation) )->size);
25. Chapitre 3
Réalisation du Profil UML
Comme il a été présenté dans le premier chapitre, il existe deux méthodes de méta-modèlisation, le
MOF et les profils. Nous présentons ici la réalisation de notre modèle abstrait grâce aux profils. Vous pour-
rez trouver en annexe, la réalisation de celui-ci avec l’outil Objecteering de la société Softeam, partenaire
du projet ACCORD. Actuellement, le langage OCL n’est pas supporté par cet outil, les contraintes ont
donc été traduites en J1 , le langage spécifique à Objecteering. Le module résultant de cette réalisation (cf
figure 3.7), utilisable avec la version gratuite d’Objecteering, est disponible en ligne.
(http ://www.lifl.fr/ mullera/ViewComponents.prof).
3.1 Identification du sous-ensemble UML
Le profil de composant vues étend le paquetage UML core en se basant sur les méta-classes suivantes :
– Package
– Classifier
– Feature
– Class
– StructuralFeature
– Attribute
– Association
– Dependency
3.2 Les éléments du profil
Les ExternalFeature et ExternalStructuralFeature sont représentées dans notre profil UML par une
Feature stéréotypée respectivement par «ExternalFeature» et
«ExternalStructuralFeature».
La valeur marquée de nom root s’applique au stéréotype «ExternalFeature» ainsi qu’aux
stéréotypes héritant de celui-ci («ExternalStructuralFeature» et «ViewAttribute»).
La valeur de type chaîne de caractères associée à ce tag contient le nom de la Feature racine de
l’élément. Cette valeur marquée est indispensable pour représenter la connexion.
Une ViewClass est représentée dans notre profil par une Class stéréotypée par «ViewClass». L’as-
sociation entre une ViewClass et la Class à laquelle elle se réfère est représentée par une
Dependency entre elles stéréotypée par «viewOf».
1 Disponible en annexe
21
26. 22 Chapitre 3. Réalisation du Profil UML
Stéréotype s’applique à Définition
«ExternalFeature» Feature Indique que la Feature est
externe.
«ExternalStructural Feature Spécialise «ExternalFeature».
Feature» Indique que la racine porte
sur un élément structurel.
Tag s’applique à Définition
root «ExternalFeature» Nom d’une Feature
Désigne la racine de l’élément.
TAB . 3.1 – Stéréotypes et valeurs marquées pour les méta-types ExternalFeature et
ExternalStructuralFeature.
<<baseElement>> Feature
{From UML}
«stereotype»
ExternalFeature
<<tagged value>> root: string
<<baseElement>>
«<<stereotype>>»
ExternalStructuralFeature
<<baseElement>>
«stereotype»
ViewAttribute
F IG . 3.1 – Méta-modèle virtuel des ExternalFeature
Stéréotype s’applique à Définition
«ViewClass» Class Indique que la Class est
une vue.
«viewOf» Dependency Permet d’indiquer une dépendance entre
une classe et sa vue.
TAB . 3.2 – Stéréotypes pour le méta-type ViewClass.
Classifier
{From UML}
<<baseElement>>
«stereotype»
ViewClass
F IG . 3.2 – Méta-modèle virtuel des ViewClass
Un ViewAttribute est représenté par un Attribute UML stéréotypé par «ViewAttribute». En
spécialisant «ExternalStructuralFeature», le stéréotype «ViewAttribute» hérite de
la valeur marquée root, qui doit ici contenir le nom d’un Attribute.
27. 3.2. Les éléments du profil 23
Dependency
{From UML}
<<baseElement>>
«stereotype»
viewOf
F IG . 3.3 – Méta-modèle virtuel des viewOf
Stéréotype s’applique à Définition
«ViewAttribute» Attribute Spécialise «ExternalStructuralFeature».
Indique que l’attribut est une vue.
TAB . 3.3 – Stéréotype pour le méta-type ViewAttribute.
Attribute
{From UML}
<<baseElement>>
«stereotype»
ViewAttribute
F IG . 3.4 – Méta-modèle virtuel des ViewAttribute
Une ViewAssociation est représentée par une Association UML stéréotypée par «ViewAssociation».
Une valeur marquée de nom root lui est appliquée. La valeur de type chaîne de caractères associée à
ce tag contient le nom de l’Association racine. Celle-ci permet de manipuler, dans le composant,
l’association définie dans le paquetage de base.
Stéréotype s’applique à Définition
«ViewAssociation» Association Indique que l’association est une vue.
Tag s’applique à Définition
root «ViewAssociation» Nom d’une Association
Désigne la racine de la ViewAssociation.
TAB . 3.4 – Stéréotypes et valeurs marquées pour le méta-type ViewAssociation.
Association
{From UML}
<<baseElement>>
«stereotype»
ViewAssociation
<<tagged value>> root: string
F IG . 3.5 – Méta-modèle virtuel des ViewAssociation
Un composant est représenté par un Package UML stéréotypé par «Component». Son application à
un Package est représenté par une Dependency entre eux stéréotypée par «viewOf».
28. 24 Chapitre 3. Réalisation du Profil UML
Stéréotype s’applique à Définition
«Component» Package Indique que le Package est
un composant vue.
«viewOf» Dependency Permet d’indiquer un dépendance entre
un paquetage et un composant.
TAB . 3.5 – Stéréotypes pour le méta-type Component.
Package
{From UML}
<<baseElement>>
«stereotype»
Component
F IG . 3.6 – Méta-modèle virtuel des Component
F IG . 3.7 – Le module Objecteering
29. Chapitre 4
Ciblage
Pour tester notre modèle, nous avons mis en œuvre l’exemple de la bibliothèque universitaire présentée
dans le premier chapitre sur les plates-formes CCM et EJB. La première réalisation (vers CCM) ne produit
pas de code éxecutable, uniquement les spécifications (IDL 3) mais elle est entièrement automatisée. La
seconde (vers EJB) n’a pas fait l’objet d’une automatisation, mais a été entiérement spécifiée. Les sections
suivantes présentent ces travaux.
4.1 Du modèle abstrait aux composants CCM
Nous proposons ici une génération automatique des descriptions UML des composants vues vers des
composants CCM. Plus précisément, l’atelier UML génère :
– La spécification IDL3 des composants CCM issus d’un composant de base.
– La spécification IDL3 des composants CCM issus d’un composant vue.
– La spécification IDL3 des composants CCM d’assemblage entre un composant vue et un composant
de base.
Après une description succinte du modèle de composants CORBA (cf 4.1.1), nous détaillons les différentes
règles de transformation d’un schéma UML profilé vers la spécification IDL3 (cf 4.1.2).
4.1.1 Le modèle de composants CORBA
Les modèles à objets ont progressivement montré leurs limites. Certains industriels, comme Microsoft,
Sun et l’OMG, ont fait évoluer leurs modèles vers les composants, dans le but de simplifier le dévelop-
pement d’applications. La réponse de l’OMG [16] est le "CORBA Component Model" (CCM) modèle de
base du futur standard CORBA 3 [17, 18, 19]. Dans un but de compatibilité ascendante, l’OMG a défini
son modèle de composants comme une extension du modèle objet de CORBA 2. Les composants CORBA
représentent donc une spécialisation des objets CORBA tels que nous les connaissons aujourd’hui. La spé-
cification de ce standard n’est pas encore achevée ; cependant, le chapitre sur le modèle de composants a
été finalisé à l’OMG en janvier 2002. C’est donc l’un des plus jeunes modèles de composants mais aussi
l’un des plus riches en comparaison avec d’autres modèles.
La spécification du CCM, qui représente plus de 1000 pages, est découpée en quatre modèles et un
méta-modèle. Ce document décrit :
Le modèle abstrait offre aux concepteurs le moyen d’exprimer les interfaces (fournies et utilisées) et les
propriétés d’un type de composant. Pour cela, le langage OMG IDL a été étendu pour prendre en
compte les nouveaux concepts introduits dans le CCM (le langage IDL3). Un type de composant
(component) regroupe la définition d’attributs et de ports. Les attributs représentent les propriétés
25
30. 26 Chapitre 4. Ciblage
configurables du type de composant. Un port représente une interface (au sens CORBA 2) soit four-
nie, soit requise, par le type de composant. Quatre types de ports sont définis dans le contexte du
CCM :
– Une facette est une interface fournie par un type de composant et qui est utilisée par des clients en
mode synchrone.
– Un réceptacle est une interface utilisée par un type de composant en mode synchrone.
– Un puit d’événement est une interface fournie par un type de composant et utilisée par ses clients
en mode asynchrone.
– Une source d’événement est une interface utilisée par un type de composant en mode asynchrone.
La figure 4.1 illustre un composant abstrait CCM doté de plusieurs ports.
Référence de Réceptacle
Composant Composant CCM
Composant
Implémentation
Références des facettes Puit d’événement
de facettes
Source d’événement
Composant
Attributs
F IG . 4.1 – Composant abstrait CCM
Le modèle de programmation spécifie le langage CIDL (Component Implementation Definition Lan-
guage) à utiliser pour définir la structure de l’implantation d’un type de composant, ainsi que cer-
tains de ses aspects non-fonctionnels (persistance, transactions, sécurité). L’utilisation de ce langage
est associée à un framework, le CIF (Component Implementation Framework), qui définit comment
les parties fonctionnelles (programmées) et non-fonctionnelles (décrites en IDL / CIDL et générées)
doivent coopérer. Il inclut aussi la manière dont l’implantation d’un composant interagit avec le
conteneur.
Le modèle de déploiement définit un processus qui permet d’installer une application sur différents sites
d’exécution de manière simple et automatique. Ce modèle s’appuie sur l’utilisation de paquetages de
composants, ainsi que de descripteurs OSD (Open Software Description, un vocabulaire XML), les
paquetages étant déployables et composables.
Le modèle d’exécution définit l’environnement d’exécution des instances de composants. Le rôle princi-
pal des conteneurs est de masquer et prendre en charge les aspects non-fonctionnels des composants
qu’il n’est alors plus nécessaire de programmer.
4.1.2 Règles de transformation
Pour la génération automatique, nous nous sommes basés sur le langage IDL3 permettant de décrire le
modèle abstrait CCM. De plus, nous nous sommes interressés uniquement aux ports synchrones du modèle
(facettes et réceptacles).
Génération du composant de base
Le tableau 4.1 énumère la transformation de chaque concept UML vers des concepts IDL3. Un com-
posant de base défini par un paquetage UML est spécifié par un module CCM.
31. 4.1. Du modèle abstrait aux composants CCM 27
Chaque classe UML de ce paquetage est spécifiée par un composant CCM, ce composant dispose d’une
facette décrite par une interface IDL contenant toutes les descriptions publiques (attributs et opérations) de
la classe UML.
Les attributs d’une classe sont transformés en attributs primitifs CORBA (l’atelier UML vérifiant que les
attributs définis dans le modèle sont des attributs simples). Ces attributs sont spécifiés dans l’interface cor-
respondante à l’unique facette du composant CCM.
Les opérations UML sont également transformées en opérations contenues dans l’interface IDL de la fa-
cette du composant
Les associations sont exprimées par des opérations primitives de manipulation de l’association (add, get
, remove) définies dans l’interface IDL correspondante à la facette du composant. ces associations sont
également gérées par l’introduction de réceptacles au niveau des composants participants à l’association
(l’atelier UML se limite aux associations binaires)
Concept modèle abstrait UML spécification IDL3 correspondante
paquetage UML X module CCM X
classe X component X doté d’une
facette de nom serviceX de l’interface IX
et d’une maison de composant homeX
attributs publiques UML attributs IDL3 dans l’interface IX
opérations publiques UML opérations IDL3 dans l’interface IX
association UML opérations de gestion des associations,
réceptacle pour l’extrémité de l’association.
TAB . 4.1 – Correspondance composant UML de base et composants CCM
Exemple : Nous illustrons cette génération par l’exemple de la bibliothèque universitaire et en se
limitant aux classes UML Location et Document reliée par une association de nom manage, la spé-
cification IDL3 générée par l’atelier UML est la suivante :
module Base
{
interface ILocation ;
interface IDocument ;
typedef sequence<IDocument> IDocuments ;
interface ILocation
{
attribute string identifiant ;
attribute string adresse ;
public void addManage(IDocument value) ;
public IDocuments getManage() ;
public void removeManage(IDocument value) ;
} ;
interface IDocument
{
attribute string title ;
attribute string publication_date ;
public void setManage(ILocation value) ;
public ILocation getManage() ;
public void removeManage() ;
} ;
component Location
{
provides ILocation serviceLocation ;
uses multiple IDocument manage ;
} ;
32. 28 Chapitre 4. Ciblage
component Document
{
provides IDocument serviceDocument ;
uses ILocation manage ;
} ;
home LocationHome manages Location { } ;
home DocumentHome manages Document { } ;
} ;
Génération du composant vue
Pour un composant vue, les règles de transformation définies pour un composant de base sont intégra-
lement applicables pour les constructions UML standards.
Le tableau 4.2 énumère la transformation de chaque concept UML étendu (viewClass, viewAttribute,
. . .) vers des concepts IDL3.
Une classe «viewClass» est spécifiée par un composant CCM, ce composant dispose d’une fa-
cette décrite par une interface IDL contenant toutes les descriptions publiques (attributs et opérations) de
la classe UML et dispose d’un réceptacle correspondant à toutes les descriptions requises (constructions
«viewAttribute» et «viewAssociation»).
Concept modèle abstrait UML spécification IDL3 correspondante
«viewClass» X component X dotée d’une
facette de nom serviceX de l’interface IX
et d’un réceptacle de nom receptX de l’interface RX
et d’une maison de composant homeX
«viewAttribute» spécifié dans l’interface IX si public
spécifié dans l’interface RX
«viewAssociation» opérations de manipulation de l’association
spécifiés dans l’interface IX et RX
TAB . 4.2 – Correspondance composant UML vue et composants CCM
Exemple : Pour illustrer la spécification IDL3 suivante décrit le composant vue resourceManager :
module ResourceManager
{
interface IResourceOwner ;
interface IResource ;
typedef sequence<IResource> IResources ;
interface IResourceOwner
{
attribute string identifiant ;
attribute long capacity ;
public void addStore(IResource value) ;
public IResources getStore() ;
public void removeStore(IResource value) ;
public void transfering(IResourceOwner o) ;
} ;
interface RResourceOwner
{
attribute string identifiant ;
public void addStore(RResource value) ;
public RResources getStore() ;
public void removeStore(RResource value) ;
33. 4.1. Du modèle abstrait aux composants CCM 29
} ;
interface IResource
{
attribute string identifiant ;
public void setStore(IResourceOwner value) ;
public IResourceOwner getStore() ;
public void removeStore() ;
} ;
interface RResource
{
attribute string identifiant ;
public void setStore(RResourceOwner value) ;
public RResourceOwner getStore() ;
public void removeStore() ;
} ;
component ResourceOwner
{
provides IResourceOwner serviceResourceOwner ;
uses RResourceOwner receptResourceOwner
} ;
component Resource
{
provides IResource serviceResource ;
uses RResource receptResource ;
} ;
home ResourceOwnerHome manages ResourceOwner { } ;
home ResourceHome manages Resource { } ;
} ;
Génération du composant d’assemblage
Comme l’illustre les exemples, composants de bases et composants vues sont parfaitement indépen-
dants. Les constructions UML détaillant la connexion d’un composant vue à un composant de base vont
permettre de générer les composants CCM d’assemblage : ce sont en fait, des composants adaptateurs qui
vont permettre de relier un réceptacle d’un composant CCM vue à la facette du composant CCM de base.
Le pattern classique adaptateur [20] est utilisé pour les connexions comme le montre le code exemple
suivant permettant de connecter un composant vue X à un composant de base Y :
component AdaptX_Y
{
provides RX serviceAdaptX ;
uses IY receptAdaptY ;
}
Exemple : voici l’exemple du composant d’assemblage permettant de connecter le composant vue
ResourceManager au composant de base Base de la bibliothèque universitaire :
import ResourceManager ;
import Base ;
module adapt
{
component AdaptResourceOwner_Location
{
34. 30 Chapitre 4. Ciblage
provides ResourceManager::RResourceOwner serviceAdaptResourceOwner ;
uses Base::Ilocation receptAdaptLocation ;
} ;
component AdaptResource_Document
{
provides ResourceManager::RResource serviceAdaptResource ;
uses Base::IDocument receptAdaptDocument ;
} ;
home AdaptResourceOwner_LocationHome
manages AdaptResourceOwner_Location {} ;
home AdaptResource_Documenthome
manages AdaptResource_Document {} ;
4.2 Du modèle abstrait aux composants EJB
Dans cette section, nous présentons une seconde projection des composants de notre modèle abstrait.
Il s’agit d’une projection vers la plate-forme EJB qui propose des composants orientés vers le développe-
ment d’applications au-dessus d’un système d’informations d’entreprise. En plus de proposer des règles
pour générer la spécification, des composants, cette projection introduit aussi des règles pour produire leur
implantation.
La projection proposée produit le code Java d’implantation de composants EJB correspondant aux
classes ViewClass d’un composant connecté à un composant de base au niveau modèle. Un composant
de notre modèle sera matérialisé par une archive empaquetant ces composants EJB avec des descripteurs
de déploiement1.
Les composants EJB résultant de la projection présentent les caractéristiques suivantes 2 .
– Ils sont connectables localement ou à distance avec des composants EJB implantant les classes du
composant de base pour lesquels la connexion a été vérifiée ;
– Ils mettent en oeuvre des traitements pour préserver la sémantique de vues à l’exécution ;
– Ils sont manipulables pour les outils EJB standard d’empaquetage et de déploiement sur un serveur.
– Ils définissent un schéma abstrait de persistance qui permet de définir un descripteur pour leur sau-
vegarde (état, associations) dans une base de donnée quelconque.
Dans la prochaine section, nous présentons les grandes lignes de la norme EJB. Cette partie permettra
d’introduire les notions utilisées lors de la projection. Ces notions sont illustrées en implantant le composant
de base de la bibliothèque sous forme de composants EJB. La section suivante décrit le choix de mise en
oeuvre et les règles de générations qui en découlent pour les composants vues.
4.2.1 Le modèle de composants EJB
La norme EJB (Enterprise Java Bean) a été proposée par SUN Microsystems pour répondre aux be-
soins de l’industrie en matière de construction de serveurs d’applications d’entreprise. Cette norme (qui
en est à sa version 2.0) décrit une architecture normalisée pour le développement et le déploiement de ces
applications à base de composants "Bean" écrits en Java. L’apport principal de cette norme est d’accorder
une grande importance à la prise en change des aspects non fonctionnels requis par les composants de ce
type d’applications à savoir la persistance des données, la sécurité et la gestion des transactions. Cette prise
en charge permet au développeur de se concentrer sur les aspects métiers de ces composants.
Un composant EJB est un ensemble de définitions JAVA (interfaces et classes) et des descripteurs XML
empaquetés - dans une archive de type jar - qui sont déployés sur un serveur d’applications. Le serveur
1 dans sa version actuelle, la projection ne produit pas le descripteur de déploiement des composants EJB mais cette opération est
tout à fait envisageable
2 La production de composants EJB qui seraient génériques par rapport à plusieurs composants de base implantées avec des
composants EJB est envisageable mais réclame l’utilisation d’outils puissants comme la réflexivité. Nous laissons l’étude de tels
composants pour des travaux futurs
35. 4.2. Du modèle abstrait aux composants EJB 31
utilise les informations contenues dans le descripteur pour instancier le composant EJB dans un container
dont la fonction est de fournir une interface entre le composant et son environnement, prenant en charge un
certain nombre d’aspects non-fonctionnels.
F IG . 4.2 – L’architecture EJB
Un composant EJB offre des services exposés aux clients sous la forme d’une interface Java de type
EJBObject (pour des client distants) ou EJBLocalObject (pour des clients locaux, c’est-à-dire s’exécutant
dans la même machine virtuelle). Un client d’un EJB peut être n’importe quel programme susceptible de
communiquer par le protocole RMI-IIOP et notamment un autre EJB ou encore un ensemble de servlet
et de pages JSP. Le container se charge de transformer les requêtes distantes du client en appels réels aux
composants, en les enveloppant éventuellement dans un contexte transactionnel.
Le code suivant présente l’interface de services proposée par des composants EJB implantant respecti-
vement la classe Document et la classe Location appartenant au composant de base de notre exemple. Les
méthodes spécifiées par chaque interface donne accès aux attributs et aux associations définis à ce niveau.
public interface Document extends EJBLocalObject
{
public String getDocumentId();
public String getTitle();
public void setTitle(String title);
public Date getPublicationDate();
public void setPublicationDate(Date d);
public Location getLocation();
public void setLocation(Location loc);
public Collection getAuthors();
public void addAuthor(Researcher r);
}
public interface Location extends EJBLocalObject
{
public String getLocationId();
public String getAddress();
public void setAddress(String a);
public Collection getDocuments();
public void addDocument(Document d);
}
A chaque composant EJB est également associée une maison de composant qui est chargée de la
construction effective des composants, de leur destruction et éventuellement de leur recherche. Ces mai-
sons correspondent à la notion bien connue de fabrique. Elles sont généralement localisables par un client,
36. 32 Chapitre 4. Ciblage
par exemple au travers d’un service de nommage, et offre une interface uniforme de type EJBHome (des-
tinée aux clients distants) ou EJBLocalHome (destinée aux clients locaux) pour la gestion des instances de
composants associés.
Le code suivant présente les interfaces de fabrique pour la création (méthodes de nom "create") et la
recherche (méthodes ayant un nom préfixé par "find") d’instances de composants EJB implantant respecti-
vement la classe Document et la classe Location du composant de base.
public interface LocalDocumentHome extends EJBLocalHome
{
public Document create(String id, String title,
Date publication Date)
throws CreateException;
public Document create(String id, String title,
Date publicationDate, Location loc)
throws CreateException;
public Document findByPrimaryKey(String id)
throws FinderException;
public Document findByDate(Date d)
throws FinderException;
}
public interface LocationHome extends EJBLocalHome
{
public Location create(String id, String address)
throws CreateException;
public Location findByPrimaryKey(String id)
throws FinderException;
}
La norme EJB définit trois types de composants qui se différentient principalement par rapport à leur
utilité et la gestion de leur cycle de vie par le conteneur : il s’agit des beans "session", des beans "orientés
message" (message-driven) et des beans "entité". Les bean "session" sont des composants existants pour
une session demandée par le client. Ils peuvent être avec état ou sans état ce qui, dans ce dernier cas, permet
au conteneur de les partager entre plusieurs clients (sous forme de pool). Les beans "orientés message" sont
des réceptables de messages asynchrones gérés par file d’attente. Les beans "entité" sont des composants
représentant des données d’une base de données dont ils permettent d’obtenir une vue orientée objet.
Etant donné que les beans "entité" sont les seuls beans à être employés lors de la projection, nous nous
focalisons sur les caractéristiques de ce type de bean dans le reste de la présentation, notamment ceux qui
sont liées à la gestion de la persistance.
L’association des beans "entité" avec les éléments d’une base de données leur confère deux caractéris-
tiques principales.
La première caractéristique est d’être identifié de manière unique par un clé primaire. La présence de
cette clé permet aux clients de rechercher un bean entité donné par sa clé primaire. Il suffit pour cela que
le client s’adresse à la maison liée au bean. Cette clé primaire peut-être n’importe quel objet sérialisable.
La seconde caractéristique est d’être persistant ce qui signifie que l’état du bean et ses associations
avec d’autres beans peuvent être sauvegardés dans la base de données. Pour la gestion de cette persistance,
la norme EJB propose deux approches : une gestion par le bean et une gestion par le conteneur que nous
privilégions. Dans ce second cas, le container collabore avec le gestionnaire de la base pour mettre en
oeuvre un schéma de persistence qui leur est fourni au travers du descripteur de bean. Schématiquement,
le descripteur définit des sources de données, des champs de données et des relations (à la manière d’un
schéma de base de données) qui sont identifiés au niveau de la classe d’implantation du bean par des
méthodes d’accès abstraites nommées selon des conventions particulières. Il appartient au conteneur et au
gestionnaire de la base de créer et de mettre à jour effectivement et automatiquement les données lors de la
création et l’exécution des beans.
Le code suivant présente les classes d’implantation des composants EJB Document et Location (sans
code d’implantation pour plus de clarté). Ces classes héritent de EntityBean pour indiquer que ceux sont