Vous êtes sur la page 1sur 51

Institut de la Francophonie pour l'Informatique LORIA

Hanoi, Vietnam Nancy, France

Approche Composant :
de la spécication à l'implantation

Mémoire de n d'études

Thi Minh Tuyen Nguyen

Lieu de stage : Équipe DEDALE, LORIA

Campus Scientique, BP 239

F-54506 Vand÷uvre lès Nancy Cedex

Sous la direction de : Arnaud Lanoix

Jeanine Souquières

Nancy, le 14 novembre 2008


Remerciements
Je voudrais tout d'abord remercier Jeanine Souquières de m'avoir accueillie au sein de

l'équipe de recherche DEDALE du Laboratoire Lorrain de Recherche en Informatique et ses

Applications (LORIA).

Je tiens également à remercier tout particulièrement Arnaud Lanoix et Jeanine Souquières

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

cours des neuf mois de ce stage, et plus particulièrement à Samuel Colin.

Je remercie chaleureusement mes camarades de la promotion XII pour leur amitié sans

faille et je leur souhaite bonne chance pour la soutenance.

Finalement j'adresse un grand merci à toute ma famille et mes amis pour leur soutien et

leur encouragement de tout l'instant.

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

de la compatibilité entre méthodes à l'aide de Java Modeling Language (JML).

Mots-clés : composant, adaptateur, spécication, compatibilité, EJB, JML

Abstract
The DEDALE team, a research group at LORIA institute, works on component-based

software verication approaches. Components are considered as black-boxes communicating

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-

lity using the Java Modeling Language (JML).

Keywords : component, adapter, specication, matching, EJB, JML

2
Table des matières

1 Introduction 7
1.1 Problématique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

1.2 Objectif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

1.3 Contribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.3.1 Au niveau programmation . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.3.2 Au niveau spécication . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.4 Environnement de stage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.5 Contenu du mémoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

2 État de l'art 10
2.1 Adaptateur et B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2.1.1 Vue générale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2.1.2 Méthode B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2.1.3 Interopérabilité entre composants . . . . . . . . . . . . . . . . . . . . . 12

2.1.4 Diérents assemblages de composants . . . . . . . . . . . . . . . . . . 12

2.2 Enterprise Java Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.2.1 Dénition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.2.2 Présentation d'un composant EJB . . . . . . . . . . . . . . . . . . . . 13

2.2.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.3 Java Modeling Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

2.3.1 Dénition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

2.3.2 Spécication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

2.3.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2.4 Compatibilité de spécications . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2.4.1 Dénition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2.4.2 Compatibilité au niveau signatures . . . . . . . . . . . . . . . . . . . . 22

2.4.3 Compatibilité au niveau comportements . . . . . . . . . . . . . . . . . 22

3 Propositions 25
3.1 Dénition d'un adaptateur au niveau EJB . . . . . . . . . . . . . . . . . . . . 25

3.1.1 Schéma d'achitecture de composant . . . . . . . . . . . . . . . . . . . . 25

3.1.2 Correspondance entre l'achitecture UML et EJB . . . . . . . . . . . . 25

3.1.3 Diérents types d'adaptateurs en fonction des EJBs manipulés . . . . 28

3.1.4 Étude de cas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

3.2 Compatibilité au niveau signatures . . . . . . . . . . . . . . . . . . . . . . . . 35

3.3 Compatibilité au niveau comportements avec JML . . . . . . . . . . . . . . . 36

3
3.3.1 Invariant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

3.3.2 Méthode pure, méthode impure et clause assignable . . . . . . . . . . 37

3.3.3 Visibilité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

3.3.4 Comportements possibles dans une méthode . . . . . . . . . . . . . . . 38

3.3.5 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

4 Conclusion et perspectives 46
4.1 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

4.2 Perspectives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

4.2.1 Niveau programmation . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

4.2.2 Niveau spécication . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

4
Table des gures
2.1 Modèle B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

2.2 Interopérabilité entre OTS1 et OTS2 . . . . . . . . . . . . . . . . . . . . . . . 12

2.3 Adaptation vue comme le développement d'un nouveau composant . . . . . . 12

2.4 Un composant EJB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.5 Diérence entre @Remote et @Local . . . . . . . . . . . . . . . . . . . . . . . 14

2.6 Exemple de composant EJB . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.7 Code source des interfaces IB et IC . . . . . . . . . . . . . . . . . . . . . . . 16

2.8 Code source des composants B et C . . . . . . . . . . . . . . . . . . . . . . . 16

2.9 Code source de l'application A . . . . . . . . . . . . . . . . . . . . . . . . . . 17

2.10 Forme générale d'une spécication JML d'une méthode Java . . . . . . . . . . 19

2.11 Interface PI_MLights en JML . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2.12 Idée de compatibilité plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

3.1 Exemples d'assemblage UML . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

3.2 Correspondance entre l'achitecture UML et EJB - Cas 1 . . . . . . . . . . . . 26

3.3 Correspondance entre l'achitecture UML et EJB - Cas 2 . . . . . . . . . . . . 27

3.4 Correspondance entre l'achitecture UML et EJB - Cas 3 . . . . . . . . . . . . 27

3.5 Adaptateur - Cas 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

3.6 Adaptateur - Cas 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

3.7 Adaptateur - Cas 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

3.8 Adaptateur - Cas 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

3.9 Adaptateur - Cas 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

3.10 Étude de cas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

3.11 Étude de cas exprimée dans EJB . . . . . . . . . . . . . . . . . . . . . . . . . 33

3.12 Code source des interfaces RI_Lights et PI_Lights . . . . . . . . . . . . . . . 34

3.13 Code source de l'adaptateur AdapterBean . . . . . . . . . . . . . . . . . . . . 34

3.14 Exemple des interfaces BankAccount et Account . . . . . . . . . . . . . . . . . 35

3.15 Exemple des interfaces MoneyComparable et MoneyOps . . . . . . . . . . . . 35

5
Liste des tableaux
2.1 Diérences entre Stateless Session Beans et Stateful Session Beans . . . . . . 14

2.2 Caractéristiques des trois types de Beans . . . . . . . . . . . . . . . . . . . . . 15

3.1 Diérences entre les trois types de Bean . . . . . . . . . . . . . . . . . . . . . 25

3.2 Résumé la compatibilité entre deux méthodes avec exception(s) . . . . . . . . 44

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

supportées par des méthodes de conception, de vérication et d'intégration adaptées à cette

nouvelle problématique.

L'équipe DEDALE du LORIA (voir section 1.4) travaille sur la conception de méthodes

de développement pour la vérication d'architectures logicielles à base de composants [4] :

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

coopérer, c'est-à-dire que leurs interfaces doivent être compatibles.

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

de preuve associés à la méthode B.

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

aux questions suivantes :

 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 ?

 Comment les composants logiciels implantés interagissent-ils au sein de ces diérentes

