Académique Documents
Professionnel Documents
Culture Documents
Approche Composant :
de la spécication à l'implantation
Mémoire de n d'études
Jeanine Souquières
Applications (LORIA).
pour m'avoir encadrée pendant ces neuf mois. Je les remercie de leur contact chaleureux, leurs
conseils et encouragements, leur soutien permanent et la liberté de recherche qu'ils ont bien
voulu me laisser.
Mes plus sincères remerciements vont également à tous les professeurs et les personnels de
l'Institut de la Francophonie pour l'Informatique (IFI) pour m'avoir donnée des cours de très
grande qualité et pour leur soutien tout au long de mes études à l'IFI.
Un grand merci aux post-doctorants et thésards de l'équipe DEDALE qui m'ont aidée au
Je remercie chaleureusement mes camarades de la promotion XII pour leur amitié sans
Finalement j'adresse un grand merci à toute ma famille et mes amis pour leur soutien et
1
Résumé
L'équipe DEDALE du LORIA travaille sur les approches de vérication d'architectures
logicielles à base de composants. Les composants sont des boîtes noires pour lesquelles seules
leurs interfaces sont connues. Une interface décrit les fonctionnalités oertes et/ou requises
par le composant considéré. Pour que diérents composants puissent être déployés et tra-
vailler ensemble, ils doivent pouvoir coopérer, c'est-à-dire que leurs interfaces doivent être
compatibles.
Mon travail de stage a porté sur la liaison entre les travaux de l'équipe DEDALE sur l'as-
semblage de composants au niveau UML/B et les composants Enterprise Java Bean (EJB).
Nous avons proposé une liaison à diérents niveaux : celui de la programmation avec la dé-
nition d'adaptateurs à partir des EJBs existants ; celui de la spécication avec la dénition
Abstract
The DEDALE team, a research group at LORIA institute, works on component-based
through required and/or provided interfaces which describe their visible behaviors. A provided
interface of one component can be connected with a required interface of another component
if the former oers the services needed to implement the latter. Software components can be
composed and have to be connected in an appropriate way, this means that their interfaces
must be compatible.
We have studied how to etablish a relationship between the work of the DEDALE team
about component assembly with UML/B and Enterprise Java Bean (EJB). We have proposed
a relationship at dierent levels : at the programing level with the denition of adapters using
EJB existing components ; at the specication level with the denition of method compatibi-
2
Table des matières
1 Introduction 7
1.1 Problématique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2 Objectif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.3 Contribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2 État de l'art 10
2.1 Adaptateur et B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.1.2 Méthode B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2.1 Dénition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.2.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.3.1 Dénition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.3.2 Spécication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.3.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.4.1 Dénition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3 Propositions 25
3.1 Dénition d'un adaptateur au niveau EJB . . . . . . . . . . . . . . . . . . . . 25
3
3.3.1 Invariant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.3.3 Visibilité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.3.5 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4 Conclusion et perspectives 46
4.1 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
4.2 Perspectives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
4
Table des gures
2.1 Modèle B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
5
Liste des tableaux
2.1 Diérences entre Stateless Session Beans et Stateful Session Beans . . . . . . 14
6
Chapitre 1
Introduction
1.1 Problématique
Les méthodes d'ingénierie basées sur l'assemblage de composants indépendants répondent
aux besoins de l'évolutivité des architectures logicielles grâce aux avantages de l'ingénierie ba-
sée sur les composants tels que la réutilisabilité des composants logiciels certiés, la réduction
du coût de développement, la exibilité des systèmes développés. Les technologies telles que
les Enterprise Java Beans (EJB) de Java/Sun [22, 23], les composants .NET de Microsoft [18],
CORBA défendu par l'OMG [26, 27], permettent de développer et de déployer des composants
réutilisables. Néanmoins, les approches basées sur l'ingénierie des composants sont encore peu
nouvelle problématique.
L'équipe DEDALE du LORIA (voir section 1.4) travaille sur la conception de méthodes
les composants sont des boîtes noires pour lesquelles seules leurs interfaces sont connues. Une
interface décrit les fonctionnalités oertes et/ou requises par le composant considéré. Pour
que diérents composants puissent être déployés et travailler ensemble, ils doivent pouvoir
Pour décrire les interfaces des composants et les interactions entre composants, l'équipe
DEDALE utilise les diagrammes de composants UML 2.0. An de vérier formellement l'in-
teropérabilité entre composants, les interfaces sont décrites de manière plus précise à l'aide
d'un langage formel de haut niveau, la méthode B (voir section 2.1). La vérication de l'inter-
opérabilité entre les composants s'eectue grâce aux techniques de ranement et aux outils
Il est donc nécessaire d'établir un lien plus précis entre les travaux de l'équipe sur l'as-
semblage de composants au niveau UML/B et les composants logiciels usuels tels que les
Enterprise Java Beans ou les composants .NET, objectifs du stage que j'ai eectué dans
l'équipe DEDALE.
1.2 Objectif
L'objectif de mon sujet de stage est dans un premier temps d'étudier les diérentes techno-
logies à base de composants : Corba, Enterprises JavaBeans, .NET, puis d'établir un lien avec
7
le modèle d'assemblage UML/B actuellement promu par l'équipe DEDALE pour répondre
Quelles sont les diérences majeures entre les technologies basées composants existantes :
Corba, Enterprises Java Beans, .NET ? Existe-il des liens, des passerelles entre elles ?
est-elle susante pour permettre le passage vers les technologies existantes à base de
composants ?
1.3 Contribution
Pour répondre aux objectifs du sujet, nous établissons une liaison à deux diérents ni-
prise Java Beans (EJB), technologie très connue utilisant Java. La méthode B est une mé-
l'adaptateur est une notion importante. Il est donc nécessaire de dénir l'adaptateur entre
des composants existants au niveau programmation. A l'aide des connaissances sur les com-
posants EJBs, nous choisissons le type Bean comme élément moteur de notre travail. Puis
nous essayons de mettre en correspondance l'architecture d'assemblage UML/B avec les EJBs.
Enn, nous dénissons des types d'adaptateurs en fonction des EJBs manipulés.
permettant d'exprimer des propriétés de type pré/post conditions. Il existe actuellement des
outils de vérication pour les programmes Java qui utilisent des annotations de JML tel que
au niveau interface ne sont pas prise en compte. Notre travail consiste à étudier la compatibilité
Fondé en 1997, le LORIA se concentre sur ses trois missions principales : la recherche fon-
8
de l'Information et de la Communication, la formation par la recherche en partenariat avec
L'équipe DEDALE, au sein de LORIA, est une équipe travaillant sur la qualité et la
sûreté des logiciels. L'objectif de cette équipe est d'étudier les mécanismes de construction de
de l'évolution et de la qualité des logiciels. L'idée sous-jacente est que les développements de
spécications et de programmes sont des objets à part entière que l'on peut étudier, modéliser,
apporter des aides dans la démarche de construction d'un logiciel, depuis l'analyse du
cahier des charges fourni par le client jusqu'à la production d'une spécication for-
melle, avec un intérêt particulier pour les aspects de vérication et de qualité via une
construction prouvée,
cications existants et les outils associés à ces langages tout au long du développement,
de spécications formelles.
Spécication de systèmes par composants avec preuve de leur interopérabilité [4, 8, 12,
14, 15].
Dans le chapitre 2, nous présentons des travaux existants concernant notre approche : B
et les adaptateurs (approche proposée par l'équipe DEDALE), Enterprise Java Beans et Java
Modeling Language. Nous présentons aussi des travaux concernant la compatibilité de signa-
tures et de spécications qui jouent un rôle important dans la compatibilité entre interfaces.
9
Chapitre 2
État de l'art
2.1 Adaptateur et B
Le développement des adaptateurs à l'aide de B est une direction de recherche de l'équipe
DEDALE. Nous nous basons sur les articles [6, 13, 15, 19], principalement l'article [15] pour
sant est considéré comme une boîte noire. Des composants logiciels sont développés par
Les composants communiquent via leurs interfaces. Il existe deux types d'interface de
composants : une interface fournie qui ore des fonctionnalités, une interface requise qui
utilise les fonctionnalités d'un autre composant pour implanter ses propres fonctionnalités.
Une interface fournie peut être connectée avec une interface requise si la première ore toutes
composants, il est nécessaire d'avoir une description appropriée des interfaces et de vérier
termes d'un ranement : l'interface fournie doit "raner" l'interface requise. La méthode B
[1] est une méthode qui supporte la spécication formelle des interfaces et permet aussi la
Dans l'ingénierie des composants, la notion de réutilisation est très importante. Les inte-
faces fournies et requises des composants existants peuvent rarement être connectées directe-
ment. Pour répondre au besoin de connexion entre composants, il faut intercaler un adaptateur
(ou médiateur) entre composants ou bien développer un nouveau composant par assemblage
2.1.2 Méthode B
a) Dénition
Initiée par Jean-Raymond Abrial au début des années 80, B [1] est une méthode formelle
basée sur la logic du premier ordre et la théorie des ensembles, permettant un développement
10
incrémental de spécications grâce au ranement. Un développement commence avec la dé-
nition d'une spécication abstraite qui est ensuite ranée pas à pas jusqu'à l'obtention d'une
des fondements mathématiques en logique du premier ordre avec théorie des ensembles,
qui forment un corpus formel connu et compris depuis longtemps et permettant de
dans le domaine du ferroviaire, comme le projet METEOR [3] ou le métro Val [2]. Elle s'appuie
sur des outils robustes [21, 5] basés sur la preuve. Nous rappelons ici comment un modèle est
rester vraies après toute étape d'évolution du modèle. La correction du modèle signie la
MODEL example
SEES seen_model
INCLUDES included_model
VARIABLES var1, var2
INVARIANT inv
INITIALISATION init
OPERATIONS
out1, out2 ←− method1(in1, in2) =
PRE pre1
b
THEN body1
END
END
Un modèle B commence par la clause MODEL pour déclarer le nom du modèle. Les
propriétés sont spéciées dans la clause INVARIANT du modèle et l'évolution de ce modèle
est spéciée dans plusieurs opérations situées dans la clause OPERATIONS. Soit le modèle
générique présenté gure 2.1 : il dispose de variables var1 et var2 (déclarées par la clause
VARIABLES) dont les propriétés sont indiquées dans l'invariant inv. Le modèle contient
une opération method1 qui précise comment var1 et var2 sont modiées en fonction des
paramètres in1 et in2. Elle peut aussi retourner une ou plusieurs valeurs out1 et out2. La
précondition pre1 de method1 permet d'indiquer quelles sont les contraintes sur l'état du
modèle (et les paramètres de l'opération) lors de l'appel de l'opération. Le corps de l'opération
included_model de la clause INCLUDES est un autre modèle B dont l'état est visible et
dont les changements peuvent être contrôlés en appelant ses opérations.
11
2.1.3 Interopérabilité entre composants
Pour vérier l'interopérabilité entre deux composants, c'est-à-dire, qu'ils peuvent être
connectés via leur interfaces respectives, il faut s'assurer que ces interfaces sont compatibles.
Plus précisément, il s'agit de montrer que l'interface fournie implante bien les fonctionnalités
Soient deux composants OTS11 et OTS2 avec leur interfacesRI_ots1 et PI_ots2 respec-
tives. Ils sont interopérables si et seulement si le modèle B de PI_ots2 est un ranement de
celui de RI_ots1 [15].
Dans le cas où deux composants ne sont pas compatibles, le développement d'un adapta-
teur ou celui d'un nouveau composant à partir de composants existants sont nécessaires. Ces
composant OTS2, revient à développer un nouveau composant DEV qui fournira l'interface
RI_ots1 en utilisant le composant OTS2 via son interface fournie PI_ots2, comme illustré
gure 2.3.
directement compatibles. Un nouveau composant est nécessaire pour les rendre compa-
nombre et du type de composants existants à assembler. La dénition des diérents cas d'ar-
1
Nous nommons les composants existants OTS pour O-The-Shelf .
12
de l'assemblage est présentée dans l'article [15]. Notre objectif est de mettre en correspondance
composants logiciels côté serveur pour la plateforme de développement J2EE . Cette archi-
2
tecture propose un cadre pour créer des composants distribués (c'est-à-dire déployés sur des
données (EJB dit entité), de proposer des services avec ou sans mémorisation d'états entre
les appels (EJB dit session), ou encore d'accomplir des tâches de manière asynchrone (EJB
dit message). En d'autres termes, EJB est un modèle de composants pour le développement
des applications d'entreprises telles que des sites web (de commerce en ligne, de travail colla-
boratif, communautaires, etc.), des systèmes d'information, des applications de gestion, etc.
Dans ce contexte, la question posée est : qu'est-ce qu'un composant ? Nous disposons d'un
composant A muni de deux interfaces : une interface fournie IA et une interface requise IB.
Dans ce composant, la classe Java ABean implante l'interface IA et importe l'interface IB
nologies (Corba, .NET, etc.) est l'existence de types de composants diérents selon leur uti-
lisation. Il existe trois types de Beans : Session Bean, Message-Driven Bean et Entity Bean.
2
Java Platform, Enterprise Edition.
3
Un serveur d'applications est un serveur sur lequel sont installées les applications utilisées par les usagers.
Ces applications sont chargées sur le serveur d'applications et accédées à distance.
13
a) Session beans
Ils modélisent les processus métiers, exprimés à l'aide de verbes parce qu'ils eectuent des
actions.
Les Session Beans sont divisés en deux sous-types : Stateless Session Beans et Stateful
Session Beans. Les Stateless Session Beans ne mémorisent pas l'information résultat des
diérentes requêtes alors que les Stateful Session Beans mémorisent des états.
Les principales diérences entre ces deux types de Session Beans sont présentés dans le
tableau 2.1.
- Deux instances quelconques d'un tel - Même instance pendant toute la durée
Tab. 2.1 Diérences entre Stateless Session Beans et Stateful Session Beans
Dans le composant de type Session Bean, nous déclarons aussi le type d'utilisation : locale
(@Local) ou à distance (@Remote) via des annotations Java. Ce sont deux notions que nous
utiliserons souvent dans l'application client/serveur. Nous présentons la diérence entre ces
Pour le type d'utilisation à distance, l'application côté client et les composants EJBs
qu'elle utilise sont déployés sur des machines diérentes alors que dans l'utilisation locale, ils
b) Message-Driven Beans
Les Message-Driven Beans Session Beans. La diérence
eectuent des actions comme les
entre ces deux types de composants, c'est que les Message-Driven Beans sont appelés à l'aide
d'un système de messages, c'est-à-dire qu'il n'existe pas de chemin direct pour appeler une
c) Entity Beans
Ils modélisent les données métiers. Ce sont des noms correspondant aux objets.
14
Les Entity Beans n'ont pas d'interface. Ils sont utilisés localement. Ils peuvent aussi être
d) Synthèse
Le tableau 2.2 présente les diérences entre les trois types de Beans [7].
deux clients appellent une même instance de Session Bean, il y a une erreur.
15
2.2.3 Exemple
Nous présentons dans le gure 2.6 un exemple générique d'application client/serveur
Dans cet exemple, IB et IC sont des interfaces décrites en Java. B et C sont des com-
posants EJBs côté serveur dont les interfaces fournies sont IB et IC. A est une application
client écrite en Java. Nous présentons les interfaces IB et IC (voir gure 2.7).
public i n t e r f a c e I B { public i n t e r f a c e I C {
public void methodeB ( ) ; public void methodeC ( ) ;
} }
package component_B ;
import j a v a x . e j b . Remote ;
import javax . ejb . Stateless ;
package component_C ;
import j a v a x . e j b . EJB ;
import component_C . I C ;
import javax . ejb . Local ;
@Stateless
import javax . ejb . Stateless ;
@Remote
@Stateless
public c l a s s BBean implements IB {
@Local
@EJB
private IC c ;
public c l a s s CBean implements IC {
public void methodeC ( ) {
.....
public void methodeB ( ) {
}
....
}
c . methodeC ( ) ;
....
}
}
Dans la classe BBean du composant B, @Stateless précise qu'il s'agit d'un Stateless Session
Bean. La clause @Remote précise que l'application A (qui utilise B ) et le composant B ne
sont pas déployés la même machine.
16
C est déni de la même manière que B. Dans la classe CBean, nous déclarons
Le composant
import component_B . I B ;
public c l a s s A {
@EJB
p r i v a t e s t a t i c IB b ;
public s t a t i c void main ( S t r i n g [ ] args ) {
....
b . methodeB ( ) ;
....
}
}
ments d'interface pour Java. Il permet de spécier formellement le comportement d'une classe
Java. Le comportement décrit ce qui se passe quand une méthode est appelée. Le comporte-
ment d'une méthode est spécié à l'aide de préconditions et postconditions [16, 17, 28].
2.3.2 Spécication
Il y a trois notions importantes dans une spécication JML :
Précondition : propriété qui doit être vériée avant l'appel d'une méthode
Dans la suite, nous présentons en détail les notions relatives à notre travail :
a) Types de clauses
Une modélisation JML est composée de clauses (prédicats) décrivant la classe et les mé-
thodes.
Spécication de types C'est la partie statique du modèle, elle contient des propriétés qui
Constraintes initiales (clause initially predicatJM L ) : les propriétés qui doivent être
sur les attributs de la classe qui doivent être vraies dans tous les états "visibles"
4 du
4
Etats "visibles" : états atteints après l'exécution d'une méthode
17
système
Spécication de méthodes C'est la partie dynamique du modèle, elle contient des pro-
priétés relatives aux comportements autorisés des méthodes, exprimées à l'aide des clauses
suivantes :
Précondition (clause requires predicatJM L ) : condition qui doit être remplie par le
système et les paramètres de la méthode pour que la méthode puisse être exécutée
Champs modiés (clause assignable predicatJM L ) : liste des attributs qui sont modiés
par l'exécution de la méthode
b) Méthodes pures
Une méthode qui ne modie aucun attribut est dite pure et peut être utilisée dans les
prédicats JML. Elle ne doit pas changer l'état du système an d'éviter des eets de bord. Les
déclarer qu'une méthode est pure à l'aide du modieur "pure". Le modieur pure a le même
sense que :
diverges false ;
assignable \nothing ;
c) Exceptions
En Java, une exception est un événement qui a lieu pendant l'exécution d'un programme
qui ne satisfait pas les instructions normales. En d'autres termes, dans JML, une exception
Dans JML, pour dénir une (plusieurs) exception(s) d'une méthode, nous utilisons la
signals_only E1, E2 . . .
indique que E1, E2 . . . sont les seules exceptions autorisées à être levées par la méthode
considérée.
5
Java Application Programming Interface
18
/ ∗@ behavior
@ signals_only E ; // default E
@∗ /
T method ( T1 p1 , . . . ) throws E {
...
}
Fig. 2.10 Forme générale d'une spécication JML d'une méthode Java
les contraintes de visibilités de Java. Pour modier la visibilité des attributs et des méthodes
spec_public
spec_protected
/ ∗@ behavior
@ requires P1 ;
@ ensures Q1 ;
@ signals ( E1 ) S1 ;
@ also
@ behavior
@ requires P2 ;
@ ensures Q2 ;
@ signals ( E2 ) S2 ;
@∗ /
T method ( . . . )
throws E1 , E2 {
...
}
19
/ ∗@ behavior
@ requires P1 || P2 ;
@ ensures P1 => Q1
@ & P2 => Q2 ;
@ signals (E e)
@∗ /
T method ( . . . )
throws E1 , E2 {
...
}
f) Comportements spéciques
Nous pouvons distinguer les comportements normaux et les comportements exceptionnels
termine normalement sans déclancher d'exception. Cela veut dire que dans JML, la
ensures false
2.3.3 Exemple
Nous présentons un exemple de spécication utilisant JML à partir d'une interface PI_Lights
gure 2.11.
Dans cet exemple, nous avons utilisé des annotations JML, disposées entre des annotations
de commentaires sous formes /*@ . . .@*/. Il est aussi possible d'utiliser la forme //@ pour
déclarer des annotations JML sur une seule ligne.
Dans une interface Java, il n'existe pas de vraies variables. Pour représenter des variables
utilisées dans les comportements, nous déclarons ces variables à l'aide du modieur model.
Le modieur model exprime qu'un attribut est déclaré seulement au niveau spécication.
Dans l'interface PI_MLights, les deux variables color et ml_state sont déclarées au niveau
spécication de la manière suivante :
Pour chaque méthode, nous avons une précondition (exprimée par requires ) et une post-
condition (exprimée par ensures ). Pour la méthode change(ML_Color newColor) :
Cela veut dire qu'avant l'appel de cette méthode, les valeurs des variables color et newColor
doivent être diérentes et elles seront identiques après l'exécution. La clause assignable dans
20
/ /@ model import org . j m l s p e c s . models . ∗ ;
public i n t e r f a c e PI_MLights {
/ ∗@ requires c o l o r != newColor ;
@ assignable color ;
@ ensures color == n e w C o l o r ;
@∗ /
@ assignable ml_state ;
@∗ /
public void on ( ) ;
@ assignable ml_state
@∗ /
en relation avec notre approche, en vue de les appliquer pour dénir la compatibilité entre
2.4.1 Dénition
La compatibilité de spécications est un processus pour déterminer si deux composants
Recherche : Comment est-ce que je peux trouver un composant à partir d'une biblio-
Réutilisation : Comment est-ce que je peux adapter un composant à partir d'une biblio-
Remplacement : Quand est-ce que je peux remplacer un composant par un autre sans
Sous-type : Quand est-ce qu'un objet d'un type est un sous-type d'un autre objet ?
La spécication d'un composant C est divisée en deux niveaux, sa signature Csig et son
comportement Cspec .
Soient deux composants, C = <Csig ,
0 ,C 0
Cspec > et C' = <Csig spec >. La compatibilité entre
ces deux composants C et C' est dénie par :
21
2.4.2 Compatibilité au niveau signatures
a) Dénition
La compatibilité de signatures de méthodes utilise la compatibilité de types. Un type est
composants, τl , et le type de la requête, τq , alors la compatibilité M(τl ,τq ) est dénie par :
Dans lequel :
la requête
mations Tl , Tq .
22
Dénition 1 La formule générale de compatibilité pré/post matchpre/post (S, Q) la plus
Avec :
nous avons besoin de considérer une relation de spécications plutôt qu'une relation entre des
Avec :
de compatibilité :
partir de la formule 2.5, avec Sb = Spost et R1 et R2 sont une équivalence, nous obtenons la
@∗ / @∗ /
public i n t addR ( int a, int b); public i n t addP ( int a, int b);
} }
addP de l'interface interfaceP sont les mêmes. Donc, addRpre ⇔ addPpre et addPpost ⇔
addRpost , correspondant à la compatibilité exacte.
23
Fig. 2.12 Idée de compatibilité plug-in
Soit deux méthodes : une méthode Q <Qpre , Qpost > d'une interface requise ; une méthode
S <Spre , Spost >d'une interface fournie. Les eches signient une implication. Selon cette
@∗ / @∗ /
public i n t addR ( int a, int b); public i n t addP ( int a, int b);
} }
addRpre ⇒ addPpre ( addPpre = true, addRpre est plus forte que addPpre
Dans cet exemple,
24
Chapitre 3
Propositions
Driven Beans et Entity Beans, chaque type de Bean ayant ses caractéristiques. Les Session
Beans peuvent être appelés à distance via une interface. Les Message-Driven Beans sont des
récepteurs de messages à partir de JMS (Java Messaging Services). Ils n'ont pas d'interface,
c'est le conteneur qui les appelle. Les Entity Beans ont seulement une classe et pas d'interface.
Les diérences entre les trois types en termes d'interfaces sont résumées dans le tableau
3.1.
Appele à distance Oui, via une inter- Par le conteneur À l'aide d'autres
face Beans
Les Session Beans sont une solution permettant d'exprimer l'interopérabilité entre com-
d'eectuer la liaison entre cette démarche d'assemblage et EJB. Dans la suite, nous présentons
25
Fig. 3.1 Exemples d'assemblage UML
PI_dev et utilise un composant existant OTS via son interface PI_ots. Cette construction
correspond à un assemblage qui exprime comment les attributs et les méthodes de l'interface
PI_dev PI_ots.
sont réalisés à l'aide de ceux de
En EJB, nous dénissons la classe DEV qui implante PI_dev et importe PI_ots.
26
b) Cas de deux interfaces dans l'assemblage
DEV
Figure 3.3, le composant déni est plus complexe. Le composant importe l'interface
RI_dev. En EJB, la classe DEV importe donc les deux interfaces PI_ots et RI_dev.
requises. Nous utilisons une seule classe pour les exprimer en EJB.
27
En d'autres termes, nous avons toujours une correspondance entre les diérents schémas
mètres.
a) Hypothèses
Les hypothèses générales pour tous les cas présentés par la suite, sont les suivantes :
Dans la section 2.2, nous avons indiqué que les EJBs sont des composants distribués,
c'est-à-dire qu'ils sont déployés sur des serveurs distants. Nous avons besoin de dénir des
b) Solutions
Nous avons identié cinq cas diérents, et pour chaque cas, nous donnons les solutions
possibles.
Cas 1 Il correspond à l'hypothèse où A est déployé côté client1 , B est déployé côté serveur
comme un Bean et il doit être déployé sur le même serveur que B. Dans la classe AdapterBean,
nous déclarons @Remote exprimant le fait que A utilise Adapter à distance (A est déployé le
B est déployé côté serveur et l'interface IB est implantée à distance par @Remote, comme
Puisque IB est implanté par @Remote, l'adapteur Adapter n'est pas sur le même serveur
implantée par @Remote pour que A puisse utiliser Adapter à distance, comme présenté
gure 3.6(b).
L'adaptateur Adapter est placé côté client. L'interface IA et la classe Adapteur sont
Dans notre contexte : si un composant A est déployé côté client, ce n'est pas un Bean. Par contre, s'il est
1
28
(a) Hypothèse
(b) Solution
Cas 3 Les composants A et B sont déployés sur le même serveur et l'interface IB est
Comme l'interface IB est implantée localement, l'adaptateur Adapter doit être sur le même
serveur que B et A. L'interface IA est implantée par @Local, voir gure 3.7(b).
Cas 4 Les composants A et B sont déployés sur deux serveurs diérents et l'interface IB
est implantée localement, comme présenté gure 3.8(a).
ter doit donc être déployé sur le même serveur que B. Puisque le composant A utilise le
composant Adapter à distance (A et Adapter sont sur deux serveurs diérents), l'interface IA
Cas 5 Les composants A et B sont déployés sur deux serveurs diérents et l'interface IB
est déclarée@Remote (gure 3.9(a)).
L'interfaceIB est implantée par @Remote, cela veut dire que l'adaptateur Adapter n'est
pas sur le même serveur que B. Nous avons deux possiblilités :
L'adaptateur Adapter est un composant EJB déployé sur le même serveur que le com-
(gure 3.9(b)).
L'adaptateur Adapteur est déployé sur un autre serveur et l'interface IA est declarée
29
(a) Hypothèse
(b) Solution 1
(c) Solution 2
30
(a) Hypothèse
(b) Solution
(a) Hypothèse
(b) Solution
31
(a) Hypothèse
(b) Solution 1
(c) Solution 2
32
3.1.4 Étude de cas
Notre proposition a été élaborée à partir d'une étude de cas réelle du système de contrôle
de cas, illustré gure 3.10, correspondant à l'utilisation d'un composant existant, MultiLights,
pour réaliser le système.
Le système est exprimé dans EJB (voir gure 3.11) en utilisant le cas 3 où les trois
composants sont mis sur le même serveur. Il faut ajouter que l'adaptateur déni implante
Au niveau des spécications UML/B, il était possible de déclarer des variables dans l'in-
terface (voir gure 3.10) mais ceci est interdit dans une interface Java. Pour résoudre ce
problème, nous ajoutons des méthodes get/set pour chaque variables déclarons dans l'inter-
face : une pour obtenir la valeur de la variable et une autre pour modier cette variable qui est
déclarée dans la classe qui implante cette interface. Par exemple, dans l'interface RI_Lights,
nous introduisons les deux méthodes getLightG() et setLightG(boolean var) pour la variable
LightG.
33
package component . adapter_1 ;
L'adaptateur est déni par une classe AdapterBean qui implante RI_Lights en utilisant
PI_Lights, comme présenté gure 3.13. Puisque les trois composants sont sur le même serveur,
le composant Adapter utilise le composant MultiLights localement (par @Local dans la classe
AdapterBean ).
package component . a d a p t e r ;
import component . m u l t i l i g h t . ∗ ;
import javax . ejb . Stateful ;
import javax . ejb . Local ;
import j a v a x . e j b . EJB ;
@Stateful
@Local ( RI_Lights . class )
public c l a s s AdapterBean implements RI_Lights {
@EJB
private PI_Lights mLights ;
34
3.2 Compatibilité au niveau signatures
Comme présenté dans la section 2.4.2, la compatibilité de signatures de méthodes est basée
sur la compatibilité de types. Rappelons que le type d'une méthode de l'interface requise est
représenté par τq , et celui d'une méthode de l'interface fournie est représenté par τl .
La vérication de la compatibilité de signatures peut être eectuée par le compilateur
Java. Les types de paramètres et le type du résultat sont exprimés en Java et nous n'avons
Pour illustrer ceci, nous présentons deux exemples, avec l'interface requise BankAccount
et l'interface fournie Account (voir gure 3.14).
public i n t e r f a c e B a n k A c c o u n t { public i n t e r f a c e A c c o u n t {
public B a n k A c c o u n t ( Money amt , S t r i n g own ) ; public A c c o u n t ( MoneyOps amt , S t r i n g own ) ;
public Money b a l a n c e ( ) ; public MoneyOps b a l a n c e ( ) ;
public void p a y I n t e r e s t ( double r a t e ) ; public void p a y I n t e r e s t ( double r a t e ) ;
public void d e p o s i t ( M o n e y C o m p a r a b l e amt ) ; public void d e p o s i t ( MoneyOps amt ) ;
public void w i t h d r a w ( M o n e y C o m p a r a b l e amt ) ; public void w i t h d r a w ( MoneyOps amt ) ;
} }
Les deux types MoneyComparable et MoneyOps utilisés dans les deux interfaces ci-dessus
sont eux-même dénis par les deux interfaces, comme présenté gure 3.15.
public i n t e r f a c e MoneyComparable
public i n t e r f a c e MoneyOps
extends Money {
extends MoneyComparable {
public boolean g r e a t e r T h a n ( Money m2 ) ;
public MoneyOps p l u s ( Money m2 ) ;
public boolean gtThanOrEqTo ( Money m2 ) ;
public MoneyOps m i n u s ( Money m2 ) ;
public boolean l e s s T h a n ( Money m2 ) ;
public MoneyOps s c a l e B y ( double factor );
public boolean l e s s T h a n O r E q T o ( Money m2 ) ;
}
}
τq = (double) → void
τl = (double) → void
Facilement, nous avons τq = τl . Ceci correspond à la compatibilité exacte dénie par A.
M. Zaremski et J. M. Wing.
Observons un autre cas : Money balance() et MoneyOps balance(), comme présenté gure
3.14. Nous avons :
τq = ()2 → Money
τl = () → MoneyOps
Sachons que Money est une super-interface de MoneyOps (voir gure 3.15), nous pouvons
remplacer MoneyOps par Money selon la règle du renommage des variables [30], alors τq =
V τl , correspondant à la compatibilité de signatures exacte.
2
() signie que cette méthode n'a pas de parammètres.
35
deposit(MoneyComparable amt) et withdraw(MoneyComparable amt)
Les deux méthodes :
τq = (MoneyComparable) → void
τl = (MoneyOps) → void
compatibilité entre méthodes. Nous essayons d'appliquer ces travaux pour diérents aspects
de JML.
3.3.1 Invariant
L'invariant (clause invariant predicatJM L ) est une propriété qui doit toujours être vraie.
Dans la spécication des interfaces, nous pouvons utiliser l'invariant au lieu de déclarer les
methode_Rpre = methode_Rpre ∧ IN V _R
methode_Rpost = methode_Rpost ∧ IN V _R
methode_Ppre = methode_Ppre ∧ IN V _P
methode_Ppost = methode_Ppost ∧ IN V _P
Illustrons la compatibilité dans ce cas par l'exemple suivant :
public i n t e r f a c e CounterR {
public i n t e r f a c e CounterP {
int CAPACITY = 1 0 0 ;
int CAPACITY = 1 0 0 ;
/ /@ public model int val ;
/ /@ public model int val ;
/ ∗@ public invariant
/ ∗@ requires
@ 0 <= val && val < CAPACITY ;
@ 0 <= val && val < CAPACITY ;
@∗ /
@ assignable val ;
@ ensures val == \ o l d ( v a l ) + 1
/ ∗@ assignable val ;
@ && 0 <= val && val < CAPACITY ;
@ ensures val == \ o l d ( v a l ) + 1;
@∗ /
@∗ /
36
Pour l'interface CounterR, il existe un invariant mais il n'y a pas de précondition de
la méthode incR. Par défaut, la précondition de cette méthode : incRpre = true. Après
La relation entre les préconditions et entre les postconditions des deux méthodes est :
incRpre ⇔ incPpre
incPpost ⇔ incRpost
Ces relations sont satisfaites et la formule 2.7 est vraie indiquant une compatibilité pré/-
Comme présenté dans la section 2.3, une méthode pure est exprimée dans le comportement à
l'aide de :
diverges false ;
assignable \nothing ;3
Pour une méthode impure, dans le comportement, nous déclarons une liste des variables
sont déjà exprimés dans le comportement de sa méthode. La compatibilité entre ces deux
public i n t e r f a c e pureR {
public i n t e r f a c e pureP {
/ ∗@ requires
/ /@ public model int somme ;
@ a >= 0 && b >= 0 && c >= 0;
@ ensures \result == a + b + c ;
/ ∗@
@∗ /
@
ensures \result == a + b + c
&& somme == \ r e s u l t ;
@∗ /
}
public i n t addP ( int a, int b, int c );
}
Les préconditions et postconditions des deux méthodes addR et addP sont représentées
par :
3
Cela veut dire qu'il n'y a pas de variables qui sont modiées
37
addRpre = (a >= 0 && b >= 0 && c >= 0)
addRpost = (\result == a + b + c)
addPpre = true
addPpost = (\result == a + b + c && somme == \result)
Selon la dénition de la compatibilité entre deux méthodes :
addRpre ⇒ addPpre
addPpost ⇒ addRpost
Cela correspond à la compatibilité plug-in entre les deux méthodes addR et addP. Il faut
ajouter que nous considérons seulement la compatibilité entre les deux méthodes. Si nous
vérions la compatibilité entre les deux interfaces, ce n'est pas vrai ça ne marche pas parce
3.3.3 Visibilité
Nous divisons la visibilité en trois niveaux :
a) Visibilité d'interface
Dans Java, il est obligatoire de déclarer l'interface avec la visibilité public.
JML. Dans notre approche, nous étudions la visibilité de plus haut niveau.
private Si la visibilité d'une méthode d'interface est private, cela signie que la méthode est
utilisé uniquement dans son interface. Cette visibilité n'est pas utilisée dans notre approche.
protected et public Dans notre travail, ces deux types de visibilité sont utilisables parce
de spécications. Il n'y a donc pas de conit entre la visibilité de Java et celle de JML.
Si la visibilité de la variable est private, cela signie que la variable est utilisée seulement
dans son interface, elle n'est pas utilisée à l'extérieur. Ce cas n'a donc pas intérêt ici.
requise utilise une variable de l'interface fournie de ce type, ces deux types de visibilité
sont utilisables.
alors : comment déterminer la compatibilité entre deux méthodes ayant plusieurs comporte-
ments ?
38
Pour simplier notre travail, nous divisons en quatre cas en fonction du nombre de com-
portements.
Cas 1 C'est le cas le plus simple, nous comparons la précondition et la postcondition cor-
public i n t e r f a c e nbCompP{
public i n t e r f a c e nbCompR{
/ ∗@ public normal_behavior
@ requires a > b;
/ ∗@ public normal_behavior
@ ensures \result == a − b;
@ requires a != b;
@ also
@ ensures
@ public normal_behavior
@ \result == a b s ( a − b);
@ requires a < b;
@∗ /
@∗ /
ensures \result == b − a;
}
public i n t subP ( int a, int b);
}
public i n t e r f a c e nbCompP{
public i n t e r f a c e nbCompR{
/ ∗@ public normal_behavior
@ requires a > b;
/ ∗@ public normal_behavior
@ ensures \result == b − a;
@ requires a != b;
@ also
@ ensures
@ public normal_behavior
@ \result == a b s ( a − b);
@ requires a < b;
@∗ /
@∗ /
ensures \result == a − b;
}
public i n t subP ( int a, int b);
}
Bien que nous ayons permuté les deux postconditions de subP, nous obtenons le même
résultat de compatibilité que dans l'exemple précédent. En fait, cette compatibilité n'est pas
utilisable parce que ces deux méthodes ne sont pas comparables. Pour résoudre ce problème,
nous utilisons la compatiblité de prédicats. Pour l'exemple précédent, la compabilité est véri-
39
((B1pre ⇒ B1post ) ∨ (B2pre ⇒ B2post )) ⇔ (Apre ⇒ Apost )
Cette formule prouve aussi que le deuxième exemple ne satisfait pas la compatibilité.
W
(Bipre ⇒ Bipost ) ⇔ (⇒) (Apre ⇒ Apost )
public i n t e r f a c e nbCompR{
/ ∗@ public normal_behavior
public i n t e r f a c e nbCompP{
@ requires a > b;
/ ∗@ public normal_behavior
@ ensures \result == a − b;
@ requires a != b;
@ also
@ ensures
@ public normal_behavior
@ \result == a b s ( a − b);
@ requires a < b;
@∗ /
@
@∗ /
ensures \result == b − a;
public i n t subP ( int a, int b);
}
public i n t subR ( int a, int b);
}
En général, si une méthode subR avec n comportements veut utiliser une méthode subP
ayant un seul comportement, la formule suivante doit être satisfaite :
W
(Bpre ⇒ Bpost ) ⇔ (⇒) (Aipre ⇒ Aipost )
Cas 4 Il correspond à la combinaison des cas 2 et cas 3. La formule à vériée est la suivante :
W V
(Bjpre ⇒ Bjpost ) ⇔ (⇒) (Aipre ⇒ Aipost )
3.3.5 Exceptions
Les exceptions jouent un rôle important en Java. Elles peuvent également être spéciées
nous examinons les diérents cas possibles où il existe une (plusieurs) exception(s) dans une
méthode de l'interface requise et dans l'interface fournie, présentés dans le tableau suivant :
40
Cas 2 Il existe une (plusieurs) exceptions(s) dans la spécication d'une méthode de l'inter-
face fournie.
public i n t e r f a c e IP {
public i n t e r f a c e IR {
/ ∗@
@
public normal_behavior
@∗ /
signals_only NegativeException ;
}
public i n t int a , int b)
addP (
throws N e g a t i v e E x c e p t i o n ;
}
Dans les méthodes addR et addP, les parties normal_behavior sont identiques, c'est-à-dire
que addRpre ⇔ addPpre . Lorsque addRpre = true, nous avons aussi addP = true, l'exception
n'est donc pas utilisée. Par contre, si addRpre = f alse, il ne faut pas considérer addP.
public i n t e r f a c e IP {
/ ∗@ public normal_behavior
public i n t e r f a c e IR {
@
@
requires
ensures
a >= b ;
\result == a−b ;
/ ∗@ public normal_behavior
@ also
@ requires a > b;
@ public exceptional_behavior
@ ensures \result == a−b ;
@ requires a < b;
@∗ /
@∗ /
signals_only NegativeException ;
}
public i n t int a , int b)
subP (
throws N e g a t i v e E x c e p t i o n ;
}
Dans les comportements normaux des deux méthodes subR (de l'interface IR ) et subP (de
l'interface IP ), nous avons subRpre ⇒ subPpre (subRpre = (a > b) ; subPpre = (a >= b)).
Si subRpre = true alors subPpre = true, l'exception de subP n'est pas utilisée
public i n t e r f a c e IP {
@ requires Ppre ;
@∗ / @ requires PE ;
@∗ /
41
Il correspond à l'hypothèse où :
(sans exceptions). La condition (3) assure qu'il n'y a pas de mélange entre Ppre et P E,
l'exception de P.
La compatibilité entre deux méthodes est exprimée par :
La notion d'exception n'est donc pas concernée avec la compatibilité entre les deux mé-
public i n t e r f a c e IR {
/ ∗@ public normal_behavior
@
requires
ensures
a > b;
\result == a−b ;
public i n t e r f a c e IP {
/ ∗@ public normal_behavior
@ also
@ requires a >= b ;
@ public exceptional_behavior
@ ensures \result == a−b ;
@ requires a <= b ;
@∗ /
@
@∗ /
signals_only NegativeException ;
public i n t subP ( int a, int b);
}
public i n t int a , int b)
subR (
throws N e g a t i v e E x c e p t i o n ;
}
Dans les comportements normaux, subRpre ⇒ subPpre . Si subRpre = true, alors subPpre =
true et nous vérions la relation entre subPpost et subRpost pour déterminer la compatibilité.
Par contre, si subRpre = f alse, alors subR lance son exception sans utilier subP.
Supposons que pour le cas 3, nous ayons une forme générale suivante :
public i n t e r f a c e IR {
/ ∗@ public normal_behavior
@ requires RE ; @∗ /
4
Nous utilisons seulement une implication parce que Rpre ⇔ Ppre est un cas particulier de Rpre ⇒ Ppre
5
La condition (Rpre ⇒ Ppre ) and (Rpre ) assure que Rpre = true et Ppre = true et (Rpre ⇒ Ppre ) = true
42
Rpre ⇔ (⇒) Ppre (1)
Ppost ⇔ (⇒) Rpost (2)
Rpre ∧ RE = φ (3)
Les conditions (1) et (2) assurent qu'il existe une compatibilité entre les deux méthodes
(sans exception). La condition (3) assure qu'il n'y a pas de mélange entre Rpre et RE , l'ex-
ception de R.
Si Rpre = true : Ppre = true et la méthode P() est appelée
Cela correspond à :
Cas 4 C'est le cas général où dans une méthode de l'interface requise et celle de l'interface
À l'aide des deux cas précédents, la compatibilité entre deux méthodes est basée sur des
public i n t e r f a c e IR { public i n t e r f a c e IP {
/ ∗@ public normal_behavior / ∗@ public normal_behavior
@ also @ also
@∗ / @∗ /
satisfaite.
La forme générale :
public i n t e r f a c e IR { public i n t e r f a c e IP {
/ ∗@ public normal_behavior / ∗@ public normal_behavior
@ also @ also
@ requires RE ; @ requires PE ;
@ signals_only E1 ; @ signals_only E2 ;
@∗ / @∗ /
43
Rpre ⇔ (⇒) Ppre (1)
Ppost ⇔ (⇒) Rpost (2)
Rpre ∧ RE = φ (3) Ppre ∧ P E = φ (4)
Cas 2
Cas 3
Cas 4
En conclusion, la compatibilité entre deux méthodes dans lesquelles il existe une (plusieurs)
44
La compatibilité entre deux méthodes sans exception(s)
45
Chapitre 4
Conclusion et perspectives
4.1 Conclusion
L'approche composant est un paradigme très connu, utilisé pour le développement des lo-
giciels aussi bien dans le milieu académique que dans le milieu industriel. Les composants sont
considérés comme des "boîtes noires" décrites en termes de leur comportement visible et de
leurs interfaces (requises et fournies). En communiquant via leurs interfaces, des composants
L'objectif principal de notre travail de stage a porté sur l'établissement d'une liaison entre
des travaux proposés par l'équipe DEDALE sur l'assemblage UML/B et les technologies à
base de composants logiciels usuelles telles que les Enterprise Java Beans ou les composants
.NET. En d'autres termes, nous avons établi des liens entre deux niveaux d'abstraction : au
Les Enterprise Java Beans sont une technologie à base de composants implémentés comme
une surcouche à Java. JML, Java Modeling Language, est un langage de spécication formelle
pour Java. Les adaptateurs entre composants permettent d'assurer l'interopérabilité entre
composants. Des schémas de développement d'adaptateurs à l'aide de B [11] ont été proposés
Nous avons proposé une mise en correspondance entre achitecture d'assemblage UML/B
et EJB. Nous avons proposé une dénition des adaptateurs en fonction des EJBs manipulés.
Ce travail a été élaboré à partir d'une étude de cas réelle du système contrôle d'accès à un
ensemble de bâtiments.
À notre connaissance, il n'existe pas de travaux sur l'interopérabilité entre méthodes (in-
terfaces respectives) en Java Modeling Language. Nous avons proposé, en partant des travaux
de A. M. Zaremski et J. M. Wing sur la compatibilité de spécications, une dénition de la
compatibilité directe entre deux méthodes déclarées dans leur interface en Java et dont le
Nous avons étudié comment les composants EJBs implantés interagissent et eectué
Nous avons cité la possibilité du passage vers les technologies existantes à base de com-
DEDALE. Ceci est exprimé par la correspondance entre l'architecture UML/B et EJB
46
et par la compatibilité entre méthodes à l'aide de JML.
4.2 Perspectives
À partir du travail eectué, de nombreuse perspectives sont envisageables. Parmi celles-ci,
les deux niveaux considérés dans notre approche peuvent être considérés :
Il est aussi envisageable de formaliser le lien entre UML/B et EJB à l'aide des travaux
considération :
terface fournie
La dénition d'un adaptateur entre composants via des interfaces requises et des interfaces
fournies pour leur interopérabilité pourrait être revisitée en prenant comme base une approche
algébrique. Dans le cas de la compatibilité directe entre deux interfaces, l'adapateur entre
2. Un contrat imcomplet. Par exemple, l'interface requise A dispose des trois méthodes
n_1, n_2, n_3 et l'interface fournie B dispose des trois méthodes n_1, n_2, n_4 (voir
tableau suivant).
Considérons les deux méthodes n_3 et n_4. Elles ont la même postcondition n_3post
mais leur précondition est diérente. Pour s'assurer de l'interopérabilité entre ces deux
47
Cette approche correspond à l'adjonction de conditions dans l'adaptateur permettant de
créer de nouvelles connexions entre deux interfaces existantes par diminution des diérences
48
Bibliographie
[1] J.-R. Abrial. The B Book. Cambridge University Press, 1996.
[2] F. Badeau and A. Amelot. Using B as a high level programming language in an industrial
in a large project. In Integrated Formal Methods, IFM99, volume 1708 of LNCS, pages
2006.
49
[15] Arnaud Lanoix, Samuel Colin, and Jeanine Souquières. Développement formel par com-
[16] Gary T. Leavens, Albert L. Baker, and Clyde Ruby. JML : A notation for detailed design.
[17] Gary T. Leavens, Erik Poll, Curtis Clifton, Yoonsik Cheon, Clyde Ruby, David Cok,
Peter Muller, Joseph Kiniry, Patrice Chalin, and Daniel M. Zimmerman. JML Reference
[21] Steria. Obligations de preuve : Manuel de référence, version 3.0. Steria Technologies
de l'information, 1998.
[25] B. Tatibouet, A. Requet, J.C. Voisinet, and A. Hammad. Java Card code generation
4.0.
[28] Gary T.Leavens and Yoonsik Cheon. Design by Contract with JML DRAFT, 2006.
[29] J.-C. Voisinet and B. Tatibouet. Génération de code à partir du langage formel B vers
[30] A. M. Zaremski and J. M. Wing. Signature matching : a tool for using software libraries.
50