plateformes ? Comment s'eectue l'assemblage des composants ?

 L'expressivité du modèle de composants UML 2.0 / B proposé dans l'équipe DEDALE

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-

veaux du cycle de développement : au niveau spécication et au niveau programmation. Notre

contribution est divisée en deux parties selon ces niveaux.

1.3.1 Au niveau programmation


Parmi les technologies basées sur les composants existants, nous avons étudié les Enter-

prise Java Beans (EJB), technologie très connue utilisant Java. La méthode B est une mé-

thode formelle permettant de vérier formellement l'interopérabilité entre composants dont

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.

1.3.2 Au niveau spécication


Il existe un langage de spécication pour Java : Java Modeling Language (JML) [9]. Une

caractéristique commune à B et JML : ce sont des langages de spécication haut niveau,

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

Krakatoa ([10]). Néanmoins, la spécication et la vérication de l'adaptation à l'aide de JML

au niveau interface ne sont pas prise en compte. Notre travail consiste à étudier la compatibilité

entre méthodes de l'interface requise et celles de l'interface fournie en utilisant JML.

1.4 Environnement de stage


Le LORIA, Laboratoire Lorrain de Recherche en Informatique et ses Applications, est une

Unité Mixte de Recherche commune à plusieurs établissements : CNRS (Centre National de

Recherche Scientique), INPL (Institut National Polytechnique de Lorraine), INRIA (Institut

National de Recherche en Informatique et en Automatique), UHP (Université Henri Poincaré,

Nancy 1) et Nancy 2 (Université Nancy 2).

Fondé en 1997, le LORIA se concentre sur ses trois missions principales : la recherche fon-

damentale et appliquée au niveau international dans le domaine des Sciences et Technologies

8
de l'Information et de la Communication, la formation par la recherche en partenariat avec

les Universités lorraines et le transfert technologique par le biais de partenariats industriels

et par l'aide à la création d'entreprises.

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

spécications et de programmes, dans le but d'acquérir une meilleure maîtrise de la production,

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,

construire, modier et réutiliser. L'objectif principal est d' :

 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,

 comprendre et décrire des méthodes de développement en utilisant les langages de spé-

cications existants et les outils associés à ces langages tout au long du développement,

et pas uniquement lorsque la spécication est terminée.

Les axes thématiques de l'équipe concernent la :

 Dénition de guides méthodologiques pour l'expression des besoins et le passage assisté

à une spécication formelle.

 Intégration des outils de validation et de vérication dans le processus de développement

de spécications formelles.

 Spécication de systèmes par composants avec preuve de leur interopérabilité [4, 8, 12,

14, 15].

 Spécication et vérication de systèmes multi-agents situés [20].

1.5 Contenu du mémoire


La mémoire est structuré de la manière suivante.

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.

Le chapitre 3 présente la contribution de notre stage à deux niveaux d'expression : le

niveau programmation et le niveau spécication.

Nous terminons ce mémoire par une conclusion et des perspectives.

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

présenter des points importants concernant notre travail.

2.1.1 Vue générale


L'approche composant est une approche de développement de logiciels intéressante [24].

Une application à composants consiste en une composition de composants, chaque compo-

sant est considéré comme une boîte noire. Des composants logiciels sont développés par

assemblage et adapatation pour produire un système complet.

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

les fonctionnalités permettant d'implanter la seconde. An de garantir l'interopérabilité entre

composants, il est nécessaire d'avoir une description appropriée des interfaces et de vérier

la correction de cette connexion. Le terme correction d'une connexion peut s'exprimer en

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

preuve de leur interopérabilité [4, 15].

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

de plusieurs composants existants.

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

implantation. Les caractéristiques principales de B sont les suivantes :

 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

réaliser des vérications formelles ;

 la modularité qui facilite le développement par morceaux de systèmes complexes ;


 le ranement pour un développement incrémental du niveau de détail, ainsi que pour
la génération de code.

La méthode B a été utilisée pour des applications industrielles complexes, en particulier

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

développé grâce à la méthode B.

b) Construction d'un modèle B


Le principe d'un modèle tient dans l'expression de propriétés du système qui doivent

rester vraies après toute étape d'évolution du modèle. La correction du modèle signie la

préservation de ses propriétés, exprimées par un invariant.

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

Fig. 2.1  Modèle B

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

body1 est spécié selon la syntaxe du langage des substitutions de B.


Les autres clauses du modèle générique de la gure 2.1 ont trait à la modularité : seen_model
SEES est un modèle B qui peut être vu mais dont l'état ne peut pas être modié.
de la clause

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

nécessaires à l'interface requise.

En d'autres termes, nous pouvons dénir l'interopérabilité entre composants de la manière

suivante à l'aide de B [4].

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].

Fig. 2.2  Interopérabilité entre OTS1 et OTS2

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

deux manières de développement sont considérées équivalentes [15].

Fig. 2.3  Adaptation vue comme le développement d'un nouveau composant

Développer un adaptateur qui assure la bonne connexion entre un composant OTS1 et un

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.

2.1.4 Diérents assemblages de composants


Dans une approche de réutilisation, les composants existants ont rarement des interfaces

directement compatibles. Un  nouveau  composant est nécessaire pour les rendre compa-

tibles. Le développement de ce composant peut être plus ou moins complexe, en fonction du

nombre et du type de composants existants à assembler. La dénition des diérents cas d'ar-

chitecture et des schémas pour assembler un ou plusieurs composants et vérier la correction

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

ces diérents assemblages de composants avec les Enterprise Java Beans.

2.2 Enterprise Java Beans


2.2.1 Dénition
Écrite en Java, la technologie Enterprise Java Beans (EJB) [22] est une architecture de

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

serveurs distants) hébergés au sein d'un serveur d'applications


3 permettant de représenter 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.

La notion de "Bean" est considérée comme un EJB ou un composant.

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

(voir gure 2.4).

Fig. 2.4  Un composant EJB

2.2.2 Présentation d'un composant EJB


Une diérence entre les composants EJBs et la notion de composants dans d'autres tech-

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.

Nous détaillons les caratéristiques de chaque type.

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.

Stateless Session Beans Stateful Session Beans


- Sans état - Avec un état (en mémoire)

- Ne conservent pas d'information entre - Mémorisent les informations

deux appels successifs

- Deux instances quelconques d'un tel - Même instance pendant toute la durée

Bean sont équivalentes d'une session avec un client

- Une instance par appel - Une instance par client

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

deux types d'utilisation dans la gure 2.5.

Fig. 2.5  Diérence entre @Remote et @Local

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

sont déployés sur le même machine.

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

méthode d'un Message-Driven Bean.

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

utilisés à distance à l'aide les Session Beans.

d) Synthèse
Le tableau 2.2 présente les diérences entre les trois types de Beans [7].

Session Beans Message-Driven Beans Entity Beans


- S'exécutent au nom d'un - S'exécutent selon l'accusé de - Font partie d'un modèle de
client simple a réception d'un message d'un domaine, fournissent une vue
client simple d'objet de données dans la base
de données
- Modient des données parta- - Peuvent modier des données
gées dans la base de données partagées dans la base de don-
nées
- Ne représentent pas direc- - Ne représentent pas direc-
tement des données partagées tement des données partagées
dans la base de données quoi dans la base de données quoi-
qu'ils peuvent y accéder et les qu'ils peuvent y accéder et les
modier modier
- Durent peu de temps - Durent peu de temps - Durent longtemps (leur durée
de vie est la même que celle des
données de la base de données)
- Sont détruits avec le conte- - Sont détruits avec le conte- - L'entité et sa clé primaire
neur d'EJB. Le client doit réta- neur d'EJB. Le conteneur doit survivent après destruction du
blir un nouvel objet de session rétablir un nouvel objet de conteneur d'EJB. Si l'état d'une
pour continuer les calculs Message-Driven pour continuer entité est modié par une tran-
les calculs saction lors de la destruction du
conteneur, l'état de l'entité est
reconstitué à partir de l'état de
la dernière transaction eectuée
- Sont appelés de manière asyn-
chrone
- Sans état
- Un conteneur d'EJB ty- - Un conteneur d'EJB ty- - Un conteneur d'EJB et le
pique fournit un environnement pique fournit un environnement serveur fournissent un environ-
d'exécution (runtime environ- d'exécution pour un grand nement d'exécution pour un
ment) pour un grand nombre nombre d'objets de Message- grand nombre d'objets d'entités
d'objets de sessions concur- Driven de manière concurrente concurrentes
rentes. La spécication EJB dé-
nit les Stateful et Stateless
Session Beans
single client en anglais, c'est-à-dire que chaque instance de Session Bean supporte seulement un client. Si
a

deux clients appellent une même instance de Session Bean, il y a une erreur.

Tab. 2.2  Caractéristiques des trois types de Beans

15
2.2.3 Exemple
Nous présentons dans le gure 2.6 un exemple générique d'application client/serveur

complet en utilisant des EJBs.

Fig. 2.6  Exemple de composant EJB

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).

package component_B ; package component_C ;

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 ( ) ;
} }

Fig. 2.7  Code source des interfaces IB et IC


Les composants B et C (gure 2.8) sont déclarés en utilisant des annotations d'EJB.

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 ( ) ;
....
}
}

Fig. 2.8  Code source des composants B et C

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

@Local parce que B (qui utilise C ) et C sont sur le même serveur.


L'application A côté client (voir gure 2.9) déclare @EJB pour utiliser des composants

EJBs côté serveur.


import j a v a x . e j b . EJB ;

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 ( ) ;
....
}
}

Fig. 2.9  Code source de l'application A

2.3 Java Modeling Language


2.3.1 Dénition
Java Modeling Language (JML) est un langage de spécications formelles de comporte-

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 :

 Invariant : propriété toujours vraie quel que soit l'état du système

 Précondition : propriété qui doit être vériée avant l'appel d'une méthode

 Postcondition : propriété vériée après l'exécution 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

portent sur les attributs de la classe [17] :

 Constraintes initiales (clause initially predicatJM L ) : les propriétés qui doivent être

établies à la création de l'objet

 Invariants de classe (clause invariant predicatJM L ) : ce sont les propriétés portant

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

 Constraintes historiques (clause constraint predicatJM L ) : expriment la propriété entre


un état visible et l'état visible précédent ; elle doit être vraie dans tous les états du

système (invariant dynamique)

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

 Divergence (clause diverges predicatJM L ) : condition sous laquelle la méthode peut ne

pas terminer, i.e. boucles innies

 Champs modiés (clause assignable predicatJM L ) : liste des attributs qui sont modiés
par l'exécution de la méthode

 Postcondition normale (clause ensures predicatJM L ) : condition que la méthode s'en-

gage à établir lorsqu'elle termine normalement, c'est-à-dire sans lever d'exception

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

méthodes de consultation des classes de l'API Java


5 sont considérées comme pures. On peut

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

est levée quand des postconditions normales ne sont pas vériées.

Dans JML, pour dénir une (plusieurs) exception(s) d'une méthode, nous utilisons la

notion Postcondition exceptionnelle, exprimée par l'expression suivante :


signals (Exception1 exp) predicatJM L
Le predicatJM L indique la postcondition qui doit être vériée à la n de la méthode quand

celle-ci se termine en levant une exception exp de type Exception1.


Une autre notion est celle d'Exceptions autorisées :

signals_only E1, E2 . . .
indique que E1, E2 . . . sont les seules exceptions autorisées à être levées par la méthode

considérée.

La forme générale d'un comportement est dénie dans le gure 2.10.

5
Java Application Programming Interface

18
/ ∗@ behavior

@ requires P ; // default = true

@ diverges D ; // default = false

@ assignable A ; // default = \ everything

@ ensures Q ; // default = true

@ signals_only E ; // default E

@ signals (E) S ; // default = true

@∗ /

T method ( T1 p1 , . . . ) throws E {
...
}

Fig. 2.10  Forme générale d'une spécication JML d'une méthode Java

d) Visibilité de Java et visibilité de JML


Dans Java, nous avons plusieurs niveaux de visibilité pour les attributs et les méthodes :

 par défaut : visible depuis toutes les classes du package

 public : visible depuis n'importe quelle autre classe


 private : visible uniquement à l'intérieur de la classe
 protected : visible depuis la classe, les sous-classes et n'importe quelle classe du package
Les annotations JML sont vues comme externes à la classe et doivent donc respecter

les contraintes de visibilités de Java. Pour modier la visibilité des attributs et des méthodes

uniquement au niveau spécication, JML dénit les deux modieurs suivants :

 spec_public
 spec_protected

e) Plusieurs comportements pour une méthode


Nous pouvons dénir plusieurs comportements pour une méthode à l'aide de "also" qui

combine les comportements de manière disjointe (ou) :

/ ∗@ behavior

@ requires P1 ;

@ ensures Q1 ;

@ signals ( E1 ) S1 ;

@ also

@ behavior

@ requires P2 ;

@ ensures Q2 ;

@ signals ( E2 ) S2 ;

@∗ /

T method ( . . . )
throws E1 , E2 {
...
}

Sa sémantique est la suivante :

19
/ ∗@ behavior

@ requires P1 || P2 ;

@ ensures P1 => Q1

@ & P2 => Q2 ;

@ signals (E e)

@ P1 => (( e instanceof E1 ) => S1 )&

@ P2 => (( e instanceof E2 ) => S2 ) ;

@∗ /

T method ( . . . )
throws E1 , E2 {
...
}

f) Comportements spéciques
Nous pouvons distinguer les comportements normaux et les comportements exceptionnels

en utilisant deux notions :

 normal_behavior indique que le comportement décrit correspond à un cas où la méthode

termine normalement sans déclancher d'exception. Cela veut dire que dans JML, la

condition de la clause signals est false :

signals (Exception) false


 exceptional_behavior indique que le comportement décrit correspond à un cas où la

méthode termine en déclenchant une exception. En d'autres termes, la condition de la

clause ensures est false :

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 :

//@ public model ML_Color color ;


//@ public model MLights_STATES ml_state ;

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) :

 La précondition : color != newColor

 La postcondition : 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

cette méthode exprime que la variable color peut être modiée.

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 {

/ /@ public model ML_Color color ;

/ /@ public model MLights_STATES ml_state ;

/ ∗@ requires c o l o r != newColor ;

@ assignable color ;

@ ensures color == n e w C o l o r ;

@∗ /

public void c h a n g e ( ML_Color n e w C o l o r ) ;

/ ∗@ requires m l _ s t a t e == MLights_STATES . ML_Off ;

@ assignable ml_state ;

@ ensures m l _ s t a t e = MLights_STATES . ML_On ;

@∗ /

public void on ( ) ;

/ ∗@ requires m l _ s t a t e == MLights_STATES . ML_On ;

@ assignable ml_state

@ ensures m l _ s t a t e = MLights_STATES . ML_Off ;

@∗ /

public void off ();


}

Fig. 2.11  Interface PI_MLights en JML

2.4 Compatibilité de spécications


Nous présentons certains détails des travaux d'A. M. Zaremski et J. M. Wing [30, 31]

en relation avec notre approche, en vue de les appliquer pour dénir la compatibilité entre

méthodes spéciées en JML.

2.4.1 Dénition
La compatibilité de spécications est un processus pour déterminer si deux composants

sont comparables et vise à répondre aux questions suivantes :

 Recherche : Comment est-ce que je peux trouver un composant à partir d'une biblio-

thèque en utilisant son comportement plutôt que sa structure syntaxique ?

 Réutilisation : Comment est-ce que je peux adapter un composant à partir d'une biblio-

thèque pour satisfaire des besoins d'un système ?

 Remplacement : Quand est-ce que je peux remplacer un composant par un autre sans

modier le comportement du système entier ?

 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 :

Match : Component, Component → Bool


M atch(C, C 0 ) = matchsig (Csig , Csig
0 0
) ∧ matchspec (Cspec , Cspec ) (2.1)

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

soit un type variable ∈ TypeVar soit un type operator ∈ TypeOp.


Généralement, en supposant que nous avons le type des méthodes dans la bibliothèque de

composants, τl , et le type de la requête, τq , alors la compatibilité M(τl ,τq ) est dénie par :

M : Library Type, Query Type → Boolean


M (τl , τq ) = ∃Tl and Tq such that Tl (τl ) R Tq (τq ) (2.2)

Dans lequel :

 Tl et Tq sont des transformations appliquées pour le type de la bibliothèque et celui de

la requête

 R est une relation entre Tl (τl ) et Tq (τq ), par exemple =T , ≤ ou ≥


La compatibilité de signatures est fonction de la relation R entre τl et τq et des transfor-

mations Tl , Tq .

b) Types de compatibilité de signatures


Deux types de compatibilité de signatures sont distingués.

Compatibilité exacte A partir de la formule 2.2, si :

 τl est une suite de renommages des variable V,


 τq est la fonction identité,
 R est =T

La compatibilité est dite exacte :

matchE (τl , τq ) = ∃ a sequence of variable renamings, V, such that


V τl =T τq (2.3)

Compatibilité relâchée Ce type est divisé en trois sous-types de compatibilité : Com-


patibilité Généralisée (Generalized Match), Compatibilité Spécialisée (Specialized Match) et
Compatibilité Uniée (Unify Match). Dans notre travail, nous n'utilisons que le type Compa-
tibilité Spécialisée, déni par

matchspec (τl , τq ) = τl ≤ τq (2.4)

Intuitivement, un type disponible en bibliothèque est compatible avec celui de la requête

si le type de la requête est plus général que celui de bibliothèque.

2.4.3 Compatibilité au niveau comportements


a) Dénition
Soient une bibliothèque de spécications S(Spre , Spost ) et une requête Q(Qpre , Qpost ). Deux

notions de compatibilité sont distinguées :

22
Dénition 1 La formule générale de compatibilité pré/post matchpre/post (S, Q) la plus

commune pour les méthodes est dénie par :

matchpre/post (S, Q) = (Qpre R1 Spre ) ∧ (Sb R2 Qpost ) (2.5)

Avec :

 R1 est la relation entre Qpre et Spre


 R2 est la relation entre Qpost et Spost
 R1 et R2 sont soit une équivalence (⇔) soit une implication (⇒)
 Sb est soit Spost soit Spre ∧Spost , en fonction du type de compatibilité. Dans notre travail,
Sb = Spost .

Dénition 2 La formule générale de compatibilité de prédicats est utile dans le cas où

nous avons besoin de considérer une relation de spécications plutôt qu'une relation entre des

parties correspondantes de spécications :

matchpred (S, Q) = Spred R Qpred (2.6)

Avec :

 Spred = Spre ⇒ Spost


 Qpred = Qpre ⇒ Qpost
 R, relation entre Spred et Qpred est soit une équivalence (⇔) soit une implication (⇒)

b) Types de compatibilité pré/post


Pour dénir l'interopérabilité directe entre les interfaces, nous avons besoin de deux types

de compatibilité :

Compatibilité pré/post exacte C'est le cas le plus simple lorsque la précondition et la

postcondition de chaque méthode de l'interface requise et celle fournie sont équivalentes. A

partir de la formule 2.5, avec Sb = Spost et R1 et R2 sont une équivalence, nous obtenons la

formule de Compatibilité pré/post exacte suivante :

matchE−pre/post (S, Q) = (Qpre ⇔ Spre ) ∧ (Spost ⇔ Qpost ) (2.7)

Illustrons ce cas de compatibilité à l'aide de l'exemple suivant :

public i n t e r f a c e interfaceR { public i n t e r f a c e interfaceP {

/ ∗@ requires a>=0 && b >=0; / ∗@ requires a>=0 && b >=0;

@ ensures \result == a+b ; @ ensures \result == a+b ;

@∗ / @∗ /

public i n t addR ( int a, int b); public i n t addP ( int a, int b);

} }

La précondition et la postcondition de deux méthode addR de l'interface interfaceR et

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

Compatibilité plug-in L'idée de compatibilité plug-in est exprimée gure 2.12.

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

gure, pour que Q puisse utiliser S :

Qpre est plus forte que Spre


Spost est plus forte que Qpost
À partir de la formule 2.5, avec Sb = Spost ; R1 et R2 sont une implication, nous avons la

formule de Compatibilité plug-in

matchplug−in (S, Q) = (Qpre ⇒ Spre ) ∧ (Spost ⇒ Qpost ) (2.8)

La compatibilité plug-in est illustrée par l'exemple suivant :

public i n t e r f a c e interfaceR { public i n t e r f a c e interfaceP {

/ ∗@ requires a>=0 && b >=0; / ∗@

@ ensures \result == a+b ; @ ensures \result == a+b ;

@∗ / @∗ /

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,

), addPpost ⇔ addRpost . En d'autres termes, nous pouvons dire (addRpre ⇒ addPpre ) ∧

(addPpost ⇒ addRpost ) , la compatibilité entre addR et addP est donc plug-in.

c) Types de compatibilité de prédicats


Compatibilité exacte À partir de formule 2.6, la compatibilité exacte correspond au cas

où R est une équivalence :

matchpred (S, Q) = Spred ⇔ Qpred (2.9)

Compatibilité généralisée Correspond à la formule 2.6 avec R est une implication :

matchpred (S, Q) = Spred ⇒ Qpred (2.10)

24
Chapitre 3

Propositions

3.1 Dénition d'un adaptateur au niveau EJB


Dans le chapitre 2, nous avons présenté trois types de Beans : Session Beans, Message-

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.

Ils sont utilisés à distance via d'un Session Bean.

Les diérences entre les trois types en termes d'interfaces sont résumées dans le tableau

3.1.

Session Beans Message-Driven Beans Entity Beans


Interface Oui, Java pur Non Non

Classe Oui Oui Oui

Appele à distance Oui, via une inter- Par le conteneur À l'aide d'autres

face Beans

Tab. 3.1  Diérences entre les trois types de Bean

Les Session Beans sont une solution permettant d'exprimer l'interopérabilité entre com-

posants car ils possèdent des interfaces.

3.1.1 Schéma d'achitecture de composant


En utilisant les travaux de l'article [15] sur l'assemblage de composants, notre objectif est

d'eectuer la liaison entre cette démarche d'assemblage et EJB. Dans la suite, nous présentons

les diérents cas et leur modélisation en EJB.

3.1.2 Correspondance entre l'achitecture UML et EJB


Les trois cas de la gure 3.1 sont fondés sur l'utilisation d'un (ou deux) composant(s)

existant(s) OTS (OTS1 et OTS2 ).

25
Fig. 3.1  Exemples d'assemblage UML

a) Cas de base : une seule interface dans l'assemblage


Figure 3.2, notre objectif est de dénir un composant DEV à dénir, requiert une interface

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.

Fig. 3.2  Correspondance entre l'achitecture UML et EJB - Cas 1

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.

Fig. 3.3  Correspondance entre l'achitecture UML et EJB - Cas 2

c) Cas général : assemblage de plusieurs composants


Dans le cas général présenté gure 3.4, le composant DEV est déni par l'assemblage de

plusieurs composants. Il implante plusieurs interfaces fournies et utilise plusieurs interfaces

requises. Nous utilisons une seule classe pour les exprimer en EJB.

Fig. 3.4  Correspondance entre l'achitecture UML et EJB - Cas 3

27
En d'autres termes, nous avons toujours une correspondance entre les diérents schémas

d'achitecture en termes de composants et EJB.

3.1.3 Diérents types d'adaptateurs en fonction des EJBs manipulés


Les solutions proposées sont fonction des hypothèses généraless communes et des para-

mètres.

a) Hypothèses
Les hypothèses générales pour tous les cas présentés par la suite, sont les suivantes :

1. Le composant A requiert une interface IA

2. Le composant B fournit une interface IB

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

adapteurs diérents en fonction des paramètres suivants :

 A est deployé côté client ou côté serveur


 A et B sont sur le même serveur
 IB est implanté localement (@Local ) ou à distance (@Remote )
Question Comment dénir ces adaptateurs ?

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

et IB est implanté localement, comme présentée gure 3.5(a).

L'interface IB Adapter (qui utilise B ) est déni


étant implantée localement, l'adaptateur

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

client, Adapter sur serveur), comme illustré gure 3.5(b).

Cas 2 Il correspond à l'hypothèse où le composant A est déployé côté client, le composant

B est déployé côté serveur et l'interface IB est implantée à distance par @Remote, comme

présenté gure 3.6(a).

Puisque IB est implanté par @Remote, l'adapteur Adapter n'est pas sur le même serveur

que B. Il y a deux solutions possibles :


 L'adaptateur Adapter est déployé sur un autre serveur Server 1 ; l'interface IA doit être

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

dénies en Java et non en EJB (gure 3.6(c)).

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

déployé côté serveur, c'est un Bean

28
(a) Hypothèse

(b) Solution

Fig. 3.5  Adaptateur - Cas 1

Cas 3 Les composants A et B sont déployés sur le même serveur et l'interface IB est

implantée localement(gure 3.7(a)).

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).

Comme dans le cas précédent, l'interface IB @Local, l'adaptateur Adap-


est implantée par

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

doit donc être déclarée @Remote (gure 3.8(b)).

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-

posant A. L'interface IA est implantée par @Local et A utilise Adapter localement

(gure 3.9(b)).

 L'adaptateur Adapteur est déployé sur un autre serveur et l'interface IA est declarée

@Remote (gure 3.9(c)).

29
(a) Hypothèse

(b) Solution 1

(c) Solution 2

Fig. 3.6  Adaptateur - Cas 2

30
(a) Hypothèse

(b) Solution

Fig. 3.7  Adaptateur - Cas 3

(a) Hypothèse

(b) Solution

Fig. 3.8  Adaptateur - Cas 4

31
(a) Hypothèse

(b) Solution 1

(c) Solution 2

Fig. 3.9  Adaptateur - Cas 5

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

d'accès à un ensemble de bâtiments [15]. Nous présentons un sous-ensemble de cette étude

de cas, illustré gure 3.10, correspondant à l'utilisation d'un composant existant, MultiLights,
pour réaliser le système.

Fig. 3.10  Étude de cas

Le composant Controller nécessite une interface requise RI_Lights. Le composant exis-


tantMultiLights que nous souhaitons utiliser fournit une interface PI_MLights. Pour que le

composant Controller puisse utiliser MultiLights, nous devons dénir un adaptateur.

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

l'interfaceRI_Lights, en d'autres termes, RI_Lights est considerée comme une interface du


composant Adapter. Dans ce contexte, le composant Controller utilise le composant Adapter
via son interface RI_Lights.

Fig. 3.11  Étude de cas exprimée dans EJB

La spécication est réalisé en EJB de la manière suivante :

Les interfaces RI_Lights et PI_Lights sont présentées dans la gure 3.12.

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 ;

public i n t e r f a c e R I _ L i g h t s { package component . m u l t i l i g h t s ;

public void o n _ g r e e n ( ) ; public i n t e r f a c e P I _ L i g h t s {


public void o f f _ g r e e n ( ) ; public void c h a n g e ( ML_Color n e w C o l o r ) ;
public boolean g e t L i g h t G ( ) ; public void on ( ) ;
public void s e t L i g h t G ( boolean var ) ;
public void o f f ( ) ;
public void on_red ( ) ; public ML_Color g e t C o l o r ( ) ;
public void o f f _ r e d ( ) ; public void s e t C o l o r ( ML_Color c o l o r ) ;
public boolean g e t L i g h t R ( ) ; }
public void s e t L i g h t R ( boolean var ) ;
}

Fig. 3.12  Code source des interfaces RI_Lights et PI_Lights

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 ;

public void on_green ( ) {


m L i g h t s . c h a n g e ( ML_Color . G r e e n ) ;
m L i g h t s . on ( ) ;
}
public void o f f _ g r e e n ( ) {
i f ( mLights . g e t C o l o r ( ) == ML_Color . G r e e n )
mLights . o f f ( ) ;
}
public void on_red ( ) {
m L i g h t s . c h a n g e ( ML_Color . Red ) ;
m L i g h t s . on ( ) ;
}
public void o f f _ r e d ( ) {
i f ( mLights . g e t C o l o r ( ) == ML_Color . Red )
mLights . o f f ( ) ;
}
}

Fig. 3.13  Code source de l'adaptateur AdapterBean

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

pas besoin d'utiliser des annotations de JML à ce niveau.

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 ) ;
} }

Fig. 3.14  Exemple des interfaces BankAccount et Account

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 ) ;
}
}

Fig. 3.15  Exemple des interfaces MoneyComparable et MoneyOps

Examinons la compatibilité de signatures entre les méthodes payInterest(double rate) des

interfaces BankAccount Account (voir gure 3.14).


et

Soit τq le type de la méthode payInterest(double rate) d'interface BankAccount, τl est celui

d'interface Account. τq et τl sont représentés par :

τ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 :

de l'interface BankAccount sont représentées par :

τq = (MoneyComparable) → void

Les deux méthodes : deposit(MoneyOps amt) et withdraw(MoneyOps amt) de l'interface

Account sont représentées de même manière :

τl = (MoneyOps) → void

Comme dans le cas précédent, MoneyComparable est une super-interface de MoneyOps


, nous pouvons donc remplacer MoneyOps par MoneyComparable dans τl . Donc, τq = V τl ,
correspondant à la compatibilité exacte.

3.3 Compatibilité au niveau comportements avec JML


Dans le chapitre 2, nous avons présenté les travaux d'A. M. Zaremski et J. M. Wing sur la

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

mêmes préconditions et postconditions pour chaque méthode. Soient deux interfaces :

 Interface requise IR avec un invariant IN V _R et une méthode methode_R


 Interface fournie IP avec un invariant IN V _P et une méthode methode_P

An d'utiliser la notion de compatibilité de comportements, nous modions la précondition

et la postcondition de chaque méthode de manière suivante :

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 :

/ /@ model import org . j m l s p e c s . models . ∗ ;


/ /@ model import org . j m l s p e c s . models . ∗ ;

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;
@∗ /
@∗ /

public void incR ( ) ;


public void incP ( ) ;
}
}

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

combinaison avec l'invariant, la précondition et la postcondition de la méthode incR sont

exprimées comme suit :

incRpre = (0 ≤ val && val < CAPACITY)


incRpost = (val == \old(val) + 1 && 0 ≤ val && val < CAPACITY)

Pour l'interface CounterP, il n'y a pas d'invariant, la précondition et la postcondition de

la méthode incP sont inchangées :

incPpre = (0 ≤ val && val < CAPACITY)


incPpost = (val == \old(val) + 1 && 0 ≤ val && val < CAPACITY)

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é/-

post exacte entre les deux méthodes incR et incP.

3.3.2 Méthode pure, méthode impure et clause assignable


Les attributs pur et impur sont exprimés dans le comportement de chaque méthode.

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

modiées à l'aide de la clause :

assignable liste des variables modiées ;


ainsi que les modications de ces variables. Cela veut dire que les attributs purs et impurs

sont déjà exprimés dans le comportement de sa méthode. La compatibilité entre ces deux

méthodes est donc vériée à l'aide de leur comportement.

/ /@ model import org . j m l s p e c s . models . ∗ ;

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 ;
/ ∗@
@∗ /

public / ∗@ pure @∗ / int @ assignable somme ;

addR ( int a, int b , int 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

que addP modie la variable globale somme.

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.

b) Visibilité des méthodes


Nous disposons de deux niveaux pour la visibilité des méthodes : celle de Java et celle de

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

qu'ils permettent d'appeler une méthode à partir d'un autre composant.

c) Visibilité des variables


Dans une interface, il n'existe pas de "vraies" variables, ce sont seulement des variables

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.

 Si la visibilité de la variable est protected ou public, lorsqu'une méthode d'interface

requise utilise une variable de l'interface fournie de ce type, ces deux types de visibilité

sont utilisables.

3.3.4 Comportements possibles dans une méthode


JML permet de décrire plusieurs comportements pour une méthode. Une question se pose

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 Méthode d'interface requise Méthode d'interface fournie


Cas 1 1 comportement 1 comportement

Cas 2 1 comportement n comportements

Cas 3 n comportements 1 comportement

Cas 4 m comportements n comportements

Cas 1 C'est le cas le plus simple, nous comparons la précondition et la postcondition cor-

respondante de la méthode de l'interface requise et celle de l'interface fournie en utilisant soit

la compatibilité pré/post soit la compatibilité de prédicats.

Cas 2 Utilisation de la compatibilité pré/post condition.

Soit l'exemple suivant :

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;
@∗ /

public i n t subR ( int a, int b);


@

@∗ /
ensures \result == b − a;

}
public i n t subP ( int a, int b);
}

Soit A le comportement de subR, le premier comportement de subP est B1, le deuxième


comportement de subP est B2. Pour que subR puisse utiliser subP, nous devons vérier que
(Apre ⇒ (B1pre ∨ B2pre )) ∧ ((B1post ∨ B2post ) ⇒ Apost )
Prenons un deuxième exemple :

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;
@∗ /

public i n t subR ( int a, int 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-

ée de la manière suivante :

39
((B1pre ⇒ B1post ) ∨ (B2pre ⇒ B2post )) ⇔ (Apre ⇒ Apost )

Cette formule prouve aussi que le deuxième exemple ne satisfait pas la compatibilité.

En général, la compatibilité entre deux méthodes, l'une avec un comportement et l'autre

avec n comportements, est dénie par :

W
(Bipre ⇒ Bipost ) ⇔ (⇒) (Apre ⇒ Apost )

Cas 3 Soit l'exemple suivant :

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);
}

Il correspond au cas inverse du cas précédent. Soit A1 le premier comportement de subR


et A2 le deuxième comportement de subR, B le comportement de subP. La compatiblité entre
ces deux méthodes est vériée par :

(Bpre ⇒ Bpost ) ⇔ ((A1pre ⇒ A1post ) ∨ (A2pre ⇒ A2post ))

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

au niveau de la spécication JML. Pour étudier la relation entre exceptions et compatibilité,

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 :

Cas Méthode d'interface requise Méthode d'interface fournie


Cas 1 sans exception sans exception

Cas 2 sans exception avec exception(s)

Cas 3 avec exception(s) sans exception

Cas 4 avec exception(s) avec exception(s)

Cas 1 La notion d'exception n'est pas utilisée ici.

40
Cas 2 Il existe une (plusieurs) exceptions(s) dans la spécication d'une méthode de l'inter-

face fournie.

Soit l'exemple suivant :

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

requires a > 0 && b > 0;

@ ensures \result == a+b ;


/ ∗@ public normal_behavior
@ also
@ requires a > 0 && b > 0;
@ public exceptional_behavior
@ ensures \result == a+b ;
@ requires a <= 0 || b <= 0;
@∗ /

public i n t addR ( int a, int b);


@

@∗ /
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.

Continuons avec un deuxième exemple :

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;
@∗ /

public i n t subR ( int a, int 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

 Lorsque subRpre = f alse, subR n'utilise pas subP

Examinons une forme générale à partir de deux exemples ci-dessus.

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

@ requires Ppre ;

/ ∗@ public normal_behavior @ ensures Ppost ;

@ requires Rpre ; @ also

@ ensures Rpost ; @ public exceptional_behavior

@∗ / @ requires PE ;

public void R(); @ signals_only E;

@∗ /

} public void P() throws E;

41
Il correspond à l'hypothèse où :

Rpre ⇔ (⇒) Ppre (1)


Ppost ⇔ (⇒) Rpost (2)
Ppre ∧ P E = φ (3)
Les conditions (1) et (2) assurent qu'il existe une compatibilité entre les deux méthodes

(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 :

if ((Rpre ⇒ Ppre )4 and (Rpre ))5 then {


P () ;
if (Ppost ⇒ Rpost ) then return result ;
}

La notion d'exception n'est donc pas concernée avec la compatibilité entre les deux mé-

thodes dans ce cas.

Cas 3 Pour étudier ce cas, nous prenons l'exemple suivant

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 Rpre ; public i n t e r f a c e IP {


@ ensures Rpost ; / ∗@ public normal_behavior

@ also @ requires Ppre ;

@ public exceptional_behavior @ ensures Ppost ;

@ requires RE ; @∗ /

@ signals_only E; public void P();


@∗ / }
public void R() throws E;
}

Comme dans le cas 2, supposons que nous ayons l'hypothèse :

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

 Si Rpre = f alse : si RE = true alors l'exception E est levée

Cela correspond à :

if (((Rpre ⇒ Ppre ) and (Rpre ))) then {


P () ;
if (Ppost ⇒ Rpost ) then return result ;
else if (RE ) then throws E ;
}

Cas 4 C'est le cas général où dans une méthode de l'interface requise et celle de l'interface

fournie, il existe des comportements normaux et des comportements exceptionnels.

À l'aide des deux cas précédents, la compatibilité entre deux méthodes est basée sur des

comportements normaux, pas de comportements exceptionnels, illustré par l'exemple suivant :

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

@ requires a > b; @ requires a >= b ;

@ ensures \result == a−b ; @ ensures \result == a−b ;

@ also @ also

@ public exceptional_behavior @ public exceptional_behavior

@ requires a <= b ; @ requires a < b;

@ signals_only NegativeException ; @ signals_only NegativeException ;

@∗ / @∗ /

public i n t subR ( i n t a , i n t b ) public i n t subP ( i n t a , i n t b )


throws N e g a t i v e E x c e p t i o n ; throws N e g a t i v e E x c e p t i o n ;
} }

Examinons les comportements normaux, nous avons :subRpre ⇒ subPpre ; subPpost ⇒


subRpost . Si subRpre = true alors subPpre = true, les comportements normaux sont eectués.
Par contre, si subRpre = f alse alors l'exception de subR est lancée si sa précondition est

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

@ requires Rpre ; @ requires Ppre ;

@ ensures Rpost ; @ ensures Ppost ;

@ also @ also

@ public exceptional_behavior @ public exceptional_behavior

@ requires RE ; @ requires PE ;

@ signals_only E1 ; @ signals_only E2 ;

@∗ / @∗ /

public void R() throws E1 ; public void P() throws E2 ;


} }

Supposons que nous ayons l'hypothèse que :

43
Rpre ⇔ (⇒) Ppre (1)
Ppost ⇔ (⇒) Rpost (2)
Rpre ∧ RE = φ (3) Ppre ∧ P E = φ (4)

La compatibilité entre les deux méthodes est exprimée de la manière suivante :

if (((Rpre ⇒ Ppre ) and (Rpre ))) then {


P () ;
if (Ppost ⇒ Rpost ) then return result ;
else if (RE ) then throws E1 ;
}

Le tableau suivant résume les quatre cas étudiés :

Cas Conditions Compatibilité


Cas 1
if (((Rpre ⇒ Ppre ) and (Rpre ))) then {
Rpre ⇔ (⇒) Ppre P () ;
Ppost ⇔ (⇒) Rpost if (Ppost ⇒ Rpost ) then return result ;
}

Cas 2

Rpre ⇔ (⇒) Ppre if (((Rpre ⇒ Ppre ) and (Rpre ))) then {


Ppost ⇔ (⇒) Rpost P () ;
Ppre ∧ P E = φ if (Ppost ⇒ Rpost ) then return result ;
}

Cas 3

Rpre ⇔ (⇒) Ppre if (((Rpre ⇒ Ppre ) and (Rpre ))) then {


Ppost ⇔ (⇒) Rpost P () ;
Rpre ∧ RE = φ if (Ppost ⇒ Rpost ) then return result ;
else if (RE ) then throws E ;
}

Cas 4

Rpre ⇔ (⇒) Ppre if (((Rpre ⇒ Ppre ) and (Rpre ))) then {


Ppost ⇔ (⇒) Rpost P () ;
Rpre ∧ RE = φ if (Ppost ⇒ Rpost ) then return result ;
Ppre ∧ P E = φ else if (RE ) then throws E1 ;
}

Tab. 3.2  Résumé la compatibilité entre deux méthodes avec exception(s)

En conclusion, la compatibilité entre deux méthodes dans lesquelles il existe une (plusieurs)

exception(s) est exprimée par :

44
 La compatibilité entre deux méthodes sans exception(s)

 La condition où il n'y a pas de mélange entre la précondition des comportements nor-

maux et celle des comportements exceptionnels

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

existants sont assemblés pour produire de nouveaux systèmes.

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

niveau spécication (UML/B) et au niveau programmation (pour les composants existants).

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

par l'équipe DEDALE au niveau spécication.

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

comportement est spécié en Java Modeling Language.


En conclusion, nous avons répondu aux questions de l'objectif de stage :

 Nous avons étudié la technologie basée composants existants EJBs

 Nous avons étudié comment les composants EJBs implantés interagissent et eectué

l'assemblage des composants EJBs avec un adaptateur.

 Nous avons cité la possibilité du passage vers les technologies existantes à base de com-

posants à partir l'expressivité du modèle de composants UML/B proposé dans l'équipe

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 :

4.2.1 Niveau programmation


Une poursuite des travaux consiste à dénir des adaptateurs en fonction du type de Session

Bean et d'autres types de composants comme des C# vers EJBs.

Il est aussi envisageable de formaliser le lien entre UML/B et EJB à l'aide des travaux

existants autour de la traduction automatique B vers Java [29, 25].

4.2.2 Niveau spécication


En se basant sur la compatibilité de méthodes, notre approche peut être améliorée par

l'étude de la compatibilité entre deux interfaces. Ce type de compatibilité devra prendre en

considération :

 Le nombre de méthodes dans l'interface requise et dans l'interface fournie

 Les variables de chaque interface

 Les invariants de chaque interface

 La compatibilité entre deux méthodes correspondantes de l'interface requise et de l'in-

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

interface requise et interface fournie correspond à l'adaptateur "nul", nommé Γ0 . À partir de

Γ0 , plusieurs cas possibles seront envisagés en ajoutant, par exemple :

1. Un type diérent pour une méthode donnée, Γ0 + un type

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).

Interface requise Interface fournie

n_1 <n_1pre , n_1post > n_1 <n_1pre , n_1post >


A n_2 <n_2pre , n_2post > B n_2 <n_2pre , n_2post >
n_3 <n_3pre , n_3post > n_4 <n_4pre , n_3post >

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

méthodes, il est nécessaire de dénir un adaptateur dans lequel il faut "augmenter" n _3


pour appeler n_4, exprimé par Γ0 + augmentation(n_3, n_4)

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

existantes entre ces deux interfaces.

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

project : Roissy VAL. In ZB 2005 : Formal Specication and Development in Z and B,


4th International Conference of B and Z Users, volume 3455 of LNCS, pages 334354.
Springer-Verlag, 2005.

[3] P. Behm, P. Benoit, and J. M. Meynadier. METEOR : A successful application of B

in a large project. In Integrated Formal Methods, IFM99, volume 1708 of LNCS, pages

369387. Springer Verlag, 1999.

[4] S. Chouali, M. Heisel, and J. Souquières. Proving component interoperability with B

renement. Electronic Notes in Theoretical Computer Science (ENTCS), 160 :157172,

2006.

[5] Clearsy. B4free, 2004. http://www.b4free.com.


[6] S. Colin, A. Lanoix, and J. Souquières. Trustworthy interface compliancy : data mo-

del adaptation. InFormal Foundations of Embedded Software and Component-Based


Software Architectures (FESCA), Satellite workshop of ETAPS, March 2007.
[7] EJB 3.0 Expert Group. EJB Core Contracts and Requirements, 2006.

[8] D. Hatebur, M. Heisel, and J. Souquières. A method for component-based software

and system development. InProceedings of the 32nd Euromicro Conference on Software


Engineering And Advanced Applications, pages 7280. IEEE Computer Society, 2006.
[9] Java Modeling Language (JML). http://www.cs.ucf.edu/~leavens/JML/.
[10] The Krakatoa Tool for Java Program Verication. http://krakatoa.lri.fr/
krakatoa0.html.
[11] A. Lanoix, S. Colin, and J. Souquières. Développement formel par composants : as-

semblage et vérication l'aide de b. Research report, LORIA, 2007. http://hal.


archives-ouvertes.fr/hal-00180972/en/.
[12] A. Lanoix, D. Hatebur, M. Heisel, and J. Souquières. Enhancing dependability of

component-based systems. In Springer Verlag, editor, Reliable Software Technologies


Ada-Europe 2007, number 4498 in LNCS, pages 4154. Springer Verlag, 2007.
[13] A. Lanoix and J. Souquières. A step-by-step process to build conform UML protocol

state machines. Research Report hal-00019314, LORIA, February 2006. http://hal.


archives-ouvertes.fr/hal-00019314.
[14] A. Lanoix and J. Souquières. A trustworthy assembly of components using the B re-

nement. e-Informatica Software Engineering Journal (ISEJ), 2(1), 2008. 19 pages,

published in advances of print.

49
[15] Arnaud Lanoix, Samuel Colin, and Jeanine Souquières. Développement formel par com-

posants : assemblage et vérication à l'aide de B. Technique et Science Informatiques


(TSI), 26(8), 2008. 27 pages, numéro spécial AFADL07, to appear.

[16] Gary T. Leavens, Albert L. Baker, and Clyde Ruby. JML : A notation for detailed design.

In Behavioral Specications of Businesses and Systems, pages 175188. Kluwer Academic


Publishers, 1999.

[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

Manual DRAFT, Revision : 1.231 Date : 2008/05/1320 : 54 : 59.


[18] Microsoft. Microsoft. Net. http://www.microsoft.com/net.
[19] I. Mouakher, A. Lanoix, and J. Souquières. Component adaptation : Specication and

Proc. of the 11th Int. Workshop on Component Oriented Programming


verication. In

(WCOP'06), satellite workshop of ECOOP, pages 2330, 2006.


[20] O. Simonin, A. Lanoix, S. Colin, A. Scheuer, and F. Charpillet. Generic Expression

in B of the Inuence/Reaction Model : Specifying and Verifying Situated Multi-Agent

Systems. INRIA Research Report 6304, INRIA, September 2007.

[21] Steria. Obligations de preuve : Manuel de référence, version 3.0. Steria  Technologies

de l'information, 1998.

[22] Sun Microsystems. Enterprise JavaBeans (EJB). http://java.sun.com/products/


ejb/.
[23] Sun Microsystems. JSR 220 : Enterprise JavaBeans, 2006. Version 3.0, Final Realase.

[24] C. Szyperski. Component Software. ACM Press, Addison-Wesley, 1999.

[25] B. Tatibouet, A. Requet, J.C. Voisinet, and A. Hammad. Java Card code generation

5th International Conference on Formal Engineering Methods


from B specications. In

(ICFEM'2003), volume 2885 of LNCS, pages 306318, Singapore, November 2003.


[26] The Object Management Group. Common Object Request Broker Architecture. http:
//www.omg.org/corba.
[27] The Object Management Group. Corba Component Model Specication, 2006. version

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

des langages à objets. Application à la génération de code Java/JavaCard. Livrable 5,

RNTL-BOM, October 2002. 38 pages.

[30] A. M. Zaremski and J. M. Wing. Signature matching : a tool for using software libraries.

ACM Transactions on Software Engineering and Methodology, 4(2) :146170, 1995.


[31] A. M. Zaremski and J. M. Wing. Specication matching of software components. ACM
Transaction on Software Engeniering Methodolology, 6(4) :333369, 1997.

50