Eclipse Europa
Karim
Djaafar
Eclipse Europa
CHEZ LE MME DITEUR Ouvrages sur Java et JEE A. Patricio. JPA et Hibernate. N12259, 2008, 390 pages. J. Dubois, J.-P. retaill, t. temPlier. Spring par la pratique. Mieux dvelopper ses applications Java/J2EE avec Spring, Hibernate, Struts, Ajax... N11710, 2006, 518 pages. a. Goncalves. Cahier du programmeur Java EE 5. EJB 3.0, JPA, JSP, JSF, Web Services, JMS, GlassFish, Ant. N12038, 2007, 340 pages. C. Delannoy. Programmer en Java. Java 5 et 6. N12232, 5e dition, 2007, 800 pages + CD-Rom. e. Puybaret. Cahier du programmeur Swing. N12019, 2007, 500 pages. e. Puybaret. Cahier du programmeur Java 1.4 et 5.0. N11916, 3e dition, 2006, 380 pages. J.-P. retaill. Refactoring des applications Java/J2EE. N11577, 2005, 390 pages. R. Pawlak, J.-P. retaill, L. seinturier. Programmation oriente aspect pour Java/J2EE. N11408, 2004, 462 pages. R. Fleury. Cahier du programmeur Java/XML. Mthodes et frameworks : Ant, Junit, Eclipse, Struts-Stxx, Cocoon, Axis, Xerces, Xalan, JDom, XIndice N11316, 2004, 228 pages. J. weaver, k. mukhar, J. crume. J2EE 1.4. N11484, 2004, 662 pages. Autres ouvrages sur le dveloppement Web C. Porteneuve Bien dvelopper pour le Web 2.0 Bonnes pratiques Ajax. N12028, 2007, 580 pages. r. Goetter. CSS 2 : pratique du design web. N11976, 2e dition, 2007, 350 pages. T. temPlier, a. GouGeon. JavaScript pour le Web 2.0. N12009, 2007, 492 pages. M. Plasse. Dveloppez en Ajax. N11965, 2006, 314 pages. D. thomas et al. Ruby on Rails. N12079, 2e dition, 2007, 750 pages. E. DasPet et C. Pierre de Geyer. PHP 5 avanc. N12167, 4e dition 2007, 792 pages.
Eclipse Europa
Karim Djaafar
Le code de la proprit intellectuelle du 1er juillet 1992 interdit en effet expressment la photocopie usage collectif sans autorisation des ayants droit. Or, cette pratique sest gnralise notamment dans les tablissements denseignement, provoquant une baisse brutale des achats de livres, au point que la possibilit mme pour les auteurs de crer des uvres nouvelles et de les faire diter correctement est aujourdhui menace. En application de la loi du 11 mars 1957, il est interdit de reproduire intgralement ou partiellement le prsent ouvrage, sur quelque support que ce soit, sans autorisation de lditeur ou du Centre Franais dExploitation du Droit de Copie, 20, rue des Grands-Augustins, 75006 Paris. Groupe Eyrolles, 2008, ISBN : 978-2-212-12061-5
Mise en page : TyPAO Dpt lgal : dcembre 2007 N dditeur : 7755 Imprim en France
Avant-Propos
Depuis la sortie de mon premier ouvrage sur Eclipse, il y a quatre ans, couvrant la version 2.0, la plate-forme a normment chang. Eclipse tait lpoque encore peu utilis par la communaut Java, qui recourait dans sa grande majorit des IDE tels que JBuilder ou NetBeans. Avec la release Europa, sortie dbut juillet 2007, Eclipse est devenu une plate-forme de rfrence pour des projets complexes. En ce sens, la fondation Eclipse a atteint son but, qui tait de fournir la communaut Open Source et aux dveloppeurs professionnels une plate-forme able btie autour dun ensemble de produits, doutils et de services. Laboutissement de ce long travail a t la mise au point du projet Web Tools, conu et support par les grands diteurs du moment : IBM, bien sr, avec sa suite IRAD (IBM Rational Application Developer), mais aussi BEA, avec sa suite WebLogic Workshop, et bien dautres. Dans le sillage de la sortie dEuropa sont venus se greffer plus dune vingtaine de sousprojets aussi ambitieux que ceux des releases prcdentes. Citons notamment loutil de reporting volu BIRT (Business Intelligence and Reporting Tool), le support du clbre langage interprt et objet Ruby, avec le projet Eclipse Dynamic Language Tool Kit, les fonctionnalits avances de collaboration en ligne, avec le sous-projet Mylyn, ou encore le mapping O/R, avec Dali. Cet ouvrage a pour principal objectif de montrer la maturit de tous ces projets et leur couverture du cycle de dveloppement complet dune application J2EE/JEE. Au cours de notre parcours, nous nous appuyons sur une dmarche centre sur le modle, ou MDA (Model Driven Architecture), et loutil EclipseUML de lditeur Omondo. Louvrage couvre galement en profondeur la spcication EJB 3.0 et en dtaille tous les avantages en comparaison de lancienne spcication EJB 2.x, en particulier grce lAPI JPA (Java Persistence API).
VI
JEE5
Organisation de louvrage
Louvrage est structur en trois grandes parties, plus une annexe. Partie 1 : La plate-forme de dveloppement Europa Le chapitre 1 dtaille les nouveauts de la plate-forme Europa. Le chapitre 2 introduit le projet Eclipse RCP et prsente les nombreux assistants proposs. Le chapitre 3 est consacr aux aspects lis la gestion de conguration et du dveloppement en quipe grce CVS et Subversion. Le chapitre 4 clt cette partie par une prsentation du proling de code avec le projet Eclipse Test and Performance Tools Platform (TPTP). Partie 2 : Dveloppement Web avec le projet Eclipse Web Tools Le chapitre 5 est consacr WTP (Web Tools Platform), un projet phare de la communaut Eclipse pour le dveloppement J2EE/JEE, et ses deux sous-projets : JST (J2EE Standard Tools) et WST (Web Standard Tools). Le chapitre 6 prsente loutillage du projet DTP (Data Tools Platfom), ax sur la manipulation des donnes. Le chapitre 7 introduit au dveloppement Web avec loutillage Web Tools et les patterns de conception. Le chapitre 8 clt cette partie par une prsentation dtaille du puissant framework Seam, la nouvelle plate-forme de dveloppement fonde sur les annotations. Partie 3 : Dveloppement EJB3 avec Eclipse et Web Tools Le chapitre 9 dcrit les principaux apports de la norme EJB 3.0 pour les projets JEE et dtaille les volutions de la notion de beans session ainsi que les annotions associes. Le chapitre 10 se penche sur lvolution des beans entit avec lAPI JPA et en montre toute la puissance pour la gestion de la persistance et du mapping objet-relationnel. Le chapitre 11 complte cette introduction lAPI de persistance avec le projet Dali, destine en faciliter la mise en uvre. Le chapitre 12 prsente latelier EclipseUML pour JEE, dont le but est de simplier le dveloppement JEE, et met en uvre la dmarche MDA au travers dune tude de cas. Le chapitre 13 conclut louvrage en revenant sur certaines fonctionnalits avances du framework Seam, notamment la gestion du contexte et la notion dintercepteurs permettant dintgrer harmonieusement des EJB 3.0 avec la technologie JSF. Partie 4 : Annexes
PARTIE I- LA PLATE-FORME DE
CHAPITRE 1
DVELOPPEMENT
EUROPA
Nouveauts dEuropa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Le projet Europa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fonctionnalits Europa dEclipse. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les sous-projets Europa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Le projet WTP (Web Tools Platform) . . . . . . . . . . . . . . . . . . . . . . . . . . . . TPTP (Test & Performance Tools Platform) . . . . . . . . . . . . . . . . . . . . . . . BIRT (Business Intelligence and Reporting Tools) . . . . . . . . . . . . . . . . . . DTP (Data Tools Platform) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . EMF (Eclipse Modeling Framework) . . . . . . . . . . . . . . . . . . . . . . . . . . . . GEF (Graphical Editor Framework). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . GMF (Graphical Modeling Framework) . . . . . . . . . . . . . . . . . . . . . . . . . . Visual Editor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . CDT (C/C++ Development Tools) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . En rsum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CHAPITRE 2
3 3 4 9 10 11 13 14 14 16 16 18 19 19
21 21 22 24
VIII
JEE5
Mise en uvre de RCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dveloppement dune application RCP . . . . . . . . . . . . . . . . . . . . . . . . . . . Classes principales dune application RCP . . . . . . . . . . . . . . . . . . . . . . . . Ajout de fonctionnalits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . En rsum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CHAPITRE 3 55
25 25 29 32 53
55 55 56 57 57 58 59 61 62 65 65 72 75 75 76 77 78 78 83 85 86
87 88 89 90 91
IX
94 98 100
En rsum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
103 104 104 105 106 107 109 111 111 112 113 114 115 117 118 123 124 125 125
JEE5
Cration dun prol de connexion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Script SQL de cration du schma de base de donnes . . . . . . . . . . . . . . . Gnration du DDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
En rsum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CHAPITRE 7
139 139 141 142 145 148 152 153 154 157 162 163 163
165 165 167 167 168 174 177 178 178 181 194
XI
197 197 197 199 202 202 203 209 211 212 213 215 215 216 222 224
225 225 227 228 228 234 235 235 241 242 243 243 245 246
XII
JEE5
246 246 247 249 249 250 251 252 252 254 255 258
En rsum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CHAPITRE 11
259 259 260 262 263 267 273 279 283 284 285 285 288 290
Intgration des entits du modle logique et mise en uvre dun bean client faade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Entits Client et Commande . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Le bean session CommandeManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
En rsum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CHAPITRE 12
XIII
293 295 295 295 305 306 308 328
EclipseUML for JEE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lapplication webstock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Environnement de travail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Modlisation avec EclipseUML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Export XMI du modle. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nouveau projet JEE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Gnration de code. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . En rsum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CHAPITRE 13
329 329 332 332 333 334 335 340 343 345 347
Annexe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Remerciements
crire un ouvrage nest jamais une entreprise solitaire, mais le fruit dun travail de partage dides, dexpriences et de patience. Je remercie lquipe dOmondo, en particulier Vlad Varnica pour ses encouragements et Amira Talbi pour sa contribution la partie touchant la modlisation EJB3 et lutilisation de loutil de modlisation EclipseUML. Je remercie aussi lquipe dEyrolles, en premier lieu ric Sulpice, qui a accept lide de ce livre, et Olivier Salvatori pour ses prcieux conseils et sa patience innie lors des diffrentes relectures. Enn, un grand merci mes proches, qui mont donn la force de conclure cette entreprise.
Partie I
1
Nouveauts dEuropa
La plate-forme Europa, nom de code dEclipse 3.3, reprsente une avance importante dans la maturit de la plate-forme Eclipse. Elle est constitue dune suite de sous-projets permettant dorganiser de manire cible et cohrente le dveloppement Java. Aprs un bref rappel des principales innovations de la plate-forme, nous prsenterons chacun des sous-projets qui la composent, dont un certain nombre nous serviront au dveloppement de ltude de cas faisant ofce de l conducteur louvrage.
Le projet Europa
Le projet Europa a t propos au public en juillet 2007. Disponible pour les principaux environnements dexploitation, comme Windows Vista ou Linux, cette nouvelle mouture dEclipse est la fois plus performante (elle fonctionne sous forme dexcutable et non plus laide dune JVM) et riche de nouveauts adressant les problmatiques de dveloppement suivantes : Dveloppement dapplications Java, de plug-in Eclipse et dapplications client riche fondes sur le cur du projet Eclipse initial, avec le JDT (Java Development Tools) et le PDE (Plug-In Development Environment). Dveloppement dapplications Web et J2EE, avec le sous-projet Web Tools (Web and J2EE Development). Dveloppement dapplications Web grce la cration de rapports avec BIRT (Business Intelligence and Reporting Tools). Dveloppement dapplications C/C++, avec le projet CDT pour Eclipse C/C++ Development Tooling (que nous ne traitons pas dans cet ouvrage). Dveloppement dapplications centres sur la gestion et laccs aux donnes quelles quelles soient (bases de donnes, connecteurs, etc.), avec DTP (Data Tools Platform). Dveloppement dapplications centres sur la modlisation, avec EMF (Eclipse Modelling Framework) et GEF (Graphical Editing Framework).
Proling et test dapplications Java, avec TPTP (Test & Performance Tools Platform). Gnration dIHM pour Eclipse de type RAD, bases sur une implmentation Swing/ JFC ou SWT avec le projet Eclipse Visual Editor (VE). Fourniture dune infrastructure de gnration fonde sur EMF et GEF, permettant de crer un diteur graphique avec le projet Eclipse Graphical Framework. Les fonctionnalits associes ces diffrents sous-projets sont illustres la gure 1.1.
Figure 1.1
Sous-projets dEuropa
Chaque sous-projet ncessite linstallation pralable des fonctionnalits associes. Par exemple, dans le cas du projet Web Tools, il est ncessaire dinstaller pralablement les fonctionnalits GEF et EMF (voir en annexe les procdures dinstallation).
Leffort important apport linterface graphique saute aux yeux des habitus dEclipse 3.2. Une nouvelle vue, lexplorateur de projets, permet de mieux organiser les projets en fonction de leur particularit.
Par exemple, les projets Java apparaissent sous la forme dune hirarchie de rpertoires source et de packages plutt que comme de simples rpertoires, tandis dans les projets de type Web apparaissent selon une arborescence respectant la spcication J2EE et maintenant JEE. La gure 1.2 illustre une vue de lexplorateurs de projets applique la gestion de ressources JEE.
Figure 1.2
Vue historique
Eclipse 3.2 apporte de puissantes fonctionnalits dhistorique, permettant de combiner les modications locales avec celles prsentes dans le rfrentiel projet. La gure 1.3 illustre cette possibilit. Il est possible de revenir la rvision dun source et de comparer la version courante avec la version historise.
Figure 1.3
Working Sets
Lorsque vous avez de nombreux projets dans un espace de travail, ou workspace, Eclipse, la vue Package Explorer devient vite surcharge. Il est dsormais possible de dnir ce quon appelle des Working Sets, ou jeux de documents, an de restreindre les ressources afches et de limiter ainsi le champ dexcution de certaines oprations, comme la recherche. Dans un projet multicouche, comportant des centaines de classes, il est de la sorte possible de nafcher un instant t quun sous-ensemble de chiers. Typiquement, lorsque vous travaillez sur un cas dutilisation, vous pouvez vouloir nafcher que sa DAO, ses services et son IHM. La gure 1.4 illustre un Working Set dni pour lafchage de ressources de type EJB.
Figure 1.4
Vue Filtres
La vue Filtres permet de regrouper les erreurs par type (incidents Java, incidents relatifs la conguration du projet, incidents de type PDE, etc.) et par gravit. La gure 1.5 illustre la conguration du ltre dafchage des erreurs.
Figure 1.5
Vue Filtres
Puissante et conviviale, la vue Cheat Sheet permet de garder ouverte une fentre daide en ligne pendant que vous tes en train de travailler avec un assistant Eclipse. La gure 1.6 illustre laide la cration dune premire application Java sous Eclipse.
Figure 1.6
Lors de limport dun projet existant, une case cocher vous permet de demander Eclipse de copier le rpertoire du projet import dans le rpertoire du workspace. La case nest pas coche par dfaut, car il nest pas obligatoire de stocker les projets dans le rpertoire du workspace.
Liens vers des ressources chier
Il est possible dutiliser un lien vers une ressource projet sans avoir copier cette ressource dans son workspace, an de ne pas surcharger ce dernier.
Lintgration des ux RSS
La section Dernires nouvelles de la fentre de bienvenue intgre des ux RSS (ncessitant une connexion Internet) permettant de proter au mieux des informations les plus rcentes en provenance de la fondation Eclipse.
Nettoyage de code
Loption Nettoyage (menus Source/Nettoyage) est une fonctionnalit puissante de productivit du code, qui permet de demander Eclipse de nettoyer le code en appliquant des rgles congurables via la bote de dialogue illustre la gure 1.8.
Figure 1.8
Vue Nettoyage
Restructuration de scripts
Europa renforce les fonctionnalits de refactoring de code dj trs avances de la version 3.1 dEclipse. Il est dsormais possible de crer des scripts avec un meilleur contrle et un historique des modications et de la rorganisation du code. La gure 1.9 illustre la vue Restructuration disponible dans Europa.
Vue Restructuration
Parmi ces sous-projets, dont plus dune vingtaine sont illustrs la gure 1.10, certains sont historiques la plate forme Eclipse, comme EMF, JDT et Equinoxe, et couvrent des domaines du dveloppement trs varis, en particulier les suivants : Business intelligence et reporting avanc avec le projet BIRT.
10
Frameworks favorisant lextensibilit de la plate-forme autour de SOA avec le projet SOA Tool Platform (http://www.eclipse.org/stp/) et de nombreux sous-projets associs. Fonctionnalits avances de collaboration en ligne fondes sur les tches avec le projet Mylyn (anciennement Mylar). Nouvel IDE pour le dveloppement avec le langage Ruby dans le projet DLTK (Dynamic Languages Toolkit). Projets de support au dveloppement JEE, comme WTP (Web Tools Platform) et Dali.
11
JSF Tools (JavaServer Faces Tools). Ce projet propose un outillage complmentaire pour le dveloppement dapplications utilisant les JavaServer Faces et une partie des spcications de la norme JEE5 (JSF 1.2). Lanc n 2005 par Oracle, ce projet apporte des assistants de conguration de projet pour le support des JSF et des tags JSF dans des pages JSP et lajout dditeurs spciques pour les chiers descripteurs facescong.xml permettant une dnition graphique de la cinmatique de navigation ( limage des diteurs dans le framework Struts). Ce sous-projet a t intgr en juin 2006 a la release Callisto et WTP 1.5, la version WTP 2.0 ayant t quand a elle bundle la release ofcielle Europa partir de juin 2007. Nous reviendrons en dtail sur ce projet important, abondamment mis contribution dans ltude de cas de louvrage. La gure 1.11 illustre la cible et les technologies sous-jacentes de ces diffrents sous projets.
Figure 1.11
En plus du projet JSF Tools, deux nouveaux sous-projets ont fait leur apparition courant 2006 : Dali JPA (Java Persistence API) Tools. Ce projet propose des outils facilitant le mapping objet-relationnel, la persistance et le dveloppement EJB3. Ce projet sera amplement discut et mis en uvre au chapitre 10. La version actuelle, Dali JPA Tools 1.0, intgre la release Europa propose des fonctionnalits intressantes pour la gnration du chier descripteur de persistance (persistence.xml), la conguration volue dun projet Java et laide aux annotations prvues par la spcication JPA. Dali propose en outre de puissants outils dORM, la possibilit de visualiser les champs persistants et les relations ainsi que le mapping de llment slectionn dans lditeur de code source. ATF (Ajax Toolkit Framework). Cr dbut 2006, ce projet rattach WST a pour objectif la livraison de frameworks et doutils de support aux diffrentes versions de runtime Ajax existantes. Comme nous le verrons tout au long de louvrage, ce projet trs dynamique risque fort de devenir loutil de rfrence des dveloppements J2EE/JEE 5.
12
Cest dans ce but que le projet TPTP a vu le jour en 2002, dabord sous le nom de Hyades avant de devenir en 2004 un des projets principaux de Callisto puis dEuropa. TPTP est organis en quatre sous-projets : TPTP Platform Project, qui forme lossature de la solution utilise par les diffrents outils de test et de mesure de performances. Il fournit les mcanismes permettant de collecter les mtriques et de les agrger. TPTP Tracing and Proling Tools Project, qui intgre les outils permettant la collecte des informations sur le fonctionnement dapplications Java sexcutant ou non sur un serveur J2EE compatible et lanalyse de ces informations (localisation des zones mmoire alloues, dtermination des temps dexcution, etc.). Ces outils sappuient sur une analyse dynamique de lapplication. Cette dernire est excute dans un mode particulier, appel Proling, qui permet la collecte dinformations sur les temps dexcution et loccupation mmoire. Pendant lexcution ou une fois celle-ci termine, plusieurs vues permettent danalyser les rsultats. TPTP Test Tools Project, qui propose des outils permettant la cration de scnarios de tests. Diffrents types de projets de test sont proposs, tels que les tests automatiss avec JUnit, les tests Web (capture et enregistrement des requtes HTTP) et les tests ncessitant lintervention de lutilisateur. TPTP Monitoring Tools Project, qui fournit des outils de collecte et dafchage des performances de lapplication ainsi que du systme. La page ofcielle du projet TPTP est disponible ladresse http://www.eclipse.org/tptp/. La version utilise au chapitre 4 de louvrage est la 4.2. La gure 1.12 illustre une vue des diffrentes mtriques disponibles dans loutil TPTP.
Figure 1.12
13
Figure 1.13
Vue des possibilits de loutil de reporting BIRT (total des chiffres de vente par trimestre et par produit)
14
15
EMF apporte les deux fonctionnalits principales suivantes : Dnition de modles objet et de diagrammes UML constitus de packages de classes et de liens entre ces classes. Ces modle peuvent tre labors partir de code Java annot, de documents XMI issus dautres modeleurs (par exemple, Omondo est en grande partie nativement intgr EMF), dun diteur arborescent intgr EMF ou par programmation. Transformation dun modle EMF en code Java et gnration dun diteur arborescent spcique pour construire des entits conformes ce modle. La structure des modles EMF est dnie par le mtamodle Ecore. Ce dernier est conceptuellement proche de MOF (MetaModel Facility), un standard de lOMG adressant la reprsentation des mtamodles et leur manipulation. Lune des caractristiques parmi les plus puissantes de ce projet est doffrir un cadre et un support la mtamodlisation, qui consiste spcier un mtamodle sous forme de modle EMF et en produire une implmentation Java an de reprsenter les instances de ce mtamodle et de les manipuler. Eclipse/Europa propose des assistants intgrs permettant la cration de modles EMF ainsi que la gnration du code associ au modle et, bien entendu, des diteurs adapts leur manipulation. La gure 1.15 illustre un aperu des outils intgrs de support la transformation de modles MOF Eclipse (appels eCore, qui est limplmentation Eclipse de la spcication MOF).
Figure 1.15
EMF est un projet trs important Callisto et dEuropa, qui mrite un examen attentif tant ses possibilits sont nombreuses et puissantes.
16
Pour plus de dtails sur ce projet, reportez-vous la documentation disponible sur le site du projet, ladresse http://www.eclipse.org/gef/.
17
assimil un environnement RAD pour la construction et le dveloppement dditeurs fonds sur EMF/GEF. Lutilisation du framework GEF est assez ardue. Elle ncessite une phase dapprentissage et de matrise de ses API relativement fastidieuse, en partie parce que GEF nest pas coupl au modle UML sous-jacent, ce qui peut engendrer un certain nombre de problmes. GMF est fond sur un framework pilot par les modles (MDA). La cinmatique dutilisation du framework et de ses principaux composants telle quillustre la gure 1.17 est propose lors de la cration dun projet GMF via lassistant de cration de nouveau projet dEclipse.
Figure 1.17
Comme vous pouvez le voir, le cur du framework GMF sappuie sur une dnition graphique du modle que lon souhaite gnrer. En option, il est possible dutiliser des outils et des lments de la palette graphique (menus, barre doutils, etc.). Une fois le mapping entre le modle slectionn et linformation graphique associe effectu, GMF fournit un gnrateur de modles (tape Create Generator Model). Ce dernier permet dimplmenter les dtails du modle permettant daboutir la gnration nale sous la forme dun plug-in directement utilisable dans Eclipse via les menus Fichier, Nouveau, Exemples et Model Diagram. La gure 1.18 illustre un exemple dditeur UML conu avec le framework GMF.
Figure 1.18
18
Prcisons que ce framework, tout comme les frameworks EMF/GEF, constitue un prrequis linstallation de Web Tools. Il est dailleurs disponible en version bundle sur le site dIBM alphaworks, ladresse http://www-128.ibm.com/developerworks/eclipse/downloads/.
Visual Editor
Visual Editor est un plug-in de type RAD pour le dveloppement dinterfaces SWING ou AWT sous Eclipse. Il sagit dun environnement complet, comportant une riche palette permettant le dveloppement assist dinterfaces graphiques volues. La gure 1.19 illustre une vue de latelier VE avec un aperu de la bote outils disponible.
Figure 1.19
Exemple dditeur UML conu avec le plug-in Visual Editor du framework GMF
Le plug-in Visual Editor permet de crer un nouveau type de Visual Class, ainsi que dutiliser une palette graphique. Visual Editor nest pas seulement utile pour modliser rapidement une interface. Il est aussi trs performant pour grer les vnements sur divers lments graphiques. La gure 1.20 illustre une liste dvnements supports par le composant de type bouton de latelierVisual Editor.
Figure 1.20
19
En rsum
Europa reprsente une tape importante dans lhistoire dEclipse et dans la fourniture doutils pour le support au dveloppement dapplications de type client riche, Internet riche et serveur.
2
Support du client riche avec Eclipse RCP
Le fort engouement pour les architectures Web 2.0 remet sur le devant de la scne la notion de client riche, que lon retrouve dans une profusion de solutions destines donner plus dinteractivit aux applications Web. Le framework Eclipse RCP (Rich Client Platform) se veut une solution de rechange crdible au bureau Windows. Vous mesurerez dans ce chapitre toute la richesse des outils fournis au dveloppeur pour simplier son travail. Aprs une prsentation des bases de la cration dune application RCP et une prise de contact avec les principales classes et interfaces associes, nous dtaillerons la cration de menus, barres doutils, vues, diteurs et botes de dialogue, ainsi que lutilisation des pages de prfrences. Nous terminerons le chapitre par le packaging du produit et lintgration des diffrents jar. Le terme workbench, ou Bureau Eclipse, sera utilis tout au long de ce chapitre.
22
et du DHTML ainsi que de portabilit entre navigateurs, de limitations imposes par ces derniers en termes dintgration avec les autres applications et de manque de performances des interfaces graphiques complexes. Applications riches fondes sur un socle applicatif installer sur le poste utilisateur. Eclipse RCP appartient cette catgorie, qui reprsente une volution des architectures client/serveur de premire et deuxime gnrations des annes 1990. Eclipse RCP apporte des solutions aux deux problmes principaux de ces architectures, qui sont la distribution de lapplication sur les postes utilisateur et leur forte dpendance vis--vis des technologies propritaires. Si ces applications natteignent pas la facilit de distribution du client lger, elles attnuent les problmatiques dinstallation initiale et de gestion des mises jours et offrent des avantages vidents en matire de ractiv, de qualit des interfaces graphiques, de souplesse (avec le mode dconnect) et dintgration pousse aux autres applications installes sur le poste. Pour satisfaire les applications daujourdhui, un client riche doit possder les mcanismes et caractristiques suivantes : interface graphique volue ; appel des services mtier sexcutant sur un serveur dapplications ; plate-forme indpendante du systme dexploitation hte ; framework de composants standards rutilisables ; mcanisme intgr et volu de mise jour des composants ; extensibilit. La gure 2.1 illustre un exemple darchitecture riche .
Figure 2.1
23
Comme lillustre la gure 2.2, Eclipse RCP est constitu des cinq composants principaux suivants : Environnement standard dexcution OSGI (Open Services Gateway Initiative). Runtime Eclipse, qui forme le socle de chargement et dexcution des services Eclipse. Workbench gnrique Eclipse (UI), qui constitue le composant de base de la plateforme. API de bas niveau SWT pour le support des objets graphiques. JFace, surcouche graphique fonde sur SWT, permettant de grer des composants graphiques complexes, tel le workbench gnrique (UI) constitu de lensemble des vues, diteurs et perspectives formant lossature dEclipse. Lutilisation dEclipse RCP pour le dveloppement dapplications riches offre les avantages suivants : Support natif du systme dexploitation hte. Permet de proter du look and feel de lenvironnement graphique utilis (Windows, MacOS, UNIX), puisque Eclipse RCP sappuie sur les composants de la bibliothque SWT, qui utilise de manire native les fonctionnalits du systme dexploitation. Concept de bureau mtier . Permet de sintgrer facilement aux applications bureautiques les plus courantes (Word, Excel, etc.) tout en combinant les dveloppements au sein dun seul bureau mtier . Le socle technique mutualise les services dauthentication et SSO ainsi que de communication avec les serveurs dapplications. Mise jour automatique des plug-ins. Permet une mise jour des plug-ins travers Internet par le biais du gestionnaire de mise jour. Dploiement multi-OS. Facilite le packaging et le dploiement des applications par simple glisser-dplacer des rpertoires de la distribution RCP dans les rpertoires de plug-ins concerns. Meilleures extensibilit et rutilisabilit. Le partitionnement des applications en plusieurs modules ou plug-ins encourage la cration de points dextension favorisant lextensibilit de lensemble ainsi que sa rutilisation pour dautres applications.
24
La gure 2.4 illustre la clbre suite Notes de lditeur IBM relooke et rebaptise IBM Lotus Symphony pour tirer partie des avantages de la pile RCP.
Figure 2.4
25
26
Prrequis
Vous pouvez tlcharger la version Eclipse for RCP/Plug-in Developers partir du site dEclipse (http://www.eclipse.org/downloads). Cest la version la plus complte pour le dveloppement dapplications fondes sur le framework RCP. Il ne faut pas utiliser les autres versions, comme Eclipse IDE for JEE, car elles ne comprennent pas lintgralit des bibliothques et outils pour le dveloppement dans cet environnement.
Cration du squelette de lapplication
Pour crer lapplication RCP, procdez de la faon suivante : 1. Lancez la cration dun nouveau projet de plug-in, via les menus File, New et Plug-in Development. 2. Dans la liste Plug-in Development de lassistant de cration de projet Eclipse, slectionnez Plug-in Project, puis cliquez sur Next. 3. Entrez le nom du projet, ici HelloRCP, en laissant les options par dfaut (option Create a Java Project coche avec les options de rpertoire source et de sortie src et bin respectifs ainsi que Version Eclipse 3.3). Cliquez sur Next. 4. Dans la page suivante, cochez yes pour loption Would you like to create a rich client application ? , et saisissez vos initiales pour le champ associ Plug-in Provider. 5. Laissez les autres options du plug-in coches par dfaut, et cliquez sur Next. 6. Vous obtenez diffrents templates sur lesquels vous pouvez vous appuyer pour crer lapplication (voir gure 2.5). Pour cet exemple, slectionnez RCP Hello, puis cliquez sur Next.
Figure 2.5
7. Lassistant vous rappelle un certain nombre dinformations sur le projet RCP que vous avez conu, dont le titre de la fentre de lapplication (Hello RCP), lID de lapplication (application), le nom du package (hellorcp), la classe de lapplication (Application). Cliquez sur Finish.
27
Figure 2.6
Noms de projets Il est dusage dans la communaut des dveloppeurs Eclipse de nommer les projets sous la forme despaces de noms, la manire des noms de packages Java. Puisque chaque plug-in est dvelopp dans un projet, cette convention pratique permet de faire correspondre le nom du projet avec les identiants des plug-ins quil contient.
28
Si vous excutez lapplication en cliquant sur loption Launch an Eclipse Application, aprs avoir bascul dans la perspective Resource et slectionn le projet HelloRCP, vous obtenez la fentre dpouille illustre la gure 2.8.
Figure 2.8
Examinons prsent les lments ncessaires la production de cette application. Le template RCP Hello a ajout les extensions org.eclipse.core.runtime.applications et org.eclipse.ui.perspectives, qui permettent de lier le plug-in linfrastructure Eclipse (que vous pouvez voir en cliquant sur longlet Extensions du plug-in illustr la gure 2.9), ainsi que les six classes Java suivantes : Activator Application ApplicationActionBarAdvisor ApplicationWorkbenchAdvisor ApplicationWorkbenchWindowAdvisor Perspective
Figure 2.9
29
30
/* * (non-Javadoc) * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop (org.osgi.framework.BundleContext) */ public void stop(BundleContext context) throws Exception { plugin = null; super.stop(context); } /** * Returns the shared instance * * @return the shared instance */ public static Activator getDefault() { return plugin; } /** * Returns an image descriptor for the image file at the given * plug-in relative path * * @param path the path * @return the image descriptor */ public static ImageDescriptor getImageDescriptor(String path) { return imageDescriptorFromPlugin(PLUGIN_ID, path); } }
La classe ApplicationActionBarAdvisor gre les diffrentes actions pour les barres de menus et dtat ainsi que les coolbars, variantes particulires de plusieurs contrles ToolBar :
public class ApplicationActionBarAdvisor extends ActionBarAdvisor { public ApplicationActionBarAdvisor(IActionBarConfigurer configurer) { super(configurer); } protected void makeActions(IWorkbenchWindow window) { } protected void fillMenuBar(IMenuManager menuBar) { } }
Les diffrentes mthodes de cette classe sont les suivantes : makeActions, qui permet de dnir des actions pour chaque menu et barre de menus. Une action est un simple objet qui possde un composant GUI. La liste des actions supportes par le Workbench Eclipse peut tre trouve en lisant la javadoc associe la classe abstraite ActionFactory, accessible sur le site de laide en ligne Eclipse (http://
help.eclipse.org/help32/index.jsp).
31
llMenuBar, qui permet de remplir la barre de menus avec nimporte quelle action que vous souhaitiez voir apparatre ici. llCoolBar, qui permet de remplir la coolbar. Une coolbar est une collection de toolbars, et une toolbar une collection dactions. llStatusLine, qui permet de remplir la barre dtat. La classe ApplicationWorkbenchAdvisor congure le Workbench et dnit la perspective par dfaut de lapplication afcher :
import org.eclipse.ui.application.IWorkbenchWindowConfigurer; public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor { private static final String PERSPECTIVE_ID = "HelloRCP.perspective"; public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor (IWorkbenchWindowConfigurer configurer) { return new ApplicationWorkbenchWindowAdvisor(configurer); } public String getInitialWindowPerspectiveId() { return PERSPECTIVE_ID; } }
Comme vous pouvez le voir dans lextrait de code prcdent, il faut obligatoirement dclarer une chane reprsentant lid de la perspective principale (celui dclar dans le fichier de conguration plug-in.xml et auquel il est fait rfrence par le biais de la variable PERSPECTIVE_ID) et rednir la mthode getInitialWindowPerspectiveId. La classe ApplicationWorkbenchWindowAdvisor permet de contrler le comportement de la fentre (taille, titre) et les composants qui sont prsents par dfaut (barre dtat, barres doutils) :
public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor { public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) { super(configurer); } public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer) { return new ApplicationActionBarAdvisor(configurer); } public void preWindowOpen() { IWorkbenchWindowConfigurer configurer = getWindowConfigurer(); configurer.setInitialSize(new Point(400, 300)); configurer.setShowCoolBar(false); configurer.setShowStatusLine(false); configurer.setTitle("Hello RCP"); } }
32
La classe Perspective reprsente un ensemble de vues, dditeurs et de menus de lapplication. Il est obligatoire de dnir au moins une perspective (ce sera la perspective par dfaut). Une perspective implmente linterface IPerspectiveFactory et la mthode createInitialLayout(), qui permet de dnir la position de chaque vue ou diteur :
public class Perspective implements IPerspectiveFactory { public void createInitialLayout(IPageLayout layout) { } }
Les diffrentes mthodes de cette classe sont les suivantes : createActionBarAdvisor(): cre un nouvel Action Bar Advisor pour congurer la barre dactions de la fentre via le congurateur de barre daction. preWindowOpen(): effectue diffrentes actions dinitialisation avant louverture de la fentre (taille de la fentre, titre, afchage ou non de la barre doutils, etc.).
Ajout de fonctionnalits
Vous allez tendre au fur et mesure les fonctionnalits de votre premire application RCP, en ajoutant du code spcique aux mthodes gnres par dfaut.
Ajout dune barre dtat
public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor { public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) { super(configurer); } public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer) { return new ApplicationActionBarAdvisor(configurer); } public void preWindowOpen() { IWorkbenchWindowConfigurer configurer = getWindowConfigurer(); configurer.setInitialSize(new Point(400, 300)); configurer.setShowStatusLine (true);
33
public void postWindowOpen() { IStatusLineManager statusline = getWindowConfigurer() getActionBarConfigurer().getStatusLineManager(); statusline.setMessage(null, "Test Status"); }
2. Relancez lapplication pour vrier la bonne prise en compte de ces modications (voir gure 2.10).
Figure 2.10
Continuez votre parcours initiatique avec lajout de menus votre application HelloRCP. Les menus et actions associes une application RCP peuvent tre ajouts par programmation ou par le biais de points dextension. Vous allez procder dans un premier temps par programmation en modiant la mthode makeActions() de la classe ApplicationActionBarAdvisor et en lajoutant aux mthodes fillMenuBar() et fillCoolbar(). 1. Ouvrez la classe ApplicationActionBarAdvisor, et apportez les modications suivantes :
import import import import import import import org.eclipse.jface.action.MenuManager; org.eclipse.jface.action.IMenuManager; org.eclipse.ui.IWorkbenchActionConstants; org.eclipse.ui.IWorkbenchWindow; org.eclipse.jface.action.Separator; org.eclipse.ui.application.ActionBarAdvisor; org.eclipse.ui.application.IActionBarConfigurer;
34
protected void makeActions(IWorkbenchWindow window) { iExitAction = ActionFactory.QUIT.create(window); register(iExitAction); iAboutAction = ActionFactory.ABOUT.create(window); register(iAboutAction); iNewWindowAction = ActionFactory.OPEN_NEW_WINDOW.create(window); register(iNewWindowAction); } protected void fillMenuBar(IMenuManager menuBar) { MenuManager fileMenu = new MenuManager("&Fichier", IWorkbenchActionConstants.M_FILE); MenuManager helpMenu = new MenuManager("&Aide", IWorkbenchActionConstants.M_HELP); menuBar.add(fileMenu); menuBar.add(helpMenu); // Ajoute le menu Fichier fileMenu.add(iNewWindowAction); fileMenu.add(new Separator()); fileMenu.add(iExitAction); iExitAction.setText("Quitter"); // Ajoute le menu Aide helpMenu.add(iAboutAction); }
Aprs la dnition des vues, vous devez remplir la barre de menus puisque vous lavez dnie comme visible dans la classe ApplicationWorkbenchWindowAdvisor. Pour cela, vous devez diter la classe ApplicationActionBarAdvisor. Cette classe est compose de diffrentes mthodes qui permettent de remplir les Action Bars et de dnir des actions excuter pour chacun des menus (Fichier et Aide en particulier) en utilisant les MenuManager de la bibliothque JFace qui permet de grer les menus. 2. Relancez nouveau lapplication, qui doit ressembler celle illustre la gure 2.11.
35
Vous allez ajouter une barre de boutons par le biais des mthodes fillCoolbar() et ApplicationActionBarAdvisor().
1. Pour ce faire, allez dans la classe ApplicationActionBarAdvisor, et ajoutez les actions correspondantes dans la mthode makeActions :
import org.eclipse.ui.actions.ActionFactory; import org.eclipse.swt.SWT; import import import import org.eclipse.jface.action.ICoolBarManager; org.eclipse.jface.action.IToolBarManager; org.eclipse.jface.action.ToolBarManager; org.eclipse.jface.action.ToolBarContributionItem;
protected void fillCoolBar(ICoolBarManager coolBar) { // Ajoute une nouvelle barre doutils a lapplication IToolBarManager toolbar = new ToolBarManager(SWT.FLAT | SWT.RIGHT); coolBar.add(new ToolBarContributionItem(toolbar, "main")); // Ajoute les entrees a la barre doutils toolbar.add(iSaveAction); toolbar.add(iExitAction); }
36
Dans cet extrait, Eclipse RCP fournit des actions standards, comme celles utilises dans la mthode makeActions (par exemple dans la ligne iNewWindowAction = ActionFactory.OPEN_NEW_WINDOW.create(window), qui cre une deuxime instance de lapplication en cours dans une nouvelle fentre lorsque lutilisateur clique sur ce menu. 2. Dans la classe ApplicationWorkbenchWindowAdvisor, modiez la mthode preWindowOpen() pour quelle afche une barre de boutons sous la barre de menus avec configurer.setShowCoolBar(true). Vous devez obtenir le rsultat illustr la gure 2.12.
Figure 2.12
3. Ajoutez les autres options du menu de manire que votre application ressemble la vue illustre la gure 2.13.
Figure 2.13
37
Cinq menus vont tre ajouts : Fichier (dj implment lors de ltape prcdente) Fentre ( implmenter) Aide (dj effectu ltape prcdente) Fentre/Ouvrir perspective ( implmenter) Fentre/Afcher vue ( implmenter) Ainsi que six actions : Fichier/Sortie (dj implmente ltape prcdente) Fentre/Ouvrir perspective/Autre ( implmenter) Fentre/Afcher vue/Autre ( implmenter) Fentre/Prfrences ( implmenter) Aide/Sommaire Aide ( implmenter) Aide/A Propos (dj implmente ltape prcdente) Il sagit dactions prdnies incluses par dfaut dans Eclipse mais que RCP fournit pour des raisons pratiques. Vous allez modier la classe ApplicationActionBar pour personnaliser la mthode llMenuBar, qui permet de personnaliser la barre de menus (vous pouvez en voir le dtail dans le code source tlchargeable sur la page Web ddie louvrage). 4. Enrichissez la classe ApplicationActionBarAdvisor visite prcdemment par le code suivant :
public class ApplicationActionBarAdvisor extends ActionBarAdvisor { private private private private private private IWorkbenchAction IWorkbenchAction IWorkbenchAction IWorkbenchAction IWorkbenchAction IWorkbenchAction iExitAction; iAboutAction; iNewWindowAction; iSaveAction; helpAction; preferencesAction;
private MenuManager perspectiveMenu = new MenuManager("&Ouvrir Perspective"); private MenuManager viewMenu = new MenuManager("Afficher Vue");
public ApplicationActionBarAdvisor(IActionBarConfigurer configurer) { super(configurer); } protected void makeActions(IWorkbenchWindow window) { iExitAction = ActionFactory.QUIT.create(window); register(iExitAction); iAboutAction = ActionFactory.ABOUT.create(window); register(iAboutAction);
38
protected void fillMenuBar(IMenuManager menuBar) { MenuManager fileMenu = new MenuManager("&Fichier" ,IWorkbenchActionConstants.M_FILE); MenuManager windowMenu = new MenuManager("&Fentre", IWorkbenchActionConstants.M_WINDOW); MenuManager helpMenu = new MenuManager("&Aide", IWorkbenchActionConstants.M_HELP); menuBar.add(fileMenu); menuBar.add(windowMenu); // Add a group marker indicating where action set menus will appear. menuBar.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); menuBar.add(helpMenu);
windowMenu.add(perspectiveMenu); windowMenu.add(viewMenu); windowMenu.add(new Separator()); windowMenu.add(preferencesAction); // Aide helpMenu.add(helpAction); helpMenu.add(new Separator()); helpMenu.add(iAboutAction); }
39
5. Ouvrez le chier plugin.xml si ce nest dj fait. 6. Slectionnez longlet Overview, et lancez nouveau lapplication RCP en cliquant sur Launch an Eclipse application. Les menus de votre application doivent ressembler ceux illustrs la gure 2.13. Il est possible ce stade dajouter quelques fonctionnalits. 7. Cliquez sur Fentre, Ouvrir perspective et Autre. La perspective cre par le template Hello RCP safche. 8. Cliquez sur Fentre, Afcher vue et Autre. Une vue vide safche, que vous remplirez un peu plus tard. 9. Cliquez sur Fentre et Prfrences. Vous devez voir safcher une bote de dialogue Prfrences vide. 10. Cliquez sur Aide et About. Une bote de dialogue safche ne comportant que trois boutons (Dtails des plug-in, Dtails de la conguration et OK). En cliquant sur Plug-in Details, vous voyez safcher votre plug-in dans la liste de ceux faisant partie de lapplication RCP (voir gure 2.14).
Figure 2.14
Copyright Vous pouvez remarquez que les informations de Copyright sont grises (Legal Info). Pour activer cette fonctionnalit, arrtez votre application, et copiez la racine du rpertoire du workspace contenant votre projet RCP les chiers about.ini et about.html fournis dans lexemple. Relancez ensuite votre application pour valider cette fonctionnalit.
ce stade, lapplication Hello RCP est encore rduite sa plus simple expression. Vous allez remplir la vue et complter loption Prfrences ainsi que la table des matires de laide : 1. Slectionnez File, New (ou Ctrl+N), puis Plug-in Project, et entrez comme nom de projet com.eclipsercp.HelloRCP.ui. Cliquez sur Next.
40
2. Choisissez lAssistant de plug-in personnalis an de crer une structure de rpertoire de plug-ins standard permettant de slectionner des lments supplmentaires dans une liste de modles. 3. Slectionnez no pour loption Would you like to create a rich client application , puis cliquez sur Next. 4. Slectionnez Custom plug-in wizard (voir gure 2.15).
Figure 2.15
5. Cliquez sur Next. 6. Choisissez Deselect All, puis slectionnez les options Hello World Action Set (jeu dactions), Help Table of Contents (table des matires daide), Preference Page et enn View (vue associe au plan de travail). Vous devez obtenir la vue illustre la gure 2.16. 7. Cliquez sur Finish ou sur Next si vous souhaitez personnaliser les diffrents templates choisis (texte associ la table des matires, nom des packages, message associ la bote de dialogue, nom de la vue et de la classe associe, type dafchage de la vue en tableau ou en tree view). Pour excuter lapplication, vous allez cette fois utiliser longlet Aperu, et non le lien Lancer une application Eclipse. Vous lancerez ensuite lapplication Hello RCP par le biais de loption Excuter de la barre doutils. 8. Slectionnez loption Run As, Open Run Dialog, puis, dans lassistant de cration, de gestion et dexcution des congurations qui souvre, slectionnez longlet Plug-in.
41
9. Cochez dans la liste le plug-in com.eclipsercp.HelloRCP.ui qui vient dtre cr et helloRCP, comme illustr la gure 2.17.
Figure 2.17
42
10. Cliquez sur Add required Plug-ins, et slectionnez les plug-ins suivants : org.apache.ant org.apache.lucene org.eclipse.help.appserver org.eclipse.help.base org.eclipse.help.ui org.eclipse.help.webapp org.eclipse.tomcat org.eclipse.ui.forms 11. Cliquez sur Run puis sur Excuter. Votre application doit prsent afcher le menu Sample Menu illustr la gure 2.18.
Figure 2.18
12. En cliquant sur Fentre, Afcher Vue puis Autre, vous devez voir safcher la vue plus riche illustre la gure 2.19, contenant une aide en ligne dynamique ainsi quune vue Exemple de vue.
Figure 2.19
43
13. En cliquant sur Exemple de vue, vous devez voir safcher sous forme de liste dicnes activables les options illustres la gure 2.20.
Figure 2.20
Comme lillustre la gure 2.21, le menu Prfrences sest enrichi dun exemple de prfrence, ajout automatiquement. La page daide a galement t ajoute au menu Prfrences du fait de lajout du plug-in daide lors de la conguration du plug-in personnalis.
Figure 2.21
Afchage des entres associes au menu et la barre doutils via les extensions
Vous allez prsent utiliser loutillage RCP pour afcher les points dextension provenant dditeurs tiers (vous en avez eu un aperu lorsque vous avez slectionn quelques plug-ins la section prcdente).
44
La dclaration dune extension se fait en XML. Chaque plug-in peut prvoir des points dextension sur lesquels dautres plug-ins viendront se brancher , comme lillustre la gure 2.22.
Figure 2.22
Points dextension
Un plug-in peut tendre ses propres points dextension (exemple actionSets), un point dextension tant dclar par un seul plug-in. La notion dextension est fondamentale pour la comprhension du framework RCP et plus gnralement du dveloppement de plug-ins sur cette plate forme. Vous pouvez approfondir ce sujet sur le portail ddi au projet RCP, ladresse http://www.eclipse.org/rcp. Pour avoir la liste des points dextension, ouvrez le chier plugin.xml, et slectionnez longlet Extensions. Vous pouvez voir la liste des points dextension dnis pour cette application, comme illustr la gure 2.23.
Figure 2.23
45
Vous pouvez ainsi voir le code gnr pour les actions associes la vue qui a t dnie, SampleView.java (notez le code associ la mthode makeActions qui permet la gestion des actions associes lIHM) :
public class SampleView extends ViewPart { private TableViewer viewer; private Action action1; private Action action2; private Action doubleClickAction; /* * The content provider class is responsible for * providing objects to the view. It can wrap * existing objects in adapters or simply return * objects as-is. These objects may be sensitive * to the current input of the view, or ignore * it and always show the same content * (like Task List, for example). */ class ViewContentProvider implements IStructuredContentProvider { public void inputChanged(Viewer v, Object oldInput, Object newInput) { } public void dispose() { } public Object[] getElements(Object parent) { return new String[] { "One", "Two", "Three" }; } } class ViewLabelProvider extends LabelProvider implements ITableLabelProvider { public String getColumnText(Object obj, int index) { return getText(obj); } public Image getColumnImage(Object obj, int index) { return getImage(obj); } public Image getImage(Object obj) { return PlatformUI.getWorkbench(). getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT); } } class NameSorter extends ViewerSorter { } /** * The constructor. */ public SampleView() { } /** * This is a callback that will allow us * to create the viewer and initialize it. */ public void createPartControl(Composite parent) { viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
46
viewer.setContentProvider(new ViewContentProvider()); viewer.setLabelProvider(new ViewLabelProvider()); viewer.setSorter(new NameSorter()); viewer.setInput(getViewSite()); makeActions(); hookContextMenu(); hookDoubleClickAction(); contributeToActionBars(); } private void hookContextMenu() { MenuManager menuMgr = new MenuManager("#PopupMenu"); menuMgr.setRemoveAllWhenShown(true); menuMgr.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager manager) { SampleView.this.fillContextMenu(manager); } }); Menu menu = menuMgr.createContextMenu(viewer.getControl()); viewer.getControl().setMenu(menu); getSite().registerContextMenu(menuMgr, viewer); } private void contributeToActionBars() { IActionBars bars = getViewSite().getActionBars(); fillLocalPullDown(bars.getMenuManager()); fillLocalToolBar(bars.getToolBarManager()); } private void fillLocalPullDown(IMenuManager manager) { manager.add(action1); manager.add(new Separator()); manager.add(action2); } private void fillContextMenu(IMenuManager manager) { manager.add(action1); manager.add(action2); // Other plug-ins can contribute there actions here manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); } private void fillLocalToolBar(IToolBarManager manager) { manager.add(action1); manager.add(action2); } private void makeActions() { action1 = new Action() { public void run() { showMessage("Action 1 executed"); } }; action1.setText("Action 1"); action1.setToolTipText("Action 1 tooltip"); action1.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages(). getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK));
47
action2 = new Action() { public void run() { showMessage("Action 2 executed"); } }; action2.setText("Action 2"); action2.setToolTipText("Action 2 tooltip"); action2.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages(). getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK)); doubleClickAction = new Action() { public void run() { ISelection selection = viewer.getSelection(); Object obj = ((IStructuredSelection)selection).getFirstElement(); showMessage("Double-click detected on "+obj.toString()); } }; } private void hookDoubleClickAction() { viewer.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { doubleClickAction.run(); } }); } private void showMessage(String message) { MessageDialog.openInformation( viewer.getControl().getShell(), "Exemple de Vue", message); } /** * Passing the focus request to the viewer's control. */ public void setFocus() { viewer.getControl().setFocus(); } }
Packaging
Il ne vous reste plus qu packager votre plug-in sous la forme dun module dployable et excutable en dehors dEclipse. Pour packager le plug-in, procdez de la faon suivante : 1. Faites un clic droit sur le projet helloRCP, puis slectionnez New et Product Conguration dans le menu contextuel. 2. Nommez lapplication par exemple HelloRCP.Product dans lassistant de conguration de produit Eclipse. 3. Activez la case Use a launch conguration. 4. Cliquez sur Finish.
48
Lditeur de dnition du produit apparat (onglet Aperu) comme illustr la gure 2.24.
Figure 2.24
5. Saisissez HelloRCP devant le champ Product Name. 6. Cliquez sur le bouton New devant le champ Product ID. Lassistant de dnition de nouveau produit apparat comme illustr la gure 2.25.
Figure 2.25
49
7. Slectionnez helloRCP dans le champ Dening Plug-in et productRCP dans le champs Product ID. Cliquez sur Finish. 8. Activez la case features, et basculez dans longlet Conguration (voir gure 2.26).
Figure 2.26
9. Cliquez sur New Feature pour intgrer les extensions qui ont permis de btir votre application (voir gure 2.27).
Figure 2.27
50
10. Entrez helloRCP-feature devant le champ nom de projet, et cliquez sur Next (voir gure 2.28).
Figure 2.28
11. Cochez com.eclipsercp.HelloRCP.ui et helloRCP comme liste des plug-ins initialiser, et cliquez sur Finish. 12. Basculez vers longlet Information illustr la gure 2.29.
Figure 2.29
51
13. Slectionnez longlet Licence Agreement, et entrez license.html devant le champ Optional URL. 14. Slectionnez Included Features, et cliquez sur Add. 15. Slectionnez les caractristiques org.eclipse.rcp et com.ibm.plte.help, et sauvegardez le tout (Ctrl+S). 16. Revenez la page HelloRCP.product, et slectionnez longlet Branding. 17. Spciez en option les images associes au produit packag devant les champs 16x16 Image ainsi que pour le champ About Dialog. 18. Saisissez devant le champ Test associ helloRCP, et sauvegardez le tout (Ctrl+S). 19. dans longlet Splash spciez helloRCP devant le champs Plug-in Splash Screen Le packaging du produit est termin. Vous pouvez le tester en allant sur la page HelloRCP_Product et en le lanant dans longlet Overview via loption Launch Product. Vous devez voir safcher la page illustre la gure 2.30.
Figure 2.30
Une fois lapplication RCP dveloppe, lobjectif est de lexcuter sans que lutilisateur se soucie du code Eclipse ni du runtime sous-jacent. Pour ce faire, vous pouvez opter pour des produits qui se chargeront de linstallation de votre application (exemple InstallShield), ou plus simplement vous appuyer sur larborescence gnre qui va contenir le programme lanceur startup.jar, cong.ini et tous les plug-ins et fonctions requis par le produit. Eclipse fournit pour ce faire un assistant dexportation de produit pour vous aider construire le rpertoire dinstallation de votre systme de chiers. Tous les projets Eclipse RCP contiennent un chier build.properties utilis par Eclipse pour dterminer quel chier et ressources il doit exporter. 1. Dans la page de construction du plug-in Hello RCP (Build Conguration), slectionnez les chiers ou rpertoires exporter avec le plug-in (voir gure 2.31) : about.html about.ini about.properties
52
Figure 2.31
2. Dans lditeur de page de construction du projet (feature.xml), slectionnez le chier license.html a exporter. 3. Ouvrez le chier plugin.xml, et exportez le plug-in avec lassistant dexport illustr la gure 2.32 en spciant un rpertoire de destination (les plug-ins seront placs dans le sous-rpertoire plugin du rpertoire choisi).
Figure 2.32
53
4. Dans longlet Options, spciez si le code source doit tre inclus en mme temps que les binaires (option Include source code) ou sous forme de Jar individuel pour chaque plug-in. Cliquez sur Finish. Vous avez achev la construction de la distribution de lapplication de dmo laide des outils de dploiement prvus avec loutillage RCP. Vous pourrez vous en servir comme base pour des applications riches plus labores.
En rsum
Cette prise de connaissance de latelier PDE dEclipse vous a permis, en partant dun exemple simple, dapprcier toute la richesse de lenvironnement de dveloppement de plug-in sur lequel est bti Eclipse. Vous avez mis en uvre les nombreux composants offerts par la plate-forme (botes de dialogue, barres doutils et de menus, etc.) pour crer des applications riches avec Eclipse RCP. Vous verrez au chapitre suivant un autre aspect du dveloppement avec Eclipse : le dveloppement coopratif laide de CVS et Subversion.
3
Support du dveloppement en quipe sous Eclipse avec CVS
Ce chapitre est ddi la mise en uvre de la solution logicielle de gestion des versions et de gestion collaborative des sources CVS. Aprs un rappel de la problmatique du dveloppement en quipe et des concepts associs (notion de rfrentiel de dveloppement et darchitecture SCMS), nous dtaillerons loutil Open Source CVS (Concurrent Versions System) et son intgration dans Eclipse. Comme nous le verrons, Eclipse propose une perspective CVS ddie, appele Exploration du rfrentiel CVS, qui permet de grer les changes et le contenu des projets stocks sous CVS de manire totalement intgre lIDE. Lune des fonctionnalits remarquables de lIDE Eclipse est sa capacit grer nativement les ressources des projets en quipe travers un rfrentiel partageable et des vues ddies. Eclipse supporte notamment la gestion de versions, qui permet au dveloppeur de comparer sa version locale avec celle stocke dans le rfrentiel de dveloppement et de remplacer ses ressources locales par une version plus rcente du projet sil le dsire. Nous introduirons en n de chapitre Subversion, parfois abrg SVN, qui apparat comme le digne successeur de CVS, dont il comble certains manques avrs qui nuisaient son dveloppement. Pour des raisons de clart, nous nous rfrons la version Eclipse Callisto en langue franaise. Ces concepts peuvent tre appliqus sans difcult particulire Eclipse Europa en version anglaise, puisque le support de la langue franaise nest pas disponible lheure ou nous mettons sous presse.
56
laquelle travaille le dveloppeur dune quipe. la diffrence de VisualAge for Java, cette structure sappuie sur le systme de chiers propre lOS cible, ainsi que sur les chiers journaux et les mtadonnes des plug-ins installs. Chaque fois quune ressource est modie dans le projet, elle est stocke dans le SF (systme de chiers) local. Il est en outre possible de stocker lespace de travail en partage sur le rseau. Ce mcanisme de gestion des sources partir du SF prsente les deux avantages suivants : Intgration facile avec les autres outils, puisque le travail seffectue directement avec le SF de la machine hte. Meilleure exibilit dans la gestion des sources et du processus de dveloppement.
Figure 3.1
57
Historique et chiers Les chiers peuvent possder un historique local, mais pas les dossiers ni les projets.
Eclipse vous permet de comparer et de remplacer votre code courant par une des versions gres localement. Pour voir lhistorique dun chier, il vous suft, partir du menu contextuel du chier, de slectionner Historique local puis Comparer . Vous pouvez slectionner dans la liste diffrents tats du chier et les comparer la version courante de ce dernier. Vous pouvez aussi remplacer nimporte quelle portion de cette version courante du chier par celle gurant dans lhistorique local (voir gure 3.1).
Historique local Lhistorique local est indpendant de lenvironnement de dveloppement dquipe et du rfrentiel partag.
Il est possible de modier les paramtres de conservation des chiers, exprims en jours, ainsi que la taille alloue lhistorique en slectionnant Prfrences, Plan de travail et Historique local.
58
La plate-forme Eclipse possde une architecture plugable, ouverte aux systmes de gestion de conguration tiers, ou SCMS, comme lillustre la gure 3.2.
Figure 3.2
Outils
Espace de travail
Gestionnaire de configuration
Rferentiel
Eclipse est livr avec un adaptateur standard pour le SCMS CVS (Concurrent Versions System). CVS est disponible sur un certain nombre de plates-formes, dont Windows, Linux, AIX, HP-UX et Solaris.
Comme nous lavons vu, larchitecture du modle de dveloppement dEclipse permet lutilisation dun rfrentiel plugable tiers au lieu dun rfrentiel propritaire. Priodiquement, les dveloppeurs effectuent leurs modications dans un espace partag, appel branche, du systme de gestion de conguration logicielle qui a t auparavant install et congur sur le serveur. Le processus de mise disposition de ressources aux autres membres de lquipe par le biais du rfrentiel est appel release. Cela quivaut une copie des chiers modis vers le rpertoire partag. Le terme team stream est souvent utilis dans la littrature consacre Eclipse pour dsigner lespace commun de travail de lquipe. Toutes les modications sont marques outgoing changes, ou modications sortantes, lorsque vous effectuez une synchronisation avec le rfrentiel. Le processus inverse, appel catch up, de rcupration des ressources partir du rfrentiel de dveloppement consiste copier les modications effectues par les autres membres de lquipe dans lespace de travail local.
Branche et HEAD Chaque rfrentiel possde au moins une branche, ou rpertoire partag principal du projet, appele par dfaut Head dans CVS.
59
Notion de version
Lorsquune ressource est versionne, une copie non modiable est dite released dans le rfrentiel. Il est alors possible, quoique non recommand, de versionner un chier ou un rpertoire. Le versionnement le plus courant dun projet est la sauvegarde de lintgralit des versions des ressources du projet. Il est possible de choisir le versionnement partir dun espace de travail personnel ou dune branche. Le plus recommand est le versionnement partir de lespace de travail personnel, car le dveloppeur est cens connatre ltat des versions des ressources projet qui doivent tre rendues released dans la version nale.
Il peut arriver quun mme projet apparaisse dans diffrentes branches, une branche reprsentant ltat en cours du projet, et les ressources voluant indpendamment les unes des autres. Cela na rien danormal pour un projet qui possde, par exemple, deux tats, un tat de maintenance corrective et un projet intgrant de nouvelles fonctionnalits.
Les modications valides dans la branche nont aucun effet sur les autres branches jusqu lopration de fusion (merge) des modications partir de cette branche dans une autre branche ou dans le head.
Notion de rles
Contrairement dautres rfrentiels de dveloppement propritaires, lespace de travail Eclipse ne possde aucune notion de droit sur les ressources du projet. Les droits en criture sont simplement contrls par les permissions dcriture sur les rpertoires contenant la ressource. Nimporte quel membre de lquipe de dveloppement ayant les droits daccs sur une ressource peut la modier, voire la supprimer. Chaque utilisateur du systme de gestion de conguration logicielle possde un compte sur le serveur o le rfrentiel dquipe a t cr et congur par ladministrateur du systme de conguration logicielle en charge des dveloppements. Il y accde par le biais dun client CVS intgr Eclipse. Ce systme de conguration logicielle install sur le serveur permet de grer et dadministrer les comptes CVS client travers un rfrentiel dquipe, soit ici CVSNT, un gestionnaire de version serveur Open Source compatible avec la fois simple et able dutilisation.
60
La gure 3.3 illustre un modle de dveloppement squentiel : 1. Le dveloppeur 1 cre un chier, FIC1, puis valide ses modications courantes dans la branche de dveloppement. 2. Le dveloppeur 2 rcupre la nouvelle version du chier FIC1 dans son espace de travail partir de la branche de dveloppement du projet. 3. Il modie son tour le chier et valide ses modications dans la branche. 4. Le dveloppeur 1 rcupre les modications effectues par le dveloppeur 2 sur le chier FIC1 et les valide dans la branche. Le cycle continue jusqu ce que le chier FIC1 soit nalis. Ce scnario favorise labsence de conits dans la gestion commune des ressources.
Etat initial Modification #2
Dveloppeur 1
Dveloppeur 2
Modification #1
Figure 3.3
Le scnario de dveloppement parallle sur une seule branche (single stream) est plus courant que le prcdent. Il repose sur le fait que plus dun dveloppeur travaille gnralement en mme temps sur un mme chier dans une mme branche du dveloppement. La gure 3.4 illustre ce scnario, moins optimiste que le prcdent. 1. Les dveloppeurs 1 et 2 rcuprent la version 1.3 du chier partir de la branche commune de dveloppement. 2. Le dveloppeur 1 modie le chier et le met disposition dans la branche. 3. Le dveloppeur 2, qui travaille galement sur le mme chier, est prt le mettre disposition dans lespace partag mais doit dabord fusionner (merge) ses modications avec celles du dveloppeur 1 avant de valider ses changements. CVS permet de dtecter automatiquement les conits ventuels en comparant les chiers et en effectuant une fusion des modications.
61
Modification#3
Dveloppeur 1
v1.3 Branche (stream) Merge v1.4 et release de la v1.5 Mise jour du stream Release v1.4
v1.3
Dveloppeur 2
Modification#4
Figure 3.4
Le scnario de dveloppement parallle sur plusieurs branches (multiple stream) est un cas particulier. Il survient dans un type de scnario o, par exemple, un dveloppement consiste en la maintenance dune application simultanment au dveloppement de nouvelles fonctionnalits. Dans ce cas, il faut crer une nouvelle branche dans le processus de dveloppement courant, branche qui va permettre la fusion des dveloppements issus du projet de maintenance effectu par un des dveloppeurs de lquipe et du projet dvolution des fonctions la charge dun autre membre de lquipe.
62
Chaque rvision est reprsente par un nombre qui sincrmente. La rvision initiale dun repository cr est zro. Il est ainsi possible de comparer les chiers et de les remplacer par une des rvisions disponibles chaque moment. La rvision la plus rcente dans le rfrentiel est dsigne par head.
3. Veillez possder les privilges administrateur adquats et ce que votre systme de chiers soit de type NTFS. Cest trs important pour la suite de linstallation.
63
4. Le chemin de linstallation CVSNT et de la commande cvs.exe est normalement ajout la variable path de votre serveur. Si ce nest pas le cas, ajoutez-les la variable path partir du Panneau de conguration Windows (c:\programs\cvsnt).
Clients Windows NT-2000-95/98 Si vous souhaitez utiliser un client NT ou Windows 2000, il est prfrable dutiliser le chier cvs.exe fourni avec la distribution de CVSNT, cette version supportant lensemble des fonctionnalits de la version serveur. Les clients Windows 95/98 doivent utiliser le chier cvs95.exe fourni aprs installation de CVSNT.
5. Aprs installation de CVSNT sur votre serveur, slectionnez Dmarrer, Programmes, CVS for NT et Service Control Panel. Vous devez obtenir la bote de dialogue illustre la gure 3.6, permettant de congurer le rfrentiel de dveloppement de lquipe.
Figure 3.6
6. Crez un rpertoire CVS sur votre disque, par exemple c:\CvsMaster, et attribuez des droits offrant un contrle total aux comptes utilisateur, y compris le compte SYSTEM. 7. Dans longlet Repositories, spciez le chemin daccs complet votre rfrentiel de dveloppement. 8. Utilisez le bouton Add pour ajouter un nouveau rfrentiel, ici Test, en prenant soin au pralable de congurer le prxe du rfrentiel, comme illustr la gure 3.7.
Figure 3.7
64
Emplacements des rfrentiels Lorsque vous utilisez des prxes de rfrentiels sans tre obligatoire, cela savre bien pratique si vous disposez de plusieurs rfrentiels , ces derniers doivent tre localiss sous le mme rpertoire racine (prxe). Sur CVSNT, il nexiste quun seul prxe de rfrentiel. Nous avons not sur la version de CVSNT en notre possession des difcults daccs au rfrentiel CVS partir dEclipse avec cette option. Il est donc conseill de ne pas y recourir et dutiliser uniquement loption Valid Repository Root ou de vous rendre sur le site de lauteur du produit (bo.berglund@telia.com) pour plus dinformation.
9. Dans longlet Advanced, prcisez les protocoles supports : Server side support for ntserver protocol . Support du protocole ntserver initialement utilis par CVS et remplac prsent par le protocole sspi, beaucoup plus scuris, supportant le cryptage et fonctionnant au-dessus de TCP/IP. Impersonation enabled . Cette option permet CVSNT dagir au nom de lutilisateur qui effectue la commande, notamment dans les permissions associes aux chiers du systme. Use local users instead of domain . Utilisez cette option si vous ne possdez pas de domaine NT rserv pour lauthentication des utilisateurs. Ces derniers doivent possder un compte, ou alias (voir plus loin), valide sur lhte hbergeant CVSNT. 10. Prcisez dans cette tape le rpertoire temporaire CVS, ici C:\CvsTemp, et attribuez tous les privilges daccs, y compris pour le compte SYSTEM, comme illustr la gure 3.8.
Figure 3.8
11. Cliquez sur OK pour que les modications prennent effet. 12. Redmarrez CVSNT (onglet Service Status) pour prendre en compte les modications.
65
Une fois le test de connexion russi, vous pouvez ajouter ou supprimer des comptes CVS partir du compte karim ou de tout compte possdant des privilges dadministrateur quivalents. CVS naccepte pas dutilisateur non connect un compte rel existant. Vous pouvez contourner cette contrainte en utilisant un alias vers un compte rel NT existant en utilisant la commande passwd. En voici la syntaxe complte :
cvs passwd [-a] [-x] [-X] [-r compte NT existant] [-R] [-D domaine] <compte cvs>
Les options de cette commande sont les suivantes : -a : ajoute un utilisateur au systme. -x : dsactive lutilisateur du systme. -X : supprime lutilisateur du systme. -r : nom dalias dun utilisateur rel. -R : supprime lalias dun utilisateur rel. -D : utilise un mot de passe du domaine. La commande suivante ajoute lidentiant CVS christophe, qui est en fait un alias systme obtenu partir du compte NT rel philippe :
cvs passwd -r philippe -a christophe
Lajout dutilisateurs CVS est requis seulement si vous envisagez dutiliser le protocole pserver, qui est le protocole par dfaut utilis par CVS et par Eclipse (voir plus loin). Pour des raisons videntes de scurit, nous recommandons dutiliser le protocole SSPI surtout si vous accdez votre rfrentiel via Internet , qui peut facilement traverser les pare-feu installs, contrairement au protocole de connexion pserver.
66
Pour congurer le rfrentiel sous Eclipse, il vous suft dutiliser lexplorateur de rfrentiel (Perspective CVS Repositories) et dajouter un rfrentiel CVS partir de la bote de dialogue illustre la gure 3.9.
Figure 3.9
Les paramtres suivants de conguration de la connexion au rfrentiel CVS sont obligatoires : Hte. Nom du serveur hte. Chemin du rfrentiel. Chemin daccs au rfrentiel partag. Utilisateur. Nom de lutilisateur accdant la ressource prcdemment congure sur le serveur. Mot de passe. Mot de passe associ lutilisateur. Type de connexion. Ce paramtre permet de slectionner le protocole dauthentication du serveur. Trois protocoles sont supports par le client CVS livr dans Eclipse : pserver. Connexion spcique de CVS, recommande pour lutilisation courante de CVS avec peu de problmatique de scurit. extssh. Client SSH 1.0 inclus dans Eclipse. ext. Mthode de connexion utilisant un outil externe, tel que SSH, pour se connecter au rfrentiel. Loutil utilis par ext est congur dans la page de prfrences, via Equipe, CVS et Mthode de connexion externe. Port. Port par dfaut ou spcique si lhte par dfaut en utilise un. Si votre conguration a t correctement valide, la perspective Rfrentiels CVS doit afcher la liste des rfrentiels prcdemment congurs et installs sur le serveur, comme illustr la gure 3.10.
67
Remarquez que la branche head gure par dfaut dans lexplorateur de rfrentiels. Votre rfrentiel est maintenant accessible partir dEclipse, et vous pouvez rcuprer les ressources dun projet Eclipse dans votre espace de travail ou enregistrer une version de votre travail dans le rfrentiel.
Synchronisation du projet
Vous allez crer un projet CvsTest de type Java contenant une seule ressource, une classe Java HelloEclipse, contenue dans un package com.eclipse.test, par exemple. Vous mettrez ce projet la disposition des autres membres de lquipe. 1. Dans la vue Navigateur associe la perspective Java, slectionnez le projet CvsTest. 2. Dans le menu contextuel du projet, slectionnez Equipe puis Partager le projet, comme illustr la gure 3.11.
Figure 3.11
68
3. Dans la page de lassistant de partage de projet, slectionnez lemplacement cr prcdemment, comme illustr la gure 3.12.
Figure 3.12
4. Choisissez le nom du projet local comme nom de projet distant, ou entrez un autre nom. 5. Cliquez sur Fin pour partager le projet avec le rfrentiel. Le projet safche dans la vue Synchronisation avec lensemble des commandes CVS usuelles (voir gure 3.13).
Figure 3.13
69
La vue Synchronisation Si le projet existe dj distance, la vue Synchronisation afche les conits de chiers en local et distance.
Le message qui apparat dans la barre de messages, au bas de lcran, signale labsence de conit, puisque le projet vient dtre partag. Dans le volet Comparaison de la structure, des icnes vous permettent dafcher toutes les ressources valider dans le rfrentiel. Vous pouvez modier ces icnes au moyen dobjets dcorateurs, qui permettent aux membres de lquipe de distinguer les ressources congures pour leur rfrentiel.
Dcorateurs Le client CVS utilise des dcorateurs pour afcher indicateurs de modication, balises, mots-cls et rvisions. Les dcorateurs sont utiles pour ajouter des fonctionnalits des types de ressources existants. De nombreuses vues standards de lespace de travail afchent les dcorateurs.
Les dcorateurs peuvent tre contrls par lutilisateur par le biais de la bote de dialogue Label Decorations, accessible via Prfrences, Team puis CVS, comme illustr la gure 3.14.
Figure 3.14
Synchronisation du rfrentiel
Le dveloppeur Eclipse ayant son projet afch dans le plan de travail Eclipse doit pouvoir se synchroniser avec son rfrentiel de dveloppement ( Synchroniser avec le rfrentiel ), mettre jour ses chiers ( Mettre jour ) et les rendre accessibles aux
70
autres membres de lquipe (voir gure 3.14) ou versionner son projet ( Baliser an tant que version ).
Mise jour Il est toujours prfrable de mettre jour les ressources avant de les valider, an de rsoudre les ventuels conits entre les ressources de lespace de travail et celles de la branche.
Vous pouvez dnir des ltres pour : Visualiser uniquement les modications entrantes. Les modications entrantes proviennent de la branche. Si elles sont acceptes, elles remplacent la version de la ressource de lespace de travail par la dernire version valide dans la branche. Visualiser uniquement les modications sortantes. Les modications sortantes proviennent de lespace de travail. Si elles sont valides, elles modient les ressources de la branche de sorte que celles-ci correspondent celles de lespace de travail. Visualiser les modications entrantes et sortantes. Dans cet exemple, sagissant dun nouveau projet, choisissez les modications sortantes : 1. Faites un clic droit pour ouvrir le menu en incrustation, puis slectionnez Equipe et Synchroniser avec le rfrentiel. 2. partir du menu contextuel illustr la gure 3.15, slectionnez Ajouter au contrle de version. Cette option indique CVS de crer une entre dans le rfrentiel de manire commencer grer lhistorique de ce chier avant sa validation dans le rfrentiel.
Figure 3.15
Vous pouvez suivre le rsultat des commandes CVS dans la console CVS ddie (voir gure 3.16).
Figure 3.16
Console CVS
71
3. Slectionnez loption Valider pour valider dans le rfrentiel les modications sortantes et les rendre visibles aux autres membres de lquipe. Vous pouvez saisir un commentaire si vous le souhaitez. 4. Revenez dans la perspective Rfrentiels CVS, et faites un clic droit pour ouvrir le menu contextuel Rgnrer la vue. Votre projet ainsi que toutes ses ressources gurent maintenant dans le rfrentiel C:\CvsMaster, comme illustr la gure 3.17. Notez le numro de rvision initiale, 1.1.
Figure 3.17
Validation Valider les modications dun projet ou des ressources associes quivaut les copier depuis votre espace de travail vers la branche du rfrentiel. chaque validation dune ressource, un nouveau tag de rvision est associ (1.1 pour le tag de rvision initial, 1.2 pour la prochaine validation, et ainsi de suite).
Une fois votre projet intgr dans le rfrentiel et ce dernier disponible pour les autres membres de votre quipe, des conits sur les ressources peuvent survenir. Ces conits peuvent tre rsolus de manire automatise ou manuelle. Un conit se produit lorsque vous modiez en local une ressource pour laquelle une rvision plus rcente est disponible dans la branche du rfrentiel. Dans un tel cas, vous pouvez effectuer lune des oprations suivantes : Rcuprer la modication de la branche et supprimer le travail effectu en local. Vous choisirez cette solution si vous avez effectu en local des modications involontaires ou si vous dcouvrez que la rvision du rfrentiel est meilleure que la vtre. Soyez prudent lorsque vous crasez vos modications locales, puisque cela dtruit le travail accompli.
72
Valider votre modication en restituant la rvision dans le rfrentiel. Neffectuez cette opration quavec une extrme prudence car elle se traduit par lcrasement du travail dautrui. De plus, il est possible que le travail cras ait des dpendances dans la branche. Fusionner votre travail avec la ressource du rfrentiel, en sauvegardant en local la ressource fusionne. Vous pouvez valider le rsultat de la fusion ultrieurement. La plupart du temps, vous effectuerez une fusion, puisque les deux autres choix entranent des pertes de travail.
Mode de rsolution des conits avec CVS
Lorsque vous travaillez sur un projet dans lespace de travail, il se peut que dautres membres de votre quipe valident des modications dans la copie du projet situe dans le rfrentiel. Pour obtenir ces modications, vous pouvez mettre jour lespace de travail de sorte quil corresponde ltat de la branche. Il convient dans tous les cas de procder une mise jour systmatique avant toute validation, de sorte vous assurer que ltat le plus rcent du rfrentiel est disponible. La commande de mise jour peut alors tre mise de lune des deux faons suivantes : en choisissant Equipe puis Mettre jour partir du menu contextuel ; en passant par la vue Synchronisation. Laction de ces deux commandes CVS tant diffrente, il est important de connatre les trois types de modications entrantes qui peuvent survenir sur un projet CVS : Modication non conictuelle. Se produit lorsquun chier est modi distance mais pas en local. Modication conictuelle pouvant tre fusionne automatiquement. Se produit lorsquun chier ASCII est modi distance et en local. Le chier comporte en ce cas des modications locales non valides. Modication conictuelle ne pouvant tre fusionne automatiquement. Se produit lorsquune ou plusieurs lignes dun chier binaire est modie distance et en local (les chiers binaires ne peuvent jamais tre fusionns automatiquement).
73
La vue Synchronisation fournit un emplacement unique dans lequel vous pouvez visualiser les modications que vous avez apportes et celles apportes et valides par dautres personnes dans le rfrentiel. Pour ouvrir la vue Synchronisation en mode entrant, procdez de la faon suivante : 1. Dans la vue Navigator, slectionnez les ressources mettre jour. 2. Dans le menu des ressources slectionnes, choisissez Equipe puis Synchroniser avec le rfrentiel. La vue Synchronisation safche. 3. Dans la barre doutils de la vue Synchronisation, cliquez sur le bouton du mode entrant pour carter toutes les ressources modies (modications sortantes) de lespace de travail dont vous disposez. En mode entrant, les modications qui ont t valides dans la branche depuis la dernire mise jour safchent. Cette vue indique le type de chaque modication entrante (non conictuelle, conictuelle pouvant tre fusionne automatiquement ou conictuelle ne pouvant tre fusionne automatiquement). 4. Pour valider les chiers qui sont en conit, slectionnez Remplacer et valider. La copie de lespace de travail de la ressource est fusionne avec le rfrentiel, et toutes les modications entrantes sont supprimes.
Validation Le contenu du rfrentiel nest pas modi lors de la mise jour. Lorsque vous acceptez les modications entrantes, ces dernires sont intgres votre espace de travail. Le rfrentiel nest modi que si vous validez des modications sortantes.
74
Les ressources sont versionnes an de capturer un instantan de leur tat un moment donn. Vous pouvez versionner les ressources de CVS en les balisant laide dun libell de version. Lorsquune ressource est versionne, une copie non modiable de cette ressource peut tre extraite du rfrentiel. Pour mettre en uvre ce concept dans Eclipse, reprenez lexemple utilis prcdemment : 1. Dans la perspective Rfrentiels CVS, slectionnez le projet que vous souhaitez versionner, CvsTest par exemple. 2. Slectionnez Baliser en tant que version partir du menu contextuel, comme illustr la gure 3.19, et entrez une balise de version, Beta1, par exemple.
Figure 3.19
Versionnement de projet
3. Cliquez sur OK. La nouvelle version safche sous le menu Versions, comme illustr la gure 3.20.
Figure 3.20
75
Pour rserver un projet partir dun rfrentiel CVS dans le plan de travail et ajouter une version votre espace de travail, procdez de la faon suivante : 1. Slectionnez la version que vous souhaitez charger dans la perspective Rfrentiels CVS. 2. Slectionnez CvsTest Beta1, et cliquez sur loption du menu contextuel Rserver en tant que projet , comme illustr la gure 3.21.
Figure 3.21
Sans surprise, un message vous indique que la ressource CvsTest existe dj dans votre espace de travail et vous propose de la remplacer.
Prsentation
Subversion a t lanc en 2004 par des dveloppeurs de CVS dsireux de le remplacer. Dus par les limitations de CVS, ces dveloppeurs ont dot le serveur de chiers Subversion datouts justiant une migration. Parmi les atouts de Subversion, citons notamment les suivants : Versionnement des rpertoires en plus des chiers, ainsi que des liens symboliques.
76
Renommage des chiers. Sous CVS renommer un chier entrane sa suppression et sa recration. Ce nest plus le cas avec Subversion, qui garde lhistorique du changement de nom. Modication atomique. Il est possible denvoyer plusieurs modications dun ensemble de chiers. Si la modication choue sur un des chiers, lensemble de la mise jour est annul. Support des chiers binaires, avec diffrenciation des versions. Choix du protocole de rseau. Subversion permet de grer les accs au rfrentiel en tenant compte de nouveaux protocoles rseau, dont SSH, favorisant dautant linteroprabilit avec les solutions existantes fournies par le serveur (authentication, autorisation, compression, etc.). Par exemple, Subversion peut se pluguer au serveur Apache HTTP en utilisant un module dextension spcique et utiliser WebDAV comme protocole. Convivialit et simplicit. Les numros de version sont dsormais globaux pour lensemble du dpt et non plus par chier. Chaque patch a un numro de rvision unique, quels que soient les chiers touchs. Il devient simple de se souvenir dune version particulire dun projet, en ne retenant quun seul numro. Tous ces avantages justient eux seuls la migration, et nous ne saurions trop conseiller de passer le cap. Subversion est distribu comme son prdcesseur sous licence compatible Apache/BSD et est disponible sur le site principal du projet, ladresse http://subversion.tigris.org/. La version 1.4.2 est disponible en tlchargement sur ce site pour pratiquement toutes les plates-formes disponibles (Linux Red Hat, Debian ou Ubuntu, Windows, etc.). La distribution cliente pour plate-forme Windows conseille est TortoiseSVN. Son principal avantage est de sintgrer parfaitement lExplorateur de chiers de Windows.
Il est possible de convertir un rfrentiel CVS grce au projet cvs2svn (http:// et les commandes CVS sont pratiquement toutes conserves (co pour rcuprer des modications, commit pour en envoyer de nouvelles, diff pour mesurer la diffrence entre deux versions et update pour mettre jour les donnes du rfrentiel). Parmi les nouvelles commandes qui ont fait leur apparition pour compenser les limitations de CVS, signalons move, qui remplace avantageusement la suite de commandes cvs, remote/add/commit), revert, qui retourne la version prcdente dun chier, et status, qui donne un rsum des modications effectues sur le dpt depuis la dernire action de lutilisateur. Les quelques concepts cls spciques Subversion concernent en particulier les trois dossiers principaux suivants dun projet svn typique : /trunk : rpertoire principal contenant les modications au jour le jour du projet ; /branches : rpertoire servant la gestion des extensions du projet initial (notion de fork) ou au stockage dune copie complte du dossier /trunk un instant donn, par exemple lors de la sortie dune release majeure du projet ; /tags : dossier servant normalement stocker une version spcique du projet.
77
Dans les faits, /branches et /tags ne sont que des copies de /trunk et se grent de la mme manire. On peut ne utiliser ces deux dossiers ou nen utiliser quun seul et y stocker les chiers selon les besoins du projet.
Mise en uvre
Monter un serveur Subversion pour une utilisation avec lIDE Eclipse ne prsente pas de difcult particulire. Pour la partie serveur, vous utiliserez la distribution standard pour plate-forme Windows. Pour une utilisation plus professionnelle et plus robuste, il est recommand dutiliser la version pour environnement Linux, la version sous Windows tant surtout utilise ici pour dmontrer les fonctionnalits de la solution. Les commandes dtailles dans cette section sont transposables sans modication particulire dans cet environnement. Aprs avoir tlcharg la distribution de svn pour Windows (ici la version 1.4.2 disponible sur le site ofciel http://subversion.tigris.org/project_packages.html), il suft de lancer le programme dinstallation svn-1.4.2-setup.exe et de se laisser guider par linstallateur. Prenez soin dajouter la variable denvironnement %SVN_HOME% avec pour valeur le rpertoire dinstallation de Subversion, et vriez que linstallation sest bien passe en entrant la commande svn help. Si vous souhaitez connatre la syntaxe dune commande, entrez svn help <macommandesvn>, o macommandesvn dsigne une commande SVN. Un groupe de programmes appel Subversion par dfaut est install sous %SVN_HOME%/ bin, contenant lensemble des outils ncessaires son fonctionnement, dont les principaux modules suivants : svn : programme de commande en ligne client ; svnversion : programme de reporting de ltat dune copie de travail ; svnlook : outil dinspection du rfrentiel Subversion ; svnadmin : outil de gestion du rfrentiel Subversion ; svndumplter : outil de ltrage pour le rfrentiel Subversion ; mod_dav_svn : plug-in pour le serveur Apache http 2.0, permettant de rendre votre rfrentiel accessible aux autres utilisateurs travers le rseau ; svnserve : programme serveur standalone, excutable comme un programme dmon ou invocable par SSH. Pour achever linstallation, vous devez congurer la variable denvironnement SVN_EDITOR via le Panneau de conguration en la positionnant la valeur du chemin contenant votre diteur favori (par exemple, Editplus.exe, en prenant soin dviter les espaces dans le chemin). La variable PATH doit tre ajoute, toujours par le biais du Panneau de conguration Windows, pour donner le chemin daccs aux binaires de svn :
PATH=%PATH%; C:\Program Files\Subversion\bin
Le service Windows permettant de dmarrer svn doit aussi tre install. Appel SvnService.zip, ce service est disponible en tlchargement. Il suft de dcompresser larchive
78
tlcharge dans un espace temporaire puis de linstaller de manire dnitive en entrant sous DOS la commande suivante :
SVNService -install
En supposant linstallation de Subversion correctement effectue, vous pouvez commencer travailler avec Subversion.
Lexcution de cette commande pour effet de construire larborescence illustre la gure 3.22 dans le rpertoire servant de rfrentiel svn_myrepo.
Figure 3.22
2. Pour congurer les chiers de conguration svn, ouvrez le rpertoire d:\svn_myrepo\ conf. 3. Ouvrez le chier svnserve.conf dans un diteur de texte, et dcommentez les lignes [general], anon-access = read, auth-access = write et password-db = passwd (pour dcommenter, il suft de supprimer le # et lespace, mais surtout pas les ###). 4. Sauvegardez et fermez lditeur. 5. Ouvrez le chier passwd dans un diteur de texte, puis dcommentez la ligne [users], et ajoutez le username et le password que vous voulez utiliser pour vous connecter au serveur Subversion. 6. Sauvegardez et fermez lditeur.
79
Lditeur de texte que vous avez paramtr en variable denvironnement souvre alors sur un chier comportant le texte :
--Cette ligne, et les suivantes ci-dessous, seront ignores-A svn://localhost/myproject
3. Entrez un commentaire, par exemple "Cration de mon projet SVN" au dbut du chier (avant la ligne commenant par "--" ). 4. Sauvegardez le chier et fermez lditeur. 5. Dans la fentre de commande DOS de cration, si votre login Subversion est le mme que celui de votre session Windows, saisissez votre mot de passe (celui que vous avez entr dans le chier passwd), et pressez la touche Entre. 6. Si votre login Subversion est diffrent de votre login Windows, pressez la touche Entre linvite du password dans la fentre de commande. Subversion vous demande le login et le mot de passe que vous avez saisis dans le chier passwd. 7. Comme illustr la gure 3.23, Subversion indique "Rvision 1 propage". Ce message vous conrme que la rvision a bien t propage et que vous disposez dune premire version du chier qui vient dtre charg.
Figure 3.23
9. Comme prcdemment, saisissez un commentaire dans le chier ouvert, puis sauvegardez et fermez lditeur. Vous devez constater quune deuxime rvision a t propage dans la fentre DOS. Vous pouvez prsent accder votre serveur svn en utilisant le client TortoiseSVN symbolis par une petite tortue (voir la procdure dinstallation de TortoiseSVN en annexe) et en cliquant sur loption Navigateur de rfrentiel illustre la gure 3.24.
80
Vous pouvez ds lors travailler directement avec le rfrentiel prcdemment cr en utilisant le navigateur de rfrentiel et en examinant dans le dtail la structure et ltat du rfrentiel (voir gure 3.25).
Figure 3.25
81
Vous pouvez excuter des actions telles que la copie, le renommage ou le dplacement de chiers ou de rpertoires directement dans le rfrentiel svn_myrepo. Dans la zone URL du navigateur, vous pouvez entrer lURL du rfrentiel et de la rvision dans lesquels vous souhaitez naviguer. Naviguer dans une ancienne rvision peut se rvler utile si vous souhaitez rcuprer un chier malencontreusement supprim (voir gure 3.26).
Figure 3.26
laide du client TortoiseSVN, vous pouvez crer un chier dans un rpertoire, en procdant de la manire suivante : 10. Crez un rpertoire sur votre disque, par exemple d:\MyProject. 11. Faites un clic droit sur le rpertoire, et slectionnez SVN Extraire. 12. Entrez svn://localhost/monprojet/trunk/ comme URL du rfrentiel, et cliquez sur OK puis nouveau sur OK dans la fentre suivante (voir gure 3.27).
Figure 3.27
82
Une bote de dialogue vous demande de conrmer lextraction, ce qui a pour effet dajouter une icne dans lExplorateur de chiers Windows. 13. Crez un chier dans ce rpertoire, par exemple tata.txt. 14. Faites un clic droit sur ce chier, et slectionnez TortoiseSVN puis Ajouter (voir gure 3.28). 15. Validez en cliquant sur OK.
Figure 3.28
16. Une bote de dialogue conrme lopration. Cliquez sur OK. 17. Mme si la bote de dialogue conrme lajout du chier, celui-ci nest pas encore charg dans le rfrentiel Subversion. Pour ce faire, faites un clic droit sur le chier, et cliquez sur SVN Livrer. 18. Dans la fentre qui safche (voir gure 3.29), saisissez un commentaire plus cliquez sur OK. Si tout se passe bien, lenvoi du chier est pris en compte et conrm par une bote de dialogue. Un clic sur lExplorateur de rfrentiel doit conrmer lopration dajout.
https Il est plus que conseill d'utiliser https pour tout accs en criture depuis les clients SVN, an de protger les chiers par mot de passe.
83
Commit du chier
Plutt que de lancer le dmon directement en ouvrant chaque fois une fentre DOS, il est possible de le faire via le service Windows associ. 1. Ouvrez larchive SVNService.zip tlcharge prcdemment. 2. Extrayez SVNService.exe (et les autres chiers de larchive) dans le rpertoire bin de Subversion. Il est important que le contenu de larchive soit au mme endroit que lexcutable svnserve.exe. 3. Ouvrez une fentre de commande DOS, et entrez :
svnservice -install --daemon --root "d:\svn_myrepo".
Si tout se passe bien, votre service svn est install durablement comme service Windows, et vous pouvez le dmarrer ou larrter en mode manuel ou automatique. Si vous arrtez le service, laccs au rfrentiel devient impossible, et le message Cant connect to host "localhost" safche.
84
2. Cliquez sur Rechercher les nouveaux dispositifs installer puis sur Suivant. 3. Ajoutez un nouveau site distant nomm Subclipse (URL : http://subclipse.tigris.org/update), puis cliquez sur OK et Terminer. 4. Slectionnez lensemble des dispositifs illustrs la gure 3.30.
Figure 3.30
Compatibilit Veillez toujours slectionner une version cliente de Subversion compatible avec votre serveur svn.
5. Cliquez sur Suivant, et acceptez les termes du contrat de licence. 6. Cliquez nouveau sur Suivant puis sur Terminer pour dmarrer le processus dinstallation du plug-in dans Eclipse. 7. Relancez votre plan de travail Eclipse an de prendre en compte linstallation du plug-in. 8. Si linstallation sest bien droule, vous devez dcouvrir une nouvelle vue Eclipse, en cliquant sur Fentre, Ouvrir la perspective, Autre et SVN Repository Exploring. Cette vue laisse dcouvrir la palette svn illustre la gure 3.31.
Figure 3.31
9. Faites un clic droit dans lespace de travail de svn, puis slectionnez New et Repository Location, comme illustr la gure 3.32
85
10. Congurez laccs au rfrentiel svn prcdemment cr en entrant svn://localhost/, puis cliquez sur Terminer. Vous pouvez prsent accder au contenu du rfrentiel et disposer de toutes les commandes svn daccs. la gure 3.33, notez le nom de la rvision en face du nom du chier, tata dans notre exemple.
Figure 3.33
86
2. Dsignez lemplacement du rfrentiel (dans cet exemple d:\MyProject). 3. Crez un nouveau projet Eclipse (un projet Java, par exemple). 4. Subclipse vous demande de prendre en charge votre projet sous le contrle du rpertoire de Subversion et de lajouter automatiquement. Rpondez Oui, et cliquez sur Terminer. Votre projet est dsormais intgr au rfrentiel svn. 5. Pour partager votre projet en quipe, slectionnez-le par clic droit, et choisissez Equipe puis Partager le projet dans le menu contextuel. 6. Slectionnez le type de rfrentiel, ici svn, puis cliquez sur Suivant. 7. Cliquez sur lemplacement du rfrentiel existant (svn://localhost), et cliquez sur Suivant. 8. Conservez loption par dfaut Use project name as folder name , et cliquez sur Terminer. La conguration permettant le partage de votre projet Eclipse avec le rfrentiel svn prcdemment dni est termine. Vous pouvez prsent proter pleinement des nouvelles fonctionnalits de Subversion.
En rsum
Ce chapitre vous a permis de mesurer la facilit de prise en main de loutil CVS dans Eclipse grce la perspective CVS intgre. Vous avez fait connaissance avec Subversion et avez pu apprcier sa facilit dutilisation et ses nombreux avantages par rapport son anctre CVS. Le chapitre suivant vous donnera loccasion de mettre en uvre les fonctionnalits de proling volu de lIDE Eclipse grce au plug-in TPTP.
4
Proling de code avec le projet TPTP
La mise en place de tests et lanalyse des performances des applications sont des phases essentielles dans le cycle de dveloppement dun projet. Cest dans cette optique que la plate-forme TPTP (Test & Performance Tools Platform), aussi appele Hyades, a vu le jour comme sous-projet Eclipse en 2002. Aprs une description des fonctionnalits de TPTP et des diffrents modules qui le constituent, nous dtaillerons sa mise en uvre pratique sur un projet Java avant de passer au proling dune application Web. Le projet TPTP a pour objectif de fournir un environnement complet pour la couverture des tests et la mesure des performances. Il est constitu des quatre modules suivants organiss en sous-projets : TPTP Platform Project, la plate-forme qui fournit le socle utilis par les diffrents outils de performance ainsi que les mcanismes de collecte des mtriques. TPTP Monitoring Tools Project, les outils de monitoring qui permettent de collecter et danalyser les ressources concernant lapplication teste. TPTP Test Tools Project, les outils qui facilitent la cration des tests (capture et excution dune suite de requtes HTTP). TPTP Tracing and Proling Tools Project, les outils de trace et de proling des applications Java et J2EE qui permettent de collecter des informations sur le fonctionnement des applications Java et de les analyser (localisation des allocations mmoire, dtermination des temps dexcution). Eclipse TPTP est une solution extensible qui couvre lensemble du cycle de vie dun projet, depuis les tests unitaires jusqu la mise en production et au monitoring de lapplication, en passant par lenregistrement des tests, leur excution ainsi que la collecte des mtriques et le proling. Outre IBM, les principaux contributeurs au projet sont Computer Associates, Compuware, Intel, SAP et Scapa Technologies.
88
Architecture de TPTP
Avant dentrer dans le cur de larchitecture du projet TPTP, un des nombreux sousprojets Eclipse (http://www.eclipse.org/tptp), nous allons esquisser une dnition de cette activit de plus en plus importante au sein dune quipe de dveloppement J2EE, voire au sein des quipes en charge des tests de charge et doptimisation Java, quest le proling de code Java. Du fait de la complexit croissante des architectures J2EE/JEE, le besoin de connatre dans le dtail la sant de lapplication, en particulier des composants quelle embarque, ncessite la mise en uvre doutils ddis au proling de code Java. Le proling de code consiste gnrer un rapport dtaill de lapplication analyse, comme son temps dexcution et le pourcentage dexcution de chaque procdure, ou mthode dans le cas dapplications Java, contenues au sein de lapplication. Avec un outil de proling, on recherche essentiellement dans lapplication les points suivants : prsence de goulets dtranglement lorigine de dgradations des performances de lapplication (temps de rponse, consommation de ressources CPU, etc.). consommation mmoire excessive provenant de certains composants ou mthodes de lapplication ; fuites mmoire occasionnant une consommation anormale de ressources systme (prsence dobjets volumineux crs par lapplication). Le proling du code consiste observer le comportement de lapplication en situation de charge, ce qui implique la plupart du temps lutilisation doutils de stress test ou dinjecteurs spcialiss, qui enregistrent le fonctionnement de lapplication, comme loadRuner de Mercury ou QaLoad de Compuware. Il est ensuite possible dtudier en mode dconnect lapplication et dinvestiguer plus avant les problmes de performances dtects, cette phase intervenant en gnral en n de dveloppement, avant son passage en prproduction. Le projet TPTP offre un certain nombre de fonctionnalits de proling, notamment les suivantes : ensemble de vues et de perspectives permettant dhistoriser les rsultats des tests dexcution et de les examiner hors excution (analyse statique) ; outils de test de non-rgression et frameworks (plug-in JUnit, assistants graphiques dautomatisation des tests) ; possibilit dinteragir et de proler ses applications, ainsi que, avec les ressources analyses, dexaminer les ventuels problmes de performances et de gestion mmoire ; possibilit de comprendre et de visualiser lexcution de lapplication en mettant en relief les composants qui consomment le plus de ressources.
89
Composants de TPTP
Larchitecture de TPTP fournit un cadre partir duquel une application cliente peut interagir avec une ou plusieurs applications fournissant les mtriques (agents), et ce indpendamment de leur localisation. Cette structure se compose dune interface client, dun processus de gestion dagent, dune interface dagent et de quelques agents usage gnral. Le processus de gestion dagent est appel contrleur dagent. Cest ce composant qui permet une application cliente de se sparer des dtails lis la recherche et au dmarrage des diffrents fournisseurs de donnes situs sur des machines locales ou distantes, dont le type de plate-forme (systme dexploitation et architecture dunit centrale) et le langage (C/C++, Java) peuvent tre diffrents. La gure 4.1 illustre les principaux composants de TPTP.
Figure 4.1
Composants de TPTP
Larchitecture de TPTP est constitue de deux parties, un systme contrleur et un systme cible. Le systme contrleur comporte les composants suivants : Interface utilisateur partir de laquelle les tests sont pilots. Modles de donnes fonds sur le framework EMF (Eclipse Modeling Framework) incluant des modles de tests dexcution, des chiers de logs et des statistiques. Plate-forme Eclipse (diteurs). Interfaces vers un agent de contrle ainsi quun moteur collectant les donnes statistiques. Le systme cible comporte les composants suivants : Application tester. Environnement dexcution de lapplication (JVM et API daccs associes).
90
Moteur de test pour dmarrer lapplication et son environnement. Donnes collectes. Comme vous pouvez le voir la gure 4.2, un contrleur dagent, ou processus dmon, situ de part et dautre de larchitecture permet au client de lancer des processus distants et dinteragir avec les agents distants. Ce contrleur peut ainsi, localement ou distance, proler des applications Java/J2EE et importer des chiers de log en utilisant linterface JVMPI (Java Virtual Machine Proler Interface).
Figure 4.2
91
Figure 4.3
92
Analyse de la gestion de la concurrence des threads et de lexcution de lapplication au niveau thread (vue Thread Analysis). La gure 4.4 illustre une telle vue, chaque thread tant reprsent par une barre verticale.
Figure 4.4
Localisation des fuites mmoires grce la vue Object Reference, qui afche les rfrences par type dobjet (voir gure 4.5). Identication des mthodes les plus frquemment appeles grce la vue Method Invocation, qui reprsente de manire graphique les invocations des mthodes appeles et appelantes (voir gure 4.6). Analyse du ux dexcution du programme et identication des diffrentes phases de son excution (voir gure 4.7).
93
Figure 4.5
Figure 4.6
94
95
9. Cliquez sur Add JAR pour ajouter un chier JAR (<TPTP_INSTALL_DIR>\eclipse\ plugins\ org.eclipse.tptp.platform.collection.framework_4.2.101.v200709261752 \ hcframe.jar) puis cliquez sur Apply. 10. Cliquez sur longlet Monitor pour spcier les critres de proling et cochez loption Memory Analysis pour une analyse de la mmoire lors de lexcution de lapplication (voir gure 4.9).
Figure 4.9
96
11. Cochez loption de proling Execution Time Analysis. 12. Cliquez sur le bouton Edit Options en regard de cette option pour spcier des analyses statistiques (voir gure 4.10).
Figure 4.10
13. Cochez loption Show execution ow graphical details pour afcher les dtails du ux dexcution sous forme de graphique, et rglez la profondeur des classes (Boundary class depth) 1, puis cliquez sur Finish. 14. Double-cliquez sur loption Java Proling pour modier les ltres (voir gure 4.11). Cette option permet dagir sur le niveau des informations que vous souhaitez analyser. Cest surtout utile pour ignorer les classes ou les packages que vous ne voulez pas analyser et rduire le volume des informations collectes lors du proling.
Figure 4.11
97
15. Sous la zone Contents of selected lter set, cliquez sur Add pour ajouter les packages dont vous voulez collecter les donnes. 16. Saisissez org.eclipse.hyades.test.collection.framework.* dans le champ associ au nom de la classe (lastrisque permet de ninclure que les mthodes relatives cet exemple), et cliquez sur OK. 17. Vriez que les autres classes gurant dans la liste des classes ltrer sont positionns EXLUDE (exclues de la liste des classes proler). 18. Cliquez sur Suivant pour accder la page Limites, qui permet de contrler la quantit de donnes collectes en fonction du temps coul ou du nombre dappel de mthodes spci. Acceptez les valeurs par dfaut. 19. Cliquez sur Finish pour appliquer les modications effectues. 20. Cliquez sur longlet Destination, et laissez les valeurs par dfaut dj positionnes (champs Proling project et Monitor). Ces champs reprsentent les ressources de proling charges de stocker les donnes partir de la session de proling. 21. Cliquez sur Apply pour valider lensemble des modications et Prole. Les ressources de proling requises sont cres, et lagent et le processus apparaissent dans la vue Moniteur de proling (voir gure 4.12).
Figure 4.12
22. Activez la visualisation des moniteurs en slectionnant Prsentation distribue. Remarquez que les informations collectes sont enregistres dans les ressources de proling congures prcdemment, en particulier dans DefaultMonitor, comme lillustre la gure 4.13.
Figure 4.13
98
Vue ux dexcution
2. Pour examiner une mthode donne, cliquez sur son nom pour la slectionner. Toutes les mthodes appeles sont ensuite mises en vidence en jaune. La squence des appels de mthode se droule de gauche droite ; les parties actives de lunit dexcution sont identies par cette progression de gauche droite. La longueur verticale de la zone mise en surbrillance indique le temps de base de la mthode. La valeur exacte du temps de base safche sur la ligne dtat. Comme vous pouvez le voir sur lexemple de la gure 4.15, la vue ux dexcution afche le droulement dappel de chaque mthode, organis sous forme de bandes de couleur, chaque bande reprsentant le nom du thread (sur la gure 4.15 les threads gc, main et AWT-Event_Queue). Vous pouvez bien sr slectionner les threads que vous souhaitez visualiser, ainsi que leur couleur, dans le graphe dexcution par simple clic droit. Le temps est afch (en seconde) sur laxe vertical, en commenant par le haut du diagramme. 3. Pour examiner une mthode donne, cliquez sur son nom pour la slectionner. Toutes les mthodes appeles sont ensuite mises en vidence en jaune. La longueur verticale de la zone mise en surbrillance indique le temps de base de la mthode. La valeur exacte du temps de base safche sur la ligne dtat (voir lexemple de la mthode main invoque la gure 4.16). 4. Si la zone analyse est trop sature et difcile lire, faites un zoom avant dans la zone sature. 5. Pour rinitialiser la vue, cliquez sur licne reprsentant une maison.
99
Figure 4.15
Figure 4.16
100
6. Vous pouvez analyser le dtail de linvocation de la mthode en cliquant sur loption Show Method Invocation Details du menu contextuel de la mthode (voir gure 4.17).
Figure 4.17
Cette brve prsentation du proling de code avec la vue ux dexcution vous a permis de mesurer toute la richesse de loutil dans le domaine du proling Java. Pour aller plus loin avec la solution TPTP, examinez avec attention les autres vues adaptes au proling Java.
En rsum
Ce chapitre vous a permis de faire connaissance avec le projet Eclipse Test & Performance Tools Platform et dapprcier toute la puissance de ses fonctions de visualisation. Ces dernires permettent de localiser avec prcision les performances et lutilisation mmoire de vos applications, quelles soient de simples applications Java ou des applications Web complexes.
Partie II
5
Le projet WTP (Web Tools Platform)
Le projet Web Tools est constitu de sous-projets, en particulier JST (J2EE Standard Tools), destin fournir la communaut loutillage ncessaire au support de la spcication J2EE/JEE, et WST (Web Standard Tools), qui a pour but denrichir la plate-forme Eclipse doutils de dveloppement dapplications Web en utilisant J2EE. Le projet JST forme lossature de la plate-forme Web Tools en fournissant un cadre de dveloppement respectant la spcication J2EE, ainsi quun ensemble dassistants pour le support du serveur dapplications JBoss, qui sert de cible et de support au dploiement de lapplication dveloppe. Le projet WTP inclut les lments suivants : diteurs pour les langages de pages Web (HTML, CSS, JavaScript) ; diteurs pour les documents XML et associs (XML, DTD, XSD et WSDL) ; support de projets J2EE via des assistants ; support des services Web via des assistants ; support des bases de donnes via SQL. Le projet WTP est constitu de sous-projets, notamment les suivants : JST (J2EE Standard Tools). Accessible ladresse http://www.eclipse.org/Web Tools/jst/ main.php, ce sous-projet propose des plug-ins pour faciliter le dveloppement dapplications respectant la norme J2EE 1.4 (en particulier JSP, servlets, EJB, JCA, JMS, JNDI, JDBC, Java Web Services, JAX et JSR-associes). Le support pour les spcications JCP (Java Community Process), accessible sur http://www.jcp.org, utilises dans les applications Web mais non incluses dans la spcication J2EE 1.4, est adapt au cas par cas. Par exemple, JSF fait lobjet dune implmentation particulire (voir la page du projet JSF http://www.eclipse.org/jsf). Rappelons que le rle premier du JCP est de coordonner lvolution du langage Java et den maintenir la cohsion et la compatibilit, notamment par le biais de certications.
104
WST (Web Standard Tools). Propose un socle pour le dveloppement dapplications Web sous Eclipse. JSF (JavaServer Faces). Propose des plug-ins pour faciliter le dveloppement dapplications Web utilisant les JSF. Dali. Propose des plug-ins pour faciliter le mapping O/R avec lAPI JPA. ATF (Ajax Toolkit Framework). Supporte plusieurs conteneurs et serveurs dapplications, en particulier Tomcat (versions 3.2 5.5) et JBoss 4.x et 5.0 Bta. Le site ofciel du projet est lURL http://www.eclipse.org/Web Tools/.
JEE5 Bien que WTP supporte la notation J2EE 1.4, nous utiliserons par raccourci la nouvelle dnition de la norme Java Platform Entreprise Edition, appele JEE5, pour le support des JDK 1.5 et 1.6 en lieu et place de J2EE, qui supporte plus spciquement les versions des JDK 1.4/1.3/1.2.
Primtre de JST
JST fournit Eclipse un ensemble doutils et de technologies standards pour le dveloppement dapplications Java conformes la spcication J2EE 1.4. Le tableau 5.1 rcapitule les standards JCP supports par JST.
Tableau 5.1 Standards JCP supports par JST
JSR-3 Java Management Extensions (JMX) 1.2 JSR-5 Java API for XML Parsing (JAXP) 1.2 JSR-45 Debugging Support JSR-54 JDBC API 3.0 JSR-67 SOAP with Attachments API for Java (SAAJ) 1.2
Le projet WTP (Web Tools Platform) CHAPITRE 5 Tableau 5.1 Standards JCP supports par JST (suite)
JSR-77 J2EE Management API 1.0 JSR-88 Deployment API 1.1 JSR-93 Java API for XML Registries (JAXR) 1.0 JSR-101 Java API for XML-based RPC (JAX-RPC) 1.1 JSR-109 Web Services JSR-112 J2EE Connector Architecture (JCA) 1.5 JSR-115 Java Authorization Contract for Containers (JACC) JSR-152 JavaServer Pages (JSP) 2.0 JSR-153 Enterprise JavaBeans (EJB) 2.1 JSR-181-Metadata for Web Services, JSR-154 Servlets 2.4 JSR-175: Metadata Facility for the JavaTM Programming Language JSR-907 Java Transaction API (JTA) 1.0 JSR-914 Java Message Service (JMS) 1.1 JSR-919 JavaMail 1.3
105
En complment, les standards et technologies non-JCP suivants sont inclus dans le primtre de JST : JAAS (Java Authentication and Authorization Service) JNDI (Java Naming and Directory Interface) XDoclet
106
Modle dartefacts JEE. Reprsente les sources JEE ainsi que les composants JSP, EJB, descripteurs de dploiement, etc., qui peuvent tre crs et grs au sein dun projet en mme temps que dautres artefacts, comme les ressources de type image, texte et autres chiers qui peuvent tre packags dans un module J2EE dployable (war/ejb, jar/rar). Modle de serveur JEE. Fournit les abstractions requises pour supporter le dploiement de modules pour diffrents types de serveurs dapplications. Il offre de manire additionnelle un mcanisme uni pour dmarrer, administrer et stopper les serveurs dapplications JEE. Ce modle fournit le moyen de grer les dtails de conguration des serveurs, comme les paramtres JVM, les variables daccs aux chemins (classpath), etc. Enn, les modules J2EE tels que le packaging, le dploiement, le dbogage ou limport/export de modules J2EE sont grs par ce modle.
Un projet Eclipse est utilis pour dvelopper des modules applicatifs J2EE Web, ou EJB. Chaque module J2EE est en fait dvelopp dans un projet spar et possde son propre accs aux classes dnies dans le JDT (outillage Java dEclipse). Il ne faut toutefois pas confondre module et projet. Il est ainsi possible que diffrents projets partagent un mme module (par exemple, un module jar contenant les bibliothques partages par le projet J2EE). Un projet Eclipse basique fournit une structure pour organiser les ressources dans le projet (ressources de types chiers et rpertoires) : Projet Java, qui contient les lments et artefacts (packages, mthodes, classes et attributs) ncessaires au dveloppement Java. Projet Web, qui contient en plus du code Java des ressources pour le support du dveloppement Web (bibliothques Struts, chiers html, servlets, JSP, bibliothques de balises, services Web et descripteurs de dploiement). La gure 5.1 illustre lorganisation en composants dun projet Eclipse. La gure 5.2 dcrit les constituants du packaging nal dune application JEE, rpartis selon les modules projets prcdents, lensemble de ces modules tant packags dans un chier EAR avec leurs descripteurs respectifs.
107
Figure 5.2
108
Projet de client dapplication (Application Client Project) : ensemble de composants client conus pour la consommation de services fourni par une application dentreprise. Projet connecteurs (Connector Project) : ensemble de chiers source destins la cration de connecteurs applicatifs pour lintgration aux systmes legacy spcis par la JSR-112 (J2EE Connector Architecture 1.5). Projet dapplication dentreprise (Enterprise Application Project) : ensemble de modules reprsentant une application dentreprise complte. Ce type de projet fournit la possibilit de rfrencer diffrents composants de type EJB, Web, client dapplication et connecteur qui seront dploys ensemble. Les modules J2EE additionnels fournissent de nombreuses fonctionnalits pour la cration de projet, notamment la possibilit de crer et de grer des artefacts selon les types de projets ci-dessus et, surtout, de crer une structure de dploiement type pour le support au projet J2EE (type WAR pour un projet Web, ou EAR pour une application dentreprise, par exemple). La gure 5.3 illustre lassistant de cration de projet JST proposant un certain nombre doptions pour un projet dentreprise J2EE.
Figure 5.3
Europa lheure de la rdaction de cet ouvrage, la version Eclipse 3.3 Europa ne dispose pas dun support de la langue franaise. Nous nous rfrons donc la version anglaise en notre possession.
109
Figure 5.4
Avec JST, un projet J2EE/JEE ncessite lexistence dune JRE (Java Runtime Environment) et dun environnement dexcution J2EE/JEE compatible. Lenvironnement dexcution J2EE/JEE fournit un support pour les fonctionnalits dentreprise utilises dans le projet. JST supporte la dnition de plusieurs versions denvironnements dexcution J2EE/JEE permettant la cration de projets dployables sur diffrentes versions de JVM et sur diffrentes versions de serveur dapplications cible.
110
Version EJB
1.1, 2.0 et 2.1
La gure 5.5 illustre la dnition dune cible serveur dapplications JBoss 4.0.5 (accessible via le menu Preferences dEclipse).
Figure 5.5
Des congurations supplmentaires sont disponibles pour chaque environnement cible dni sur le serveur permettant dagir sur les variables daccs aux classes, ainsi que sur les arguments dexcution de la JVM et de dmarrage de linstance.
111
La gure 5.6 illustre une conguration par dfaut dnie pour le serveur dapplications JBoss 4.0 (vous pouvez aussi agir sur le mode de publication et de dploiement des composants serveur via loption Automatic Publishing).
Figure 5.6
112
Nommes Project Facets, ces fonctionnalits sont congurables lors de la cration du projet et par la suite dans la page des proprits du projet (voir gure 5.7).
Figure 5.7
Figure 5.8
113
Lassistant WST de cration et de publication de service Web offre les avantages suivants : Dveloppement de services Web de type bottom-up/top-down ( partir dun JavaBean existant ou non). Dmarrage de services Web dans un projet Web. Gnration de proxy Java. Test de services Web. Monitoring de services Web. Web Tools inclut un moniteur embarqu qui permet de surveiller les enveloppes SOAP et les ux entre le client et le service invoqu.
114
Monitoring TCP/IP
WST inclut un navigateur Web permettant daccder aux pages Internet lintrieur de lIDE mais aussi de mesurer le trac HTTP chang, permettant ainsi la capture et lanalyse des messages envoys et reus partir dun port et dun hte spcique. Loutil de monitoring TCP/IP permet sauvegarde les messages dans un chier de log, lequel peut ensuite tre analys avec la suite doutils de test intgr (voir gure 5.10).
Figure 5.10
La version de WTP 2.0 disponible en tlchargement sur le site du projet (http://downsuppose linstallation pralable sur la plate-forme Europa des composants rcapituls au tableau 5.3.
Tableau 5.3 Composants installer sur Europa
Composant
Eclipse Platform (JDT, PDE) Eclipse Modeling Framework (EMF, XSD InfoSet, SDO) GEF (Graphical Editing Framework) DTP (Data Tools Platform)
Version
Eclipse SDK 3.3 (Europa) emf-sdo-xsd-SDK-2.3.0RC4 GEF-SDK-3.3RC4 dtp-sdk_1.5RC4
115
Linstallation de ces composants ne prsente aucune difcult particulire et seffectue, comme pour la distribution dEclipse, par une dcompression des binaires dans le rpertoire dinstallation dEclipse (par exemple, sous Windows c:\MonEclipse\3.3\eclipse). Une fois ces composants tlchargs, prenez soin de lancer lIDE Eclipse par le biais de loption clean (sous c:\MonEclipse\3.3\eclipse\bin).
Conguration de la JRE
Version de JRE Si vous ne connaissez pas lemplacement de votre JRE, vous pouvez reprer celle-ci en consultant la variable JAVA_HOME dnie dans votre systme.
Dans cette conguration, optez pour une JRE 1.5.0 Update 11. La slection du rpertoire dinstallation de la JRE installe toute les bibliothques associes cette dernire, sachant quil est aussi possible dajouter des bibliothques jar additionnelles dans lenvironnement dexcution de la JVM. Ltape suivante consiste congurer lenvironnement dexcution du serveur J2EE offrant le support des caractristiques spciques qui seront utilises au sein de lapplication J2EE dploye. linverse de la conguration de la JRE vue prcdemment, qui est gnralement fournie par Sun Microsystems, le runtime J2EE est disponible partir dune varit dditeurs proposant leur propre implmentation de serveurs J2EE compatibles (gnralement inclus dans lenvironnement du SA). La conguration du serveur est accessible par le biais de Window, Preferences, Installed Runtimes et Add. Lassistant de dnition et de conguration safche alors comme illustr la gure 5.12 (ici avec JBoss).
116
Figure 5.12
Lassistant de conguration du serveur permet, en fonction du serveur cible prslectionn, de dnir la localisation de la JRE, ainsi que du serveur dapplications, avec intgration immdiate des bibliothques jar disponibles pour ce serveur (voir gure 5.13).
Figure 5.13
Eclipse supporte la cration de plusieurs environnements J2EE, chaque environnement tant ddi un serveur dapplications particulier install sur le systme. Il est possible de crer plusieurs congurations dexcution fondes sur des installations particulires du serveur dapplications cible. Cela peut se rvler utile notamment pour tester lapplication en utilisant diffrentes versions de JRE.
117
Dans le contexte du dveloppement EJB3, vous devez utiliser certaines bibliothques de support cette technologie pour le serveur JBoss 4.0.5. Procdez pour cela de la faon suivante : 1. Cliquez sur New, et nommez votre bibliothque JBOSS_EJB3. 2. Ajoutez les jar suivants (via le bouton Add JARS) :
$JBOSS_HOME/server/default/lib/ejb3-persistence.jar $JBOSS_HOME/server/default/deploy/ejb3.deployer/jboss-ejb3.jar $JBOSS_HOME/server/default/deploy/ejb3.deployer/jboss-ejb3x.jar $JBOSS_HOME/server/default/lib/jboss-j2ee.jar
La conguration de votre bibliothque doit ressembler celle illustre la gure 5.15 (en fonction du rpertoire dinstallation de votre serveur dapplications JBoss).
118
Figure 5.15
3. Cliquez sur OK pour terminer lopration. Vous intgrerez ensuite celle-ci votre projet. Sans anticiper sur les fonctionnalits du serveur JBoss et les congurations spciques aux projets EJB3, que nous prsentons un peu plus loin dans cet ouvrage, cette tape de dnition des bibliothques spciques au projet est cruciale dans la conguration du poste de dveloppement an de permettre une standardisation des dveloppements. Passez prsent aux fonctionnalits spciques de support au dveloppement Web apportes par le projet JST pour la conguration dun projet Web.
Support des chiers jar externes Lajout et la dnition de bibliothques externes au chemin de compilation du projet pour lutilisation de lAPI EJB3 nest plus ncessaire avec les versions suprieures JBoss 4.2.
119
2. Cliquez sur Next, puis entrez WebStock devant le nom du projet (voir gure 5.17). Notez que lenvironnement dexcution cible du projet (champ Target Runtime) pointe sur la cible SA dnie prcdemment (JBoss 4.0).
Figure 5.17
120
Notez que, depuis Web Tools 2.0, trois types de congurations spciques sont proposs : Dfault Conguration for JBoss v4.0, par dfaut pour le dveloppement dapplications sur Jboss 4.0. Dynamic Web Project with XDoclet, pour le support des annotations avec le standard XDoclet. JavaServer Faces v1.1 Project, pour le support de limplmentation de rfrence de la technologie JSF. 3. Choisissez la premire option, puis cliquez sur Next (voir gure 5.18).
Figure 5.18
Project Facet Comme voqu plus haut, les fonctionnalits Project Facet permettent de grer toute la varit de projets et de supports des diffrentes varits de frameworks. Web Tools offre la possibilit dajouter et de supprimer dynamiquement ces fonctionnalits aux projets. Les Project Facets sont congurables lors de la cration du projet et par la suite dans la page des proprits du projet.
4. Slectionnez les facets JavaServer Faces 1.1 et WebDoclet (XDoclet) 1.2, puis cliquez sur Next. 5. Dans la bote de dialogue qui safche, congurez le module Web : Context Root : permet de dnir le chemin virtuel au sein duquel le contenu de lapplication Web sera accd sur le SA.
121
Content Directory : rpertoire contenant les artefacts Web (chiers HTML, JSP, chiers graphiques, etc.). Java Source Directory : rpertoire contenant les sources des classes, des servlets et des beans. Lorsque ces ressources sont ajoutes au projet Web, celles-ci sont automatiquement compiles, et le rsultat compil est ajout au rpertoire WEB-INF/classes. 6. Cliquez sur Next. La page illustre la gure 5.19 safche.
Figure 5.19
Cet assistant congure les principaux chiers de conguration JSF (faces-cong.xml, rpertoire de mapping des URL, etc.). Pour utiliser la fonctionnalit de rfrence de la technologie JavaServer Faces version 1.1, il faut tlcharger limplmentation de rfrence de cette technologie, ladresse http://java.sun.com/javaee/javaserverfaces/download.html). 7. Cliquez sur New pour crer la bibliothque et lassocier au jar tlcharg contenant les bibliothques JSF 1.1. 8. Cliquez sur Finish pour terminer la conguration du projet Web dynamique, puis cliquez sur la nouvelle perspective fournie par JST, via Fentre, Ouvrir la perspective, Autre et Java JEE. Vous devez voir safcher larborescence de votre projet JEE comme illustr la gure 5.20. La vue dafchage des erreurs laisse apparatre un problme de conguration de loutil de gnration de code XDoclet, qui permet le dveloppement orient attribut (Attribut-Oriented Programming). Il a surtout conquis ses lettres de noblesse pour fournir, grce aux trs populaires outils de build Ant, une solution de gnration multi-AS et multi-technologies J2EE (Struts, JSF, EJB, etc.).
122
Figure 5.20
9. Pour lutiliser et lintgrer dans Eclipse, tlchargez la dernire version de loutil partir du site de rfrence http://xdoclet.sourceforge.net/. ce jour, la version la plus jour est la 1.2.3. 10. Dcompressez la distribution dans un rpertoire ddie (par exemple, L:\ XDoclet1.2.3). 11. Faites pointer la version de XDoclet comme illustr la gure 5.21.
Figure 5.21
Conguration de XDoclet
12. Cliquez sur OK, puis rgnrez votre projet en slectionnant Projet et Nettoyer. Vous devez retrouver votre espace de travail exempt de toute erreur de compilation.
123
Proprits du projet
Les projets J2EE sont crs avec des proprits par dfaut par lassistant de cration de projet fourni par JST. Ces proprits sont gnralement sufsantes pour la majorit des projets dvelopps. Il arrive toutefois que ces proprits ne rpondent pas au besoin des applications dveloppes. JST fournit la possibilit de modier les rglages du projet par le biais de loption Properties du menu contextuel du projet en cours de dveloppement (voir gure 5.22).
Figure 5.22
Description
Fournit un certain nombre dinformations sur le projet en cours, comme sa localisation sur le systme de chiers, la date de dernire modication, le type dencodage, etc. Permet lactivation de lintrospection BeanInfo sur le projet. Congure les gnrateurs du projet et lordre de leur invocation. Module de gestion des dpendances (bibliothque jar externe ou projet utilitaire en particulier) Indique la location de chiers additionnels de projet ou de bibliothques inclure lors de la construction du projet. Gre galement lordre de rfrencement de ces artefacts.
124
Dveloppement Web avec le projet Eclipse Web Tools PARTIE II Tableau 5.4 Proprits de conguration du projet J2EE (suite)
Proprit
Java Code Style Java Compiler Java Editor Javadoc Location JSP Fragment Prole Compliance and Validation Project Facets Project References Refactoring History Run/Debug Settings Server Targeted Runtimes Task Tags Validation Web Content Settings Web Project Settings Xdoclet
Description
Spcie le style du code utilis pour la gnration de code pour appliquer des conventions de nommage, des rgles de style et de commentaire. Spcie les rglages pour le compilateur associ au projet Java. Spcie les actions effectuer lors de la sauvegarde du code source. Spcie la localisation de la documentation au format javadoc du projet. Dnit lencodage par dfaut, la directive page et la valeur du type de contenu pour le fragment JSP (projet dynamique uniquement). Spcie le niveau dinteroprabilit WS-I et WS-I SSBP (Attachments Prole and Simple SOAP Binding Prole). Permet de modier les caractristiques du projet. Spcie les projets rfrencer. Historique de refactoring Gre la conguration de lancement associe (Java Applet/Java application). Utilise le serveur spci lors du dmarrage du projet. Conguration serveur cible Spcie les balises qui seront utilises pour indiquer les tches. Afche les validateurs qui vont sexcuter durant la validation du projet. Proprits par dfaut du projet appliques en particulier au type de document (xHTML 1.0 Strict/Frameset/MP 1.0/Basic 1.0) Spcie le contexte root du projet Web. Congure loutil Xdoclet.
125
Description
Fournit une vue de type navigation pour parcourir les diffrents artefacts du projet JEE, chaque composant type tant reprsent par une icne par ticulire (JSP, bibliothque, etc.). Afche la structure des lments contenus dans le document en cours ddition en utilisant une vue arborescente. Liste les problmes existants dans le projet en cours de modication (problmes de compilation, etc.). Fournit une liste des lments assigns sous forme de tches ou de pense bte pour le dveloppeur (ajout de commentaire, etc.). Permet dinspecter et modier les proprits de llment courant slectionn. Permet de contrler les oprations de linstance serveur congure (arrt/relance, etc.).
Des vues supplmentaires peuvent tre ouvertes en slectionnant les options Window, Show View et Other dEclipse puis en slectionnant la vue requise. La nouvelle vue souvre ct des vues existantes de la perspective JEE et les complmente de manire personnalise. Il est ensuite possible de sauvegarder ces vues personnalises par le biais Window et Save Perspective As pour les rutiliser ensuite. La synchronisation sopre immdiatement entre chaque vue JEE et la source du document dans lditeur.
En rsum
Ce chapitre vous a permis de vous familiariser avec loutillage de support au dveloppement JEE inclus dans WTP et les diffrentes vues et proprits permettant de grer ce type de projet. Le chapitre suivant vous fournira loccasion de faire connaissance avec un autre projet utile au dveloppement Web et au support des donnes, le projet Data Tools.
6
Conception du modle de donnes avec le projet DTP (Data Tools Platform)
Ce chapitre prsente loutillage du projet Eclipse Data Tools Platform, centr sur la manipulation des structures de donnes, qui facilite la dnition du modle physique de la base de donnes. DTP est un nouveau projet principal de la communaut Eclipse. Originellement propos par Sybase en fvrier 2005, il a entran dans son sillage une large et solide communaut et est actuellement gr par un comit comprenant Sybase, IBM et Actuate. DTP est un framework orient utilisateur centr sur les problmatiques daccs aux donnes (data centric), devenues incontournables dans le dveloppement dapplications. Le projet offre les avantages suivants : centralisation de la dnition des connecteurs aux principales sources de donnes en un seul endroit, au niveau de linstance de la plate-forme Eclipse ; centralisation de la dnition des connexions et de leur cration ; possibilit pour les outils daccder un ensemble abstrait de connexions en masquant les dtails de leur implmentation ; masquage de lhtrognit des connexions et des outils pour chaque source de donnes ; possibilit de partager les dnitions de connexions, facilitant lintgration de la solution au niveau de la plate-forme Eclipse et lutilisation.
128
Architecture de DTP
Fond sur le framework EMF, DTP consiste en un modle de base, des connecteurs et des outils SQL pour linterrogation et la manipulation des donnes. Il propose une architecture de conception oriente modle (Model Driven Design) qui supporte les principales bases de donnes relationnelles du march. Les sections qui suivent dtaillent les trois sous-projets cls qui constituent lossature du projet DTP. La version que vous utiliserez est la celle livre en bundle avec Europa (DTP 1.5).
Ce projet fournit les fondations pour le dveloppement de la couche daccs aux donnes. Il utilise une approche oriente modle avec UML, fonde sur le framework EMF (Eclipse Modeling Framework). Il inclut les composants suivants : modle de dnition de donne ; diteur de modle ; modle SQL ; modle dinterrogation SQL (spcications SQL 99/03) ; modle de requte SQL/XML. Les principales caractristiques de ce sous-projet sont les suivantes : gestionnaire de version, les modles pouvant tre aisment versionns travers le composant de gestion de versions intgr Eclipse ; support dun diteur de modle intgr visuel avec EMF ; support de javadoc, les modles pouvant tre publis et documents ; extensibilit, les modles tant extensibles et ntant pas dpendants dun systme de gestion de donnes propritaire ; standardisation, les modles tant compatibles avec les standards existants, comme SQL et JDBC.
CMF (Connectivity Management Framework)
Le projet CMF fournit les ressources pour la gestion des connexions aux diverses sources de donnes JDBC ainsi que loutillage de support appropri pour lutilisation des connexions. Le framework pour la dnition ou la cration de drivers est fond sur un certain nombre de modle proposs par dfaut (dautres modles peuvent tre crs par le biais de points dextension DMF).
Conception du modle de donnes avec le projet DTP (Data Tools Platform) CHAPITRE 6
129
Une fonctionnalit cl du sous-projet connecteur est la possibilit offerte aux utilisateurs de saisir une fois leur information et de la rutiliser travers lensemble des outils dEclipse. Conu sur le modle de DMF, le framework CMF dnit des connexions spciques travers la conguration des donnes et fournit des instances de connexions. La gure 6.1 illustre les dnitions de drivers accessibles par le biais du menu Prfrences dEclipse.
Figure 6.1
Le projet CMF propose galement dans la vue Eclipse un explorateur de sources de donnes sous la forme dinstances de prols de connexion, ou CP (Connection Prole), associ un framework daccs aux donnes, ou ODA (Open Data Access). Cela permet aux applications daccder aux donnes partir de sources de donnes standards et personnalises. ODA permet la connectivit des donnes entre les consommateurs et fournisseurs de donnes travers des interfaces dexcution en fournissant une abstraction travers le concept de donne, de la mme manire que CMF fournit une abstraction travers la notion de connexion ces mmes donnes.
SQL Development Tools
Ce projet fournit les frameworks et outils permettant de travailler avec SQL et dtendre les fonctions des outils dinterrogation. Lditeur de routines et le dbogueur de routines (Routine Editor et Routine Debugger) fournissent un moyen dinteragir avec les procdures stockes et les fonctions. Le parseur de requtes SQL permet aux outils SQL dutiliser un arbre danalyse associ la requte SQL. De son ct, le framework SQL Execution Plan permet une analyse ne et le tuning des requtes SQL. Il est galement possible dexcuter des procdures stockes.
130
Figure 6.2
Conception du modle de donnes avec le projet DTP (Data Tools Platform) CHAPITRE 6
131
Derby est le nom de limplmentation Open Source du SGBD drive dIBM Cloudscape, la version commerciale de la base dIBM. Vous utiliserez essentiellement cette base pour vos tests et votre dveloppement, tant entendu que, pour des dploiements naux en production, il est recommand dutiliser des bases telles que MySQL 5 ou quivalentes. Linstallation et la prise en main de Derby ne prsentent pas de relles difcults non plus que sa conguration. Nous supposons que le rpertoire dinstallation de la base Derby (dsign par la variable denvironnement DERBY_HOME) se trouve sous C:\Tools\dbderby-10.2.2.0-bin. 1. Positionnez dans la variable classpath de votre installation les bibliothques derby.jar et derbytools.jar sous le rpertoire lib de DERBY_HOME. 2. Lancez la commande ij pour crer la base de test webstockdb (voir gure 6.3).
Figure 6.3
3. La commande ij tant une application Java, vous devez lancer une JVM et indiquer le nom complet de la classe principale que vous souhaitez excuter (ici loutil ij). En cas dexception, vriez que le chier jar derbytools.jar est prsent. La commande connect permet la connexion la base de donnes, en loccurrence ici la chaine, ou URL, de connexion jdbc:derby:webstockDB;create=true. La proprit create=true, passe au driver JDBC Derby, spcie la cration de la base si celle-ci nexiste pas. 4. Quittez la session de connexion la base Derby en entrant exit. 5. Lancez la commande dir sous Windows ou ls sous UNIX. Vous devez constater quun nouveau rpertoire webstockdb a t cr, ainsi que les sous-rpertoires webstockdb/log et webstockdb/seg0, qui contiennent les donnes de la base webstockdb.
Copie de la base de donnes Pour crer une copie de votre base de donnes Derby, vous devez simplement stopper linstance Derby, effectuer une copie du rpertoire et des sous-rpertoires (ici webstockdb) et relancer le serveur. La restauration de la base est aussi simple : stoppez le serveur, puis remplacez la structure de la base avec la copie restaure, et relancez le serveur.
6. Revenez sur lIDE Eclipse, et cliquez sur le bouton Add aprs avoir slectionn dans le menu Preferences dEclipse la dnition du driver Derby 10.2. 7. Slectionnez loption Derby Embedded Driver (voir gure 6.4).
132
Figure 6.4
8. Supprimez le chier driver derby.jar, et ajoutez la dnition des drivers suivants partir de lemplacement DERBY_HOME\lib\ (voir gure 6.5) : Connection URL Database Name : webstockdb Password : admin User Id : derby
Figure 6.5
Conception du modle de donnes avec le projet DTP (Data Tools Platform) CHAPITRE 6
133
Figure 6.6
2. Lexplorateur de sources de donnes Eclipse est accessible en slectionnant Databases puis New.
Figure 6.7
134
3. Slectionnez Derby Embedded Database, puis cliquez sur Next. 4. Donnez un nom au prol de connexion (par exemple MyDerby) et optionnellement une description, puis cliquez sur Next (voir gure 6.8).
Figure 6.8
5. Cliquez sur Finish pour terminer la cration du prol de connexion. Vous tes prt vous connecter linstance Apache Derby. 6. Dveloppez le nud Databases dans la vue Data Source Explorer, puis slectionnez le prol de connexion que vous venez de crer par clic droit, et slectionnez Connect. Aprs quelques secondes, vous devriez voir apparatre le prol de connexion dvelopp avec le contenu de la base Derby webstockdb vide (voir gure 6.9).
Figure 6.9
Conception du modle de donnes avec le projet DTP (Data Tools Platform) CHAPITRE 6
135
6. Cliquez sur Finish. 7. Faites un copier-coller du contenu du chier script de cration du schma de la base webStock dans le chier webStockDDL.sql via lditeur de script associ.
136
8. Cliquez sur Execute All pour lancer lexcution du script. Si tout se passe bien, vous devez voir safcher dans lexplorateur de source de donnes les tables illustres la gure 6.11.
Figure 6.11
Figure 6.12
Vue SQL Results Utilisez la vue SQL Results de loutillage DTP pour afcher ltat des requtes lors de leur excution. Cette vue (qui sobtient via Window, Show View, Other puis SQL Development SQL Results du menu Eclipse) afche le rsultat de linstruction SQL courante sous forme tabulaire (statut de la requte, opration, date, prol de connexion).
Conception du modle de donnes avec le projet DTP (Data Tools Platform) CHAPITRE 6
137
9. Refaite les mme tapes avec le script de peuplement de la base webstockdata disponible sur la page Web associe louvrage. 10. Vous pouvez afcher le contenu et extraire les donnes provenant des tables de la base par le biais de la vue Data Source Explorer. 11. Faites un clic droit, et slectionnez les options contextuelles Data et Sample Contents pour lafchage ou Data et Extract pour une extraction des donnes Vous pouvez galement diter les donnes afchs par le biais des options Data et Edit du mme menu contextuel. La gure 6.13 illustre lafchage du contenu de la table Article.
Figure 6.13
Pour insrer une ligne dans la table, il suft de sauvegarder lditeur en slectionnant File puis Save (ou Ctrl+S). La vue SQL Results afche le rsultat de linsertion.
Gnration du DDL
Vous pouvez gnrer le DDL (Data Denition Language) partir du modle dj gnr en slectionnant le dossier Tables du schma webstock dans la vue explorateur de donnes et en cliquant sur Generate DDL dans le menu contextuel (voir gure 6.14).
Figure 6.14
En rsum
Vous en avez termin avec les tapes de cration de la base webstock qui sert de cadre louvrage. Vous pouvez prsent vous concentrer sur le dveloppement de la partie Web de ltude de cas en utilisant les assistants et outils du projet Web Tools.
7
Dveloppement Web avec loutillage Web Tools et les patterns
Ce chapitre prsente loutillage Web Tools pour le dveloppement Web sans laide dun framework particulier, en utilisant les bonnes pratiques de conception. Nous commencerons par dcrire loutillage du projet Web Tools (WTP) et rappellerons les principes de base de larchitecture dune application Web et de ses composants (IHM et couche daccs aux donnes) ainsi que les tapes qui vont de son dveloppement jusqu son dploiement. Nous terminerons par le design et la mise en uvre dune portion dapplication Web selon une approche fonde sur les modles de conception ou pattern. Ce design et cette mise en uvre seffectueront en logique 3-tiers traditionnelle, cest--dire sans lutilisation dun framework particulier et en utilisant des composants de type servlet et JSP, ainsi que les bibliothques de balises JSTL (JavaServer Pages Standard Tag Library). Enn, nous ferons un tour dhorizon des fonctionnalits offertes par Web Tools pour simplier le dveloppement Web. Nous supposons acquises les bases du dveloppement par servlets/JSP et JSTL, ainsi que les notions propres aux API JDBC, que nous nous contenterons de rappeler.
Principes de base de lexcution dune requte JDBC partir dun programme Java
Avant dentrer dans le design et la mise en oeuvre du dveloppement Web avec Web Tools, nous allons rsumer les bases de linterrogation SQL dune base de donnes partir dun programme Java. Lexcution dune requte JDBC, implique trois concepts essentiels : une connexion base de donnes (objet Connection) ;
140
une requte SQL (objet Statement) ; le rsultat de la requte (objet ResultSet). Pour utiliser ces objets, vous devez les importer dans votre application, comme le montre lextrait de code suivant, dont le code complet est disponible sur la page Web ddie louvrage :
import import import import import import java.sql.Connection; java.sql.DriverManager; java.sql.SQLException; java.sql.SQLWarning; java.sql.Statement; java.sql.ResultSet;
public class FirstQuery { private static final String driver = "org.apache.derby.jdbc.EmbeddedDriver" ; private static final String url = "jdbc:derby:WebstockDB" ; private static final String qry = "SELECT articleId, nomArticle, articleCategorieId, fournisseurId, description, poids FROM webstock.article" ;
Les classes Java et constantes ncessaires linterrogation de la base de donnes (URL daccs la base webstockdb et requtes dinterrogation la table webstock.article) sont importes explicitement. Chaque colonne est invoque pour viter les effets de bord en cas de modication du schma de base de donnes sous-jacent. Les oprations requises pour excuter une requte la base partir dun programme Java sont relativement simples, comme lillustre lextrait de code suivant, qui prsente la mthode doQuery avec inclusion de la clause SQLException, qui permet de remonter lexception vers le code appelant :
static void doQuery(Connection con) throws SQLException { SQLWarning swarn = null ; Statement stmt = con.createStatement() ; ResultSet rs = stmt.executeQuery(qry) ; while (rs.next()) { System.out.println("Numro Article: " + rs.getString("articleId")) ; System.out.println("Nom Article: " + rs.getString("nomArticle")) ; System.out.println("Catgorie Article: " + rs.getString("articleCategorieId")) ; System.out.println("Fournisseur Article: " + rs.getString("fournisseurId")) ; System.out.println("Description: " + rs.getString("description") + '\n') ; System.out.println("Poids Article: " + rs.getString("poidsArticle") + '\n') ; swarn = rs.getWarnings() ; if(swarn != null){ printSQLWarning(swarn) ; } } rs.close() ; stmt.close() ; }
141
Dans la mthode doQuery, vous crez dabord un nouvel objet JDBC Statement en utilisant la mthode createStatement sur lobjet Connection. Vous utilisez ensuite la mthode executeQuery sur lobjet Statement cr pour envoyer la chane de requte la base Apache Derby o celle-ci est excute. Vous accdez ensuite aux rsultats de la requte dans le programme Java en utilisant limplmentation resultset fournie par le package du driver JDBC embarqu dans Derby et en itrant ensuite sur cet objet (rs.next()). Au sein de cette boucle, vous accdez aux six colonnes de lenregistrement en utilisant la mthode getString applique lobjet resultset. La mthode getString peut accder aux colonnes de la table de deux faons : en utilisant le numro de colonne original dans la requte, par exemple getString(1), ou par getString("articleId"). Nous prconisons lusage explicite des noms de colonnes pour viter tout risque dambigut. La mthode doQuery vrie explicitement dventuels avertissements sur lobjet resultset aprs accs chaque nouvel enregistrement effaant le prcdent ventuellement gnr. Pour invoquer la mthode doQuery, il est ncessaire dtablir au pralable une connexion la base de donnes et dappeler celle-ci au sein dun bloc trycatch, comme dans lextrait de code suivant :
public static void main(String[] args) { Connection con = null ; try { Class.forName(driver) ; con = DriverManager.getConnection(url); SQLWarning swarn = con.getWarnings() ; if(swarn != null){ printSQLWarning(swarn) ; } doQuery(con) ; } catch (SQLException se) { printSQLException(se) ; }
142
en cas de succs lors de lauthentication, transfert du contrle une autre servlet de traitement, LoginSuccess, via lobjet RequestDispatcher ; dploiement/test et dbogage sous Web Tools de lapplication Web dploye. Ces ressources seront ensuite dployes sur un serveur JBoss 4.0 ou JBoss 4.2, dont la conguration avec WTP a t aborde au chapitre 5.
5. Remplacez le contenu situ entre les balises <body> et </body> par le contenu suivant :
<body> <p align="center"> </p>
143
<p align="center"><strong><font size="6" style="BACKGROUND-COLOR: #999999"><IMG alt="" src="WebStore.gif" border="0"> WebStock</font></strong></p> <p align="center"> </p> <p align="center"> </p> <p align="center"><a title="Login" href="http://localhost:8080/LoginServlet/Login.jsp"><font style="BACKGROUND-COLOR: #ffffff"><strong><font size="4"> Bienvenue dans le</font></strong> <strong><font size="4">Systme</font> </strong><strong><font size="4">WebStore</font></strong></font></a></p> <p align="center"> </p> <p align="center"> </p> <hr> <br> <br> <p align="center"><STRONG>(c) Eyrolles <font style="BACKGROUND-COLOR: #ffffff">2005</font></STRONG></p> <p><br> <br> </p> </body>
6. Copiez la gure WebStore.gif dans le rpertoire WebContent. 7. Faites une publication du contenu des ressources vers le serveur JBoss pralablement congur en actionnant longlet Servers, puis slectionnez le serveur JBoss dans le menu contextuel (voir gure 7.2).
Figure 7.2
144
8. Aprs publication avec succs des ressources gurant dans longlet Console, cliquez sur loption du menu contextuel Start pour lancer le serveur JBoss. 9. Slectionnez la page index.html dans la vue explorateur de projet, et excutez votre projet via loption Run As, comme illustr la gure 7.3.
Figure 7.3
10. Lassistant de slection de dnition dun serveur souvre. Slectionnez le serveur que vous avez pralablement dni (ici JBoss 4.2), puis cliquez sur Next (voir gure 7.4).
Figure 7.4
145
11. Votre projet en cours de dnition safche dans la colonne Congured projects. Cliquez sur Finish. Votre page daccueil safche comme illustr la gure 7.5.
Figure 7.5
146
</HEAD> <BODY> <CENTER><BR> <BR> <H2>Login Page</H2> <BR> <BR> Saisissez votre nom et votre mot de passe<BR> <BR> <FORM METHOD=POST ACTION="/WebStock/LoginServletTask"> <TABLE> <TR> <TD>Nom Utilisateur :</TD> <TD><INPUT TYPE=TEXT NAME=userName></TD> </TR> <TR> <TD>Mot De Passe :</TD> <TD><INPUT TYPE=PASSWORD NAME=password></TD> </TR> <TR> <TD ALIGN=RIGHT COLSPAN=2><INPUT TYPE=SUBMIT VALUE=Login></TD> </TR> </TABLE> </FORM> </CENTER> <% out.println("Date courante: " + Calendar.getInstance().getTime()); %> </BODY> </HTML>
6. Pour apprcier les fonctionnalits de compltion de code de Web Tools, positionnez votre curseur sur le dbut de la balise recherche, puis pressez Ctrl+Espace (voir gure 7.6).
Figure 7.6
147
diteur de JSP Vous avez la possibilit de personnaliser lditeur de JSP Web Tools (coloration des commentaires, des lments de scripting, etc.) via le menu Preferences dEclipse en slectionnant Web And XML puis le sous-menu JSP Files.
7. Sauvegardez votre page (Ctrl+S), et dployez-la sur le serveur JBoss comme lors des tapes prcdentes. Votre page doit ressembler celle illustre la gure 7.7.
Figure 7.7
8. Sous le mme dossier, crez votre seconde page JSP LoginSuccess.jsp, qui, en cas de succs de lidentication, routera lutilisateur vers cette page :
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%@ page import="java.util.Calendar"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+": "+request.getServerPort()+path+"/"; %> <HTML> <HEAD> <TITLE>Page d'Identification</TITLE> </HEAD> <BODY> <p> <CENTER> <H2>Connexion russie ! </H2> </CENTER> <p align="center"><STRONG><%= request.getParameter("userName") %><font size="5" style="BACKGROUND-COLOR: #ffffff"></font></STRONG></p>
148
Le rsultat de la page gnre lors dune connexion doit safcher comme illustr la gure 7.8.
Figure 7.8
/** * @author djafaka * * TODO Pour changer le modle de ce commentaire de type gnr, allez : * Fentre - Prfrences - Java - Style de code - Modles de code
149
*/ public class LoginServletTask extends HttpServlet { /** * Constructor of the object. */ public LoginServletTask() { super(); } /** * Destruction of the servlet. <br> */ public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } /** * The doGet method of the servlet. <br> * * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { sendLoginForm(response, false); } private void sendLoginForm(HttpServletResponse response, boolean withErrorMessage) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<HTML>"); out.println("<HEAD>"); out.println("<TITLE>Login</TITLE>"); out.println("</HEAD>"); out.println("<BODY>"); out.println("<CENTER>"); if (withErrorMessage) out.println("Login failed. Please try again.<BR>"); out.println("<BR>"); out.println("<BR><H2>Login Page</H2>"); out.println("<BR>"); out.println("<BR>Please enter your user name and password."); out.println("<BR>");
150
out.println("<BR><FORM METHOD=POST>"); out.println("<TABLE>"); out.println("<TR>"); out.println("<TD>User Name:</TD>"); out.println("<TD><INPUT TYPE=TEXT NAME=userName></TD>"); out.println("</TR>"); out.println("<TR>"); out.println("<TD>Password:</TD>"); out.println("<TD><INPUT TYPE=PASSWORD NAME=password></TD>"); out.println("</TR>"); out.println("<TR>"); out.println("<TD ALIGN=RIGHT COLSPAN=2>"); out.println("<INPUT TYPE=SUBMIT VALUE=Login></TD>"); out.println("</TR>"); out.println("</TABLE>"); out.println("</FORM>"); out.println("</CENTER>"); out.println("</BODY>"); out.println("</HTML>"); }
/** * The doPost method of the servlet. <br> * * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String userName = request.getParameter("userName"); String password = request.getParameter("password"); System.out.println("doPost"+userName); if (login(userName, password)) { RequestDispatcher rd = request.getRequestDispatcher("LoginSuccess.jsp"); rd.forward(request, response); } else { sendLoginForm(response, true); } } boolean login(String userName, String password) { try { Class.forName("org.apache.derby.jdbc.EmbeddedDriver"); Connection con = DriverManager.getConnection("jdbc:derby ","derby",""); System.out.println("got connection"); Statement s = con.createStatement(); String sql = "SELECT USERID FROM webstock.webstockaccess" +
151
" WHERE NomUser='" + userName + "'" + " AND MotDePasse='" + password + "'"; ResultSet rs = s.executeQuery(sql); if (rs.next()) { rs.close(); s.close(); con.close(); return true; } rs.close(); s.close(); con.close(); } catch (ClassNotFoundException e) { System.out.println(e.toString()); } catch (SQLException e) { System.out.println(e.toString()); } catch (Exception e) { System.out.println(e.toString()); } return false; }
/** * Initialization of the servlet. <br> * * @throws ServletException if an error occure */ public void init() throws ServletException { // Put your code here } }
La servlet LoginServletTask essaie de faire correspondre les valeurs saisies dans le formulaire prcdant le login et le mot de passe avec celles des colonnes NomUser et MotDePasse stockes dans la table WebStockAccess. Lorsque lutilisateur saisit dans son navigateur lURL http://localhost:8080/WebStock/ login.jsp et quil clique sur le bouton Login, la mthode doGet est invoque. Celle-ci appelle la mthode prive sendLoginForm, qui envoie la page HTML lutilisateur pour se connecter. Cette dernire mthode possde deux arguments : un objet HttpServletResponse, que la mthode peut utiliser pour envoyer le rsultat au navigateur, et un type boolen, withErrorMessage. Ce boolen est un drapeau qui indique si le message derreur doit tre envoy avec le formulaire. Ce message derreur informe lutilisateur que le prcdent login a chou. Lorsque la servlet est appele pour la premire fois, aucun message nest envoy. Cela explique que la valeur false soit transmise en argument la mthode sendLoginForm (voir lextrait de code prcdant la mthode doGet).
152
Aprs lenvoi du formulaire la servlet via lattribut ACTION="/webstock/LoginServletTask" (voir code de la JSP login.jsp prcdente) et la transmission des paramtres la servlet, la mthode login(userName, password) est appele via la mthode doPost de la servlet. Cette mthode retourne true ou false en fonction du rsultat de la requte dans la base webstock par le biais de la table WebStockAccess. En cas de succs, la requte est transmise une JSP LoginSuccess pour un traitement associ une connexion russie au systme webstock. En cas dchec, la mthode doPost appelle nouveau la mthode sendLoginFom avec un message derreur sendLoginForm (response, true).
Figure 7.9
153
Figure 7.10
Vous utiliserez lassistant de gnration de code fourni par Eclipse pour la gnration de code automatique des getters et setters partir des champs de la classe concerne : par exemple la classe Commande (options de menu contextuel Source et Generate Getters and Setters) illustre la gure 7.11.
Figure 7.11
154
Faites de mme avec les deux autres classes du modle considr, que vous regrouperez pour des raisons de lisibilit et de bonne pratique logicielle dans un package com.webstock.chap07.domain que vous aurez pralablement cr laide de lassistant de cration de package sous Java Resources.
Cration des classes daccs aux donnes selon les design patterns Commande et Singleton
Vous allez crer des classes daccs aux donnes en utilisant le design pattern Commande, qui permet aux programmes et aux objets GUI dtre compltement spars des actions quils initient. Lorsque linterface utilisateur reoit une commande, elle demande lobjet Commande de soccuper de toutes les actions associes, sachant que la rgle fondamentale de ce pattern est de ne pas se soucier des tches qui seront excutes. Linterface du pattern Commande pour la gestion des donnes est la suivante :
package com.webstock.chap07.command; import java.sql.Connection; import java.sql.SQLException; public interface DatabaseCommand { public Object executeDatabaseOperation(Connection conn) throws SQLException ; }
Les classes CRUD (Create/Read/Update/Delete) suivantes implmentent le pattern Commande reprsent par linterface DatabaseCommande pour effectuer les oprations dans la base et insrer les enregistrements dans les tables Commande et Client:
public public public public class class class class CreateClient implements DatabaseCommand CreateCommande implements DatabaseCommand ListClients implements DatabaseCommand ListCommandesClients implements DatabaseCommand
Pour permettre lexcution de vos classes Commande, vous devez crer une classe permettant daccder la source de donnes, obtenir une connexion SQL et excuter une commande daccs aux donnes particulires. Pour ce faire, vous vous aiderez dun second pattern incontournable, le pattern Singleton, qui appellera la classe CommandExecution, garantissant linstanciation un seul objet :
private static CommandExecutor myOnlyInstance = null; public static CommandExecution getInstance() throws NamingException { if (myOnlyInstance == null) { myOnlyInstance = new CommandExecution(); } return myOnlyInstance; }
Lexcution proprement dite dune classe particulire Commande seffectue par le biais de linvocation suivante :
Object o = CommandExecution.getInstance().executeDatabaseCommand ("Instance particulire dun objet commande daccs aux donnes")
155
Pour invoquer lobjet Commande dafchage de la liste des clients, vous aurez, par exemple :
try { ArrayList<Client> list = (ArrayList<Client>)CommandExecution.getInstance() .executeDatabaseCommand(new command.ListClients()); request.setAttribute("clients", list); RequestDispatcher rd = getServletContext().getRequestDispatcher("/clients.jsp"); rd.forward(request, response); } catch (Exception e) { throw new ServletException(e); } }
Laccs la source de donnes seffectue par un lookup du contexte JNDI, comme le montre limplmentation de la mthode getDataSource() suivante, la rfrence cette ressource tant stocke dans le chier de source de donnes associ (voir conguration de la source de donnes du serveur JBoss) :
public DataSource getDataSource() throws NamingException { if (ds == null) { InitialContext ctx = new InitialContext(); Context envCtx = (Context) ctx.lookup("java:comp/env"); ds = (DataSource) envCtx.lookup("jdbc/WebStockDB"); } return ds; }
Lexcution dune commande daccs aux donnes particulires utilise la mthode executeDatabaseCommand():
public Object executeDatabaseCommand(DatabaseCommand c) throws Exception { Connection conn = null; try { conn = getConnection(); Object o = c.executeDatabaseOperation(conn); return o; } catch (SQLException e) { throw e; } catch (NamingException ne) { throw ne; } finally { if (conn != null) conn.close(); } }
prsent que les bases de votre conception Java ont ts implments, vous pouvez passer la mise en uvre en utilisant loutillage Web Tools.
156
Dveloppement des classes CRUD pour les objets mtier Client et Commande
prsent que lossature pour linvocation des mthodes mtier a t dveloppe pour les beans mtier Commande et Client, passez aux oprations CRUD proprement dites sur ces classes. Vous verrez les oprations de cration/afchage des enregistrements associs la classe Client, qui vaut aussi pour lobjet mtier Commande (le code source complet est disponible sur la page Web ddie louvrage). Voici le code de cration et dafchage associ la classe mtier Client:
package com.webstock.chap07.command; import import import import java.sql.Connection; java.sql.PreparedStatement; java.sql.SQLException; com.webstock.chap07.domain.Client;
public class CreateClient implements DatabaseCommand { private Client clt; public CreateClient(Client c) { this.clt = c; } public Object executeDatabaseOperation(Connection conn) throws SQLException { PreparedStatement stmt = conn.prepareStatement("INSERT INTO CLIENT (CLIENTID, USERID, CLIENTNOM, CLIENTPRENOM, ADDRESSE,TEL,COMMENT) VALUES ( ?, ?, ?, ?, ?, ?, ?)"); stmt.setInt(1, clt.getClientId()); stmt.setString (2, clt.getUserId()); stmt.setString (3, clt.getClientNom()); stmt.setString (4, clt.getClientPrenom()); stmt.setString (5, clt.getAdresse()); stmt.setString (6, clt.getTel()); stmt.setString (7, clt.getComment()); int lignes_maj = sta.executeUpdate(); stmt.close(); return new Integer(lignes_maj); } }
package com.webstock.chap07.command; import import import import import import java.sql.Connection; java.sql.SQLException; java.sql.Statement; java.sql.ResultSet; java.util.ArrayList; com.webstock.chap07.domain.Client;
157
public class ListClients implements DatabaseCommand { public Object executeDatabaseOperation(Connection conn) throws SQLException {
ArrayList<Client> list = new ArrayList<Client>(); Statement sta = conn.createStatement(); ResultSet rs = sta.executeQuery("SELECT CLIENTID, CLIENTNOM, CLIENTPRENOM, ADRESSE, TEL, COMMENT FROM CLIENT"); while(rs.next()) { Client clt = new Client(); clt.setClientId(rs.getInt(1)); clt.setClientNom(rs.getString(2)); clt.setClientPrenom(rs.getString(3)); clt.setAdresse(rs.getString(4)); clt.setTel(rs.getString(5)); clt.setComment(rs.getString(6)); list.add(clt); } rs.close(); sta.close(); return list;
} }
Cration des composants servlets et JSP avec les assistants Web Tools
Selon le modle classique MVC (modle, vue, contrleur), vous avez implment la section prcdente la couche modle constitue dobjets du domaine et des classes Commande. La couche contrleur sera implmente sous la forme dun composant servlet et la vue sous la forme de pages JSP. Web Tools fournit un ensemble complet dassistants et dditeurs pour faciliter la gestion des servlets et des JSP. Nous supposons cr un projet Web de type Web dynamique, appell WebStock. 1. Crez un package sous le rpertoire src cr par dfaut, et appelez-le com.webstock.chap07.servlet 2. Lancez lassistant de cration de servlet en slectionnant File, New, Other et Web-Servlet, puis saisissez ListClientsServlet comme nom de servlet. 3. Cliquez sur Next, et spciez une description optionnelle pour la servlet, ainsi que des paramtres dinitialisation ventuels lors du chargement de la servlet (mthode init() de lobjet ServletCong) et le mapping de lURL (/ListClientsServlet par dfaut). 4. Cliquez sur Next.
158
5. cette tape, lassistant propose un certain nombre doptions concernant les interfaces que la servlet peut implmenter (par dfaut, linterface javax.servlet.Servlet) ainsi que les mthodes qui sont automatiquement gnres lors de la cration de la servlet. Cochez la mthode doGet comme illustr la gure 7.12.
Figure 7.12
6. Cliquez sur Finish pour gnrer la servlet. Le code suivant de la servlet est gnr (notez que le chier descripteur web.xml de lapplication Web est automatiquement mis jour) :
<display-name>WebStock</display-name> <servlet> <description>Affichage des clients</description> <display-name>ListClientsServlet</display-name> <servlet-name>ListClientsServlet</servlet-name> <servlet-class> com.webstock.chap06.servlet.ListClientsServlet </servlet-class> </servlet> <servlet-mapping> <servlet-name>ListClientsServlet</servlet-name> <url-pattern>/ListClientsServlet</url-pattern> </servlet-mapping> </web-app>
Terminez par le code associ aux servlets de gestion des clients, respectivement ListClientsServlet pour lafchage des clients et CreateClientServlet pour la cration de
159
linstance client (le code complet pour la gestion des commandes, ListCommandesServlet et CreateCommandeServlet est disponible sur la page Web ddie louvrage) :
package com.webstock.chap07.servlet; import import import import import import java.io.IOException; javax.servlet.ServletException; javax.servlet.http.HttpServletRequest; javax.servlet.http.HttpServletResponse; javax.servlet.RequestDispatcher; java.util.ArrayList;
import com.webstock.chap07.domain.*; import com.webstock.chap07.command.*; /** * Classe dimplementation pour la servlet ListClients * */ public class ListClientsServlet extends javax.servlet.http.HttpServlet { /* (non-Java-doc) * @see javax.servlet.http.HttpServlet#HttpServlet() */ /* (non-Java-doc) * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { ArrayList<Client> list = (ArrayList<Client>)CommandExecution.getInstance() .executeDatabaseCommand(new com.webstock.chap07.command.ListClients()); request.setAttribute("clients", list); RequestDispatcher rd = getServletContext().getRequestDispatcher("/clients.jsp"); rd.forward(request, response); } catch (Exception e) { throw new ServletException(e); } } /* (non-Javadoc) * @see javax.servlet.GenericServlet#init() */ public void init() throws ServletException { // TODO Auto-generated method stub super.init(); try { CommandExecution.getInstance(); } catch (Exception e) { throw new ServletException(e); } } }
160
Comme vous pouvez le remarquer sur ce dernier code, lattribut requte "clients" est positionn un objet gnrique ArrayList et lobjet RequestDispatcher est utilis pour renvoyer la rponse la page JSP clients.jsp. Enn, dans la mthode init() de la servlet ListClientsServlet, une instance de la commande CommandExecution est ajoute an de rcuprer la source de donnes (DerbyDS) et la cacher pour les besoins futurs de gestion des connexions la base WebStockDB.
package com.webstock.chap07.servlet; import java.io.IOException; import java.sql.Timestamp; import import import import import import import import javax.servlet.ServletException; javax.servlet.http.HttpServletRequest; javax.servlet.http.HttpServletResponse; javax.servlet.RequestDispatcher; com.webstock.chap07.command.CommandExecution; com.webstock.chap07.command.DatabaseCommand; com.webstock.chap07.command.CreateClient; com.webstock.chap07.domain.Client;
/** * Servlet implementation class for Servlet: CreateCustomerServlet * */ public class CreateClientServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet { /* (non-Java-doc) * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { // creation du client String prenom = request.getParameter("prenom"); String nom = request.getParameter("nom"); int userid = request.getParameter("userid"); String tel = request.getParameter ("tel"); String adresse = request.getParameter ("adresse"); String comment = request.getParameter("comment"); int clientId = Math.abs((int)System.currentTimeMillis()); Client c = new Client(); c.setClientId(clientId); c.setPrenom (prenom); c.setNom(nom); c.setUserId(userid); c.setAdresse(adresse); c.setTel(tel); c.setComment(comment); DatabaseCommand command = new CreateClient(c);
161
int lignes = (Integer)CommandExecution.getInstance() .executeDatabaseCommand(command); RequestDispatcher rd = getServletContext().getRequestDispatcher ("/client_cree.jsp"); rd.forward(request, response); } catch (Exception e) { throw new ServletException(e); } } /* (non-Javadoc) * @see javax.servlet.GenericServlet#init() */ public void init() throws ServletException { // initialize servlet super.init(); try { CommandExecution.getInstance(); } catch (Exception e) { throw new ServletException(e); } } }
Le code de la page clients.jsp cr par lassistant de cration de page JSP de Web Tools conclut la gestion de lafchage des clients :
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Liste des clients<title> </head><body> <jsp:useBean id="clients" type="java.util.ArrayList<domain.Client>" scope="request"/> <b>Liste des clients enregistrs dans la base WebStock:</b><br> <table border="1"> <tr> <th>Id</th> <th>Nom</th> <th>Prenom</th> <th>Telephone</th> <th>Commentaire</th> </tr> <% for(com.webstock.chap07.domain.Client c : clients) { %> <tr> <td><%= c.getClientId() %></td> <td><%= c.getClientNom() %></td> <td><%= c.getClientPrenom() %></td> <td><%= c.getTel() %></td>
162
<td><%= c.getAdresse %></td> <td><%= c.getComment() %></td> <td><a href="/WebStock/ListCommandes?clientId=<%= c.getClientId() %>">Commandes</a> </td> <% } %> </body> </html>
Remarquez dans ce dernier extrait lutilisation de certaines fonctions de J2SE 5.0, comme lutilisation des gnriques et de la boucle for.
1. Copiez le driver JDBC du SGBD Derby (derby.jar), dans le rpertoire lib de la conguration. 2. Crez un chier derby-ds.xml dans le rpertoire deploy avec la conguration suivante :
<datasources> <local-tx-datasource> <jndi-name>DerbyDS</jndi-name> <connection-url> jdbc:derby:${jboss.server.data.dir}${/}derby${/}WebStockDB;create=true </connection-url> <!-- The driver class --> <driver-class>org.apache.derby.jdbc.EmbeddedDriver</driver-class> <user-name>derby</user-name> <password></password> <min-pool-size>5</min-pool-size> <max-pool-size>20</max-pool-size> <idle-timeout-minutes>5</idle-timeout-minutes> <track-statements/> <depends>jboss:service=Derby</depends> </local-tx-datasource> </datasources>
163
En rsum
Vous avez vu dans ce chapitre que la mise en uvre de loutillage Web Tools pour un dveloppement sans framework particulier exige une certaine rigueur dans la construction de lossature sous-tendant le dveloppement Web. Le chapitre suivant se penche sur Seam, un puissant framework destin complter et faciliter loutillage la disposition du dveloppeur JBoss.
8
Dveloppement Web avec le framework JBoss Seam
Ce chapitre complte loutillage Web Tools avec Seam, un framework Web 2.0 Ready , qui facilite le dveloppement JEE, en particulier pour les applications fondes sur les technologies JSF et EJB3. Aprs un bref rappel de la gense des frameworks JEE et des fondamentaux du framework Seam, vous mettrez en uvre ce dernier sur ltude de cas.
166
Cette approche en couches sappuyait sur les API de base des servlets. Une servlet traite les requtes Web en entre et afche le rsultat sous forme de balises HTML, qui permettent lafchage de pages au sein dun navigateur. Linconvnient de cette approche tait que les balises HTML charges de la prsentation taient mles du code Java, ce qui impactait fortement la maintenabilit de lensemble et ne permettait pas une rpartition efcace des rles au sein de lquipe projet (designer de pages Web et dveloppeurs Java). Est ensuite venue la technologie JSP (JavaServer Pages), qui permet aux dveloppeurs dembarquer des lments dynamiques au sein de pages HTML. Ces lments dynamiques utilisent des balises spciques (directive dimport, de code Java excuter, de rsultats afcher, etc.), ainsi que des variables implicites (request, response, session, etc.). Bien que mieux structure que les servlets, cette approche de dveloppement prsentait plusieurs inconvnients, le principal dentre eux tant le manque de lisibilit du code du fait du mlange du HTML et du Java, do une confusion entre la prsentation et la logique applicative. Le framework Open Source Struts de la fondation Apache est ensuite apparu au dbut des annes 2001. Ddi la conception dapplications Web base de servlets, de JSP et de JavaBeans, ce framework fonctionne schmatiquement comme illustr la gure 8.2.
Figure 8.2
Architecture de Struts
Conformment au modle appel MVC2, Struts sappuie sur une classe principale, la classe org.apache.struts.action.ActionServlet, qui assure le rle de contrleur. Celle-ci est associe toutes les requtes HTTP se terminant par .do via la conguration du chier de mapping associ (balise <servlet-mapping>). En plus de cette classe, un chier de conguration struts-cong.xml contient une liste dURL ddies chacune une action. Pour transfrer les donnes du formulaire laction, Struts utilise une instance drive dActionForm. Le lien entre cette instance, lURL demande et laction est aussi dni dans le chier de conguration Struts. Ct modle, Struts nimpose rien, et aucune classe nest fournie, laissant une totale libert de choix des technologies utiliser pour limplmentation du modle (ce qui est aussi un inconvnient dans la mesure ou aucun standard nest propos pour organiser cette partie du dveloppement). Peu de temps aprs sont apparues les premires implmentations Sun des spcications JSF (JavaServer Faces) JSR-000127. Conues pour le dveloppement rapide dapplications Web, ces spcications proposent une interface graphique riche associe une logique de programmation vnementielle. Pour cela, la norme dnit un cycle normalis de
167
traitement des requtes et fournit une abstraction complte du protocole HTTP. En dcoule une gestion transparente de ltat des composants. En comparaison de JSP, de lAPI servlet et de Struts, qui oblige les dveloppeurs produire beaucoup de code pour grer les aspects prsentation, interaction et ergonomie, les composants JSF prennent en charge automatiquement ces oprations.
168
sont utiles pour afcher les donnes provenant de la couche mtier ou pour la saisie des donnes de lutilisateur. Support de linternationalisation. Toutes ces caractristiques permettent au dveloppeur de se concentrer sur son application et de se dcharger de la gestion rbarbative des pages et des composants graphiques qui la composent.
Vous pouvez constatez que Web Tools propose les implmentations de rfrence de JSF. 3. Cochez cette option, et slectionnez la version 1.2, puis cliquez sur Next. 4. Les champs indiquant le contexte root de lapplication et les rpertoires Web (WebContent) et source (src) sont proposs. Cliquez sur Next.
169
La bote de dialogue suivante de lassistant de cration de projet Web dynamique propose de congurer les bibliothques JSF ainsi que lemplacement des diffrents chiers de conguration JSF du projet. 5. Slectionnez lServer Supplied JSF Implementation, et cliquez sur Finish (voir gure 8.4). 6. Cliquez sur I Agree dans la bote de dialogue de copyright concernant la version des bibliothques JSF utilises.
Figure 8.4
Larborescence typique dun projet Web/JSF est gnre comme illustr la gure 8.5.
Figure 8.5
170
7. Crez votre premire page JSF en slectionnant lassistant de cration de page JSP puis en donnant la page le nom hello.jsp. Cliquez sur Finish. 8. Ajoutez les taglibs JSF dans la page cre en protant des fonctionnalits de compltion automatique de code offertes par Web Tools (voir gure 8.6).
Figure 8.6
Les deux lignes (requises) contenant la balise @taglib sont des directives qui font respectivement rfrence lemplacement des balises JSF qui dnissent les lments de base de JSF ainsi quaux lments HTML de la page. 9. Ajoutez juste au-dessus de la balise <f:view> les lignes suivantes :
<h:outputLabel> rendered="true" value="Nom" </h:outputLabel> <h:inputText tabindex="#{loginBean.nom}"></h:inputText> </f:view>
Ces lignes vont permettre la construction dun formulaire destin transmettre la valeur saisie un backing bean (loginBean) dafchage. 10. Crez la classe com.chap08.jsf.hello suivante laide de lassistant de cration de classe Eclipse :
package com.chap08.jsf.hello; public class LoginBean { String nom; public LoginBean () { super(); } public String getNom() { return nom; }
171
11. Dans lexplorateur de projet, double-cliquez sur le chier de conguration JSF. Lditeur JSF intgr safche comme illustr la gure 8.7.
Figure 8.7
12. Slectionnez longlet ManagedBean, puis cliquez sur Add pour lancer lassistant de cration ManagedBean illustr la gure 8.8.
Figure 8.8
172
13. Slectionnez la classe com.chap08.jsf.hello.loginBean et cliquez sur Next. 14. La bote de dialogue de dialogue de conguration propose de dnir le scope du bean (les scopes possibles sont application, session, request ou none). Slectionnez session, et cliquez sur Finish. 15. Lcran suivant propose ltat de la conguration gnrale du bean ainsi enregistr. Cliquez sur Ctrl+S pour sauvegarder la conguration (voir gure 8.9).
Figure 8.9
La rfrence de ce bean est dnie dans la conguration du chier faces-cong.xml avec lattribut session correctement positionn :
<managed-bean> <managed-bean-name> loginBean</managed-bean-name> <managed-bean-class> com.chap08.jsf.hello.LoginBean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean>
16. Basculez sur la page hello.jsp. 17. Faites un clic droit sur la page, et slectionnez Validate dans le menu contextuel. 18. Ajoutez la balise JSF <h:inputMessage value=#{}></h:inputMessage>, comme illustr la gure 8.10. 19. Slectionnez loginBean dans la liste droulante. 20. Entrez le nom dune proprit, par exemple message, et sauvegardez la conguration.
173
Figure 8.10
21. Ajoutez la rfrence une ressource de type message via le code suivant, juste aprs la balise de n </title> :
<f:loadBundle basemane="com.chap08.jsf.hello.message" var="msg"/>
22. Ajoutez la rfrence au chier properties correspondant en crant, dans le package com.chap08.jsf.hello sous le dossier Java Resources:src, un chier messages.properties contenant les lignes suivantes (destines externaliser les libells utiliss par les pages JSP, ce qui est une bonne habitude prendre) :
nom=Nom login=Login welcome=Bienvenue sur JSF fin=!
Lors de la compilation, ce chier sera copi dans le rpertoire classes du projet et dcouvert par le runtime Eclipse lors de lexcution. 23. Compltez votre page hello.jsp pour quelle intgre au nal les lignes dafchage de la page avec les champs Login ainsi que la rfrence aux libells saisis :
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%> <html>
174
<head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Hello JSF</title> <f:loadBundle basename="com.chap08.jsf.hello.messages.messages" var="msg"/> </head> <body> <f:view> <h:form> <h:messages layout="table"></h:messages> <h:panelGrid columns="2"> <h:outputLabel rendered="true" value="#{msg.nom}"></h:outputLabel> <h:inputText value="#{loginBean.nom}" tabindex="0"></h:inputText> </h:panelGrid> <h:commandButton action="hello" value="#{msg.login}"></h:commandButton> </h:form> </f:view> </body> </html>
Comme vous pouvez le voir dans ce dernier extrait, la balise outputLabel afche un message Nom partir du chier properties cr lors des tapes prcdentes. La ligne contenant la balise commandButton permet de soumettre le formulaire HTML en lui passant lattribut action positionn hello , qui va matcher ce mot-cl dans les sous-balises de la balise principale navigation-outcome.
Conguration de la cinmatique des pages JSF avec lditeur de conguration Web Tools
Vous allez commencer par crer une deuxime page JSP destine afcher un message de bienvenue ainsi qu rcuprer dans la session le login de la personne. Vous utiliserez pour cela lditeur JSF Faces Conguration Resource Editor, qui vous aidera grandement dans la gestion de la cinmatique des pages. 1. laide de lassistant de cration de page JSF, crez la page welcome.jsp suivante :
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Bienvenue</title> <f:loadBundle basename="com.chap08.jsf.hello.messages" var="msg"/>
175
</head> <body> <f:view> < h3> <h:outputLabel value="#{msg.welcome}#{loginBean.nom}"></h:outputLabel> <h:outputLabel value=#msg.fin} /> </h3> </f:view> </body> </html>
2. Crez une troisime page JSP, la page index.jsp suivante associe la balise welcome-le du chier de conguration web.xml an de permettre de router lapplication vers la page hello.jsp :
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> <jsp:forward page="/hello.jsf" /> </body> </html>
Vous allez maintenant congurer la cinmatique des pages JSF avec lditeur de conguration Web Tools. 3. Double-cliquez sur le chier faces-cong.xml pour lancer lditeur de conguration des pages JSF et slectionnez longlet Navigation Rule. 4. Cliquez sur le menu Palette pour faire apparatre lditeur graphique JSF Web Tools illustr la gure 8.11.
Figure 8.11
176
5. Faites un glisser-dpose des pages hello.jsp et welcome.jsp dans lditeur JSF, et reliez-les laide de loption Link de la palette. 6. Slectionnez la ligne et congurez-la via longlet Properties en renseignant les proprits suivantes (voir gure 8.12) : From Outcome : hello. Redirect : false.
Figure 8.12
Vous pouvez voir limpact de cette dnition de la cinmatique du projet helloJSF dans le chier de conguration JSFfaces-cong.xml :
<navigation-rule> <display-name>hello</display-name> <from-view-id>/hello.jsp</from-view-id> <navigation-case> <from-outcome>hello</from-outcome> <to-view-id>/welcome.jsp</to-view-id> </navigation-case> </navigation-rule>
Ce bloc XML dnit les rgles de navigation au sein des pages du projet. La balise <from-view-id> dnit la page initiale avant linvocation de la requte vers le bean manag ; dans votre cas, il sagit de la page hello.jsp. Le listener associ au bean ne dispose que dune option par lintermdiaire de la chane hello retourne : linvocation de la page welcome.jsp dnie dans le chier de conguration JSF ci-dessus.
177
*.jsf est le modle dURL utilis au lieu de faces/* pour signaler que la page redirige dans la page index.jsp doit tre prise en charge par la servlet JSF au sein du conteneur Web de JBoss.
2. Faites une publication complte de votre projet sur le serveur via loption du menu contextuel du serveur Publish, et lancez votre serveur. Cela a pour effet de vous placer automatiquement sur la page hello.jsp, comme lillustre la gure 8.13.
Figure 8.13
3. Cliquez sur le bouton Login. Vous devez voir invoque la page de bienvenue illustre la gure 8.14.
Figure 8.14
Cette section construite autour dun exemple simple vous a permis dapprcier la richesse de la panoplie Web Tools.
178
JBoss Seam
Aprs un rappel de la gense du projet JBoss Seam et de ses caractristiques fondamentales, vous verrez comment congurer Seam au sein de vos projets JEE fonds sur lIDE Eclipse Europa et Web Tools. Les bibliothques associes la version du framework utilise ici gurent sur la page Web ddie louvrage (rpertoire lib). Conu par les quipes R&D des laboratoires JBoss et par lun des concepteurs du framework ORM Hibernate, Gavin King, Seam est un framework pour les applications Web 2.0 qui permet dunier et dintgrer les technologies suivantes : SOA (Service Oriented Architecture), telles quAJAX (Asynchronous JavaScript and XML) ; JSF 1.2 (avec Seam 2.0) ; EJB 3.0 ; portlets Java ; gestion des processus mtier (jBPM) et des workows. Conu avant tout pour liminer la complexit de larchitecture et de linterface de programmation (API), Seam permet aux dveloppeurs dassocier des applications Web complexes des objets Java simples (POJO) annots, des composants graphiques Web et une petite quantit de code XML(voir plus loin la dnition des objets POJO). Pour ce faire, Seam applique le modle de programmation par annotations avec conguration par exception dEJB3 toute la pile dapplications Web. Cela a pour effet de combler lespace entre EJB 3.0 et JSF sur la plate-forme JEE5 (Java Enterprise Edition 5.0). Cette nouvelle version est un modle dunication troitement intgre, qui active les applications avec tat, sans tat, transactionnelles ou fondes sur des processus, telles que les workows et les ux de pages. La simplicit de Seam facilite lintgration avec les ESB (Enterprise Service Bus) et bientt JBI (Java Business Integration), une norme dicte dans la JSR-208 dnissant une approche oriente composant permettant le routage des composants via des messages. En rsum, JBoss Seam est un framework cl en main permettant daffronter les nouveaux standards du Web 2.0 daujourdhui et de demain.
179
Couche de traitement distance fonde sur AJAX. Seam Remoting permet aux beans session EJB3 dtre invoqus directement par le client de navigation Web via la technologie AJAX. Les beans session apparaissent au dveloppeur comme de simples objets JavaScript et masquent la complexit de la srialisation en XML et de lAPI XMLHttpRequest. Gestion dclarative de ltat des applications. Jusqu prsent, les applications Web J2EE implmentaient la gestion des tats manuellement, une approche gnrant bogues et dysfonctionnements de la mmoire lorsque les applications ne parvenaient pas nettoyer les attributs de session. Seam supprime ces dsagrments. La gestion dclarative de ltat sappuie sur le modle de contexte enrichi dni par Seam. Modle de programmation contextuel. Auparavant, une session HTTP tait le seul moyen de grer les tats successifs dune application Web. Seam fournit dsormais plusieurs contextes, avec tats de granularit diffrents, depuis le niveau conversation jusquau niveau processus mtier, librant ainsi les dveloppeurs des contraintes des sessions HTTP. Seam ajoute trois contextes aux nombreux dj existants : Conversation, Process et Application. Le premier permet de dnir et de grer simplement les conversations entre requtes ; le deuxime gre les processus an de dnir des tches et conversations entre eux de manire similaire JBoss jBPM ; le troisime est un contexte disponible durant toute lapplication. Prise en charge des applications base de processus. Seam intgre en toute transparence la gestion des processus mtier via JBoss jBPM, simpliant ainsi radicalement limplmentation des workows complexes et des applications de ux de pages. Intgration de portails. Seam prend en charge les portails compatibles JSR-168, tels que JBoss Portal. Pour toutes ces raisons, Seam reprsente un excellent choix pour le dveloppement dapplications Web utilisant les technologies JSF et EJB 3.0, auxquelles il apporte une parfaite synergie. Les EJB stateless et stateful deviennent ainsi des composants de gestion vnementielle complmentaires de JSF. De plus, les composants JSF peuvent lier leur tat aux beans entit. La gnralisation de techniques telles que linversion de contrle (ou IOC) et les contextes Seam libre le dveloppeur de la gestion manuelle des relations et du cycle de vie au sein des diffrents composants de lapplication. La gure 8.15 illustre larchitecture JEE nale en logique 3-tiers avec le framework JBoss Seam. Seam permet denvelopper les objets POJO, ou classes Java simples , dannotations Java lies la couche prsentation grce des intercepteurs Seam. Cela permet au dveloppeur de se concentrer sur la logique mtier, la prsentation et la couche de donnes sans se soucier de la faon de les lier ensemble et de les faire interagir. Prcisons que le framework Seam fonctionne avec nimporte quel serveur dapplications supportant les EJB 3.0 ( lheure ou nous crivons ces lignes JBoss 4.2.0 GA avec le support EJB3 ou le SA compatible JEE5 Glasssh de Sun). Vous pouvez mme utiliser Seam dans un conteneur de servlets comme Tomcat. La gure 8.16 illustre les composants fondamentaux de larchitecture Seam : JSF pour la partie prsentation, Hibernate (ou JDBC) pour la persistance et les composants JavaBeans pour la logique applicative.
180
Figure 8.15
Mise en uvre de larchitecture 3-tiers pour les application JEE avec Seam
Figure 8.16
181
En rsum, construire une application avec Seam est un processus relativement simple, qui ne ncessite que le codage des composants suivants : Composants mtier, qui reprsentent le modle mtier. Ces objets peuvent tre des beans entit utilisant lAPI de persistance JPA (Java Persistence API) ou des objets POJO avec Hibernate, qui sont automatiquement mapps des tables de la base de donnes. Pages Web JSF pour la prsentation. Les champs de la page sont mapps au modle de donnes via le langage JSF EL (Expression Lanuguage). Beans session EJB3 ou objets POJO annots agissant la faon dun gestionnaire dvnements pour les pages Web JSF et mettant jour le modle en se fondant sur les donnes saisies par lutilisateur.
POJO POJO est lacronyme de Plain Old Java Objects et fait rfrence la simplicit dutilisation des objets Java en comparaison de la lourdeur des composants EJB. Par dnition, un objet POJO (que lon peut traduire par objet Java), nimplmente pas dinterface spcique un framework particulier.
Nous aurons loccasion de revenir sur ces concepts et de les mettre en uvre au cours des chapitres suivants, qui traitent spciquement du dveloppement EJB3 avec Seam et JBoss.
182
Le framework Seam offre une technologie de substitution JSP avec le support du moteur de template Facelets. Les facelets offrent des avantages indniables par rapport JSP, notamment le fait de ne pas dpendre dune balise JSP. Vous pouvez ainsi commencer employer les nouveaux dispositifs de JSF 1.2 sans attendre la disponibilit dune balise de JSP. Fonctionnant avec JSF 1.1 et 1.2, les facelets facilitent la conception des pages en mme temps que leur lisibilit, tout en rduisant la quantit de code ncessaire pour intgrer des composants dans la vue et en nexigeant pas de balises Web. Trs lgre, la technologie Facelet amliore les performances de JSF de 30 50 % en bypassant le moteur de JSP et en utilisant les balises xHTML directement comme composants vue . Enn, et cest important pour le support de la technologie JSF, Facelets fournit un framework de templating pour JSF utilisant le modle Seam dinjection de dpendances pour assembler les pages, au lieu de le faire manuellement, portion de page par portion de page afcher (haut de page ou header, bas de page ou footer et barre de menus).
Seam pour des applications Web POJO
Seam a t conu lorigine pour se placer au-dessus de JEE5 an de servir de pont entre les technologies JSF et EJB3. Toutefois, Seam noblige pas le dveloppeur fonder son architecture sur EJB3. Tout objet POJO avec une annotation @Name peut tre manag par les services du conteneur. Rappelons quun objet POJO nimplmente pas dinterface spcique dun framework, la diffrence dun composant EJB. Il est ds lors possible dutiliser les transactions ou la persistance objet et de scuriser votre application par le biais des frameworks Spring, Hibernate, etc., tout en ne faisant appel qu des objets Java classiques. Lastuce rside dans linjection dune dpendance au sein des paramtres du constructeur dun objet (en particulier par lutilisation des annotations @in et @out, par exemple, qui forment le cur du modle de programmation Seam). Par exemple, vous pouvez dvelopper lobjet POJO manager suivant au lieu dun bean session EJB3 :
@Name("manager") public class ManagerPojo { @In (required=false) @Out (required=false) private Employe employe; // @PersistenceContext (type=EXTENDED) @In (create=true) private EntityManager em;
Lutilisation dobjets POJO pour remplacer les composants EJB3 ne prsente toutefois pas que des avantages. Certes, les objets POJO sont beaucoup plus faciles dvelopper puisquils ne requirent pas dannotations EJB3 ni dinterfaces spciques. De plus, si tous vos composants mtier sont des objets POJO Seam, vous pouvez excuter votre
183
application en dehors du conteneur du serveur dapplications EJB3 (tout conteneur Web compatible, comme Tomcat, est sufsant). Toutefois, un objet POJO dispose de moins de fonctionnalits quun composant EJB3, car il ne peut pas compter sur les services du conteneur EJB3. Citons notamment les limitations suivantes : Linjection @PersistenceContext ne fonctionne pas avec les objets POJO alors quelle est utilise de manire transparente par le conteneur EJB3. Pour obtenir un objet EntityManager avec Seam POJO, il est ncessaire dinitialiser EntityManager dans le chier de conguration Seam et dutiliser lannotation @in pour linjecter dans lobjet POJO. Nous verrons ce point en dtail dans les chapitres suivants. Il nexiste pas de support pour le niveau dclaratif des mthodes transactionnelles en POJO, qui reste du ressort du dveloppeur, contrairement aux beans EJB3 (utilisation de lannotation @TransactionAttribute). Il est donc ncessaire de congurer Seam pour dmarrer une transaction base de donnes lorsque la requte est reue jusqu lafchage de la rponse. Pas de composants POJO de type MDB (message driven bean). Pas de support pour les mthodes asynchrones (@Asynchronous). Pas de support de la scurit gre par le conteneur. En rsum, faire le choix de POJO complexie la conguration mettre en uvre et rduit laccs aux services offerts nativement par le conteneur.
Conguration de Seam avec les composants POJO
Vous allez construire une application POJO en utilisant les API de la spcication JPA (Java Persistence API), fondement de la norme EJB3, qui permet de grer le cycle de vie dun objet persistant. Prcisons que cette API peut tre utilise en dehors dun serveur dapplications, par exemple avec Tomcat en utilisant simplement Java SE. JPA est un composant important de la spcication JEE5, et EJB3 en particulier, et constitue dailleurs un des apports majeurs de cette spcication qui va dans le sens dune plus grande simplicit de mise en uvre des EJB. Votre application utilisera Hibernate JPA comme fournisseur JPA. Lapplication permet de grer une liste demploys selon lapproche POJO en sappuyant sur les API JPA. Comme vous le verrez, lorsque lutilisateur clique sur le bouton du formulaire dajout demploy, Seam cre un composant manag employe. Il invoque alors la mthode updateEmploye() sur le composant Seam manag.
Conguration du projet POJO
Pour dployer une application en dehors dun conteneur EJB3, vous devez congurer Seam de manire quil puisse prendre en charge les services normalement grs par le conteneur. Vous pouvez galement utiliser le gnrateur Seam (seam-gen), qui permet, en slectionnant un type de projet war, de construire la conguration dun projet de type POJO au sein du serveur JBoss, ou simplement rutiliser un modle existant en utilisant un modle de chier de construction build.xml comme celui que nous prsentons cidessous.
184
Une structure de projet Seam/POJO avec JPA se prsente selon la structure monAppSeamPOJO suivante :
| + src | + Sources Java |+ view |+ pages web (.xhtml), css et images |+ resources |+ WEB-INF |+ web.xml | + components.xml | + faces-config.xml | + navigation.xml | + pages.xml |+ jboss-web.xml |+ META-INF |+ persistence.xml |+ seam.properties |+ lib (libraires jar SEAM) |+ App bibliothques spcifiques |+ test |+ build.xml |+ build.properties
Cette structure projet Seam/POJO ncessite la personnalisation des composants suivants : Ajout des composants Seam et des classes ncessaires lapplication dans le rpertoire src. Ajout des pages Web, des images et des autres ressources dans le rpertoire view. Ajout des bibliothques requises sous le rpertoire lib (support des Facelets avec la bibliothque jsf-facelets.jar et du framework Seam comme jboss-seam-ui.jar et jbossseam-debug.jar). Ajout de bibliothques spciques sous le rpertoire lib pour le support, par exemple, de composants AJAX. Cela implique de modier en consquence le chier build.xml si vous souhaitez packager vos jar en dehors du chier app.jar (voir la tche Ant pojar correspondante). Modication du chier navigation.xml sous resources/WEB-INF pour dnir les rgles de navigation entre les pages. Modication du chier resources/WEB-INF/pages.xml pour inclure les paramtres des pages de type restful. Modication du chier resources/META-INF/persistence.xml pour spcier les options personnalises de persistance (type de framework JPA ou hibernate par exemple). Modication des paramtres de conguration de lapplication (changement du nom du projet dans le chier build.xml et modication du chier resources/WEB-INF/jbossweb.xml pour le positionnement du contexte root de lapplication). Le modle de chier build.xml de votre application de gestion des employs avec support JPA est fourni pour examen ci-dessous (il sappuie sur le chier de proprit build.properties contenant la rfrence au serveur dapplications JBoss) :
185
<project name="MonPOJO" default="deploy" basedir="."> <description>Mon projet POJO</description> <property name="projname" value="jpa" /> <property file="build.properties"/> <property name="jboss.deploy" location="${jboss.home}/server/default/deploy"/> <property name="lib" location="../lib" /> <property name="testlib" location="../lib/embeddedejb3" /> <property name="applib" location="lib" /> <path id="lib.classpath"> <fileset dir="${lib}" includes="*.jar"/> <fileset dir="${testlib}" includes="*.jar"/> <fileset dir="${applib}" includes="*.jar"/> </path> <property name="resources" location="resources" /> <property name="src" location="src" /> <property name="test" location="test" /> <property name="view" location="view" /> <property <property <property <property name="build.classes" location="build/classes" /> name="build.jars" location="build/jars" /> name="build.test" location="build/test" /> name="build.testout" location="build/testout" />
<target name="clean"> <delete dir="build"/> </target> <target name="main" depends="compile,pojojar,war"/> <target name="compile"> <mkdir dir="${build.classes}"/> <javac destdir="${build.classes}" classpathref="lib.classpath" debug="true"> <src path="${src}"/> </javac> </target> <target name="test" depends="compile"> <taskdef resource="testngtasks" classpathref="lib.classpath"/> <mkdir dir="${build.test}"/> <javac destdir="${build.test}" debug="true"> <classpath> <path refid="lib.classpath"/> <pathelement location="${build.classes}"/> </classpath>
186
<src path="${test}"/> </javac> <copy todir="${build.test}"> <fileset dir="${build.classes}" includes="**/*.*"/> <fileset dir="${resources}" includes="**/*.*"/> <fileset dir="${testlib}/conf" includes="*.*"/> </copy> <!-- Overwrite the WEB-INF/components.xml --> <copy todir="${build.test}/WEB-INF" overwrite="true"> <fileset dir="${test}" includes="components.xml"/> </copy> <testng outputdir="${build.testout}"> <classpath refid="lib.classpath"/> <classpath path="${build.test}"/> <xmlfileset dir="${test}" includes="testng.xml"/> </testng> </target> <target name="pojojar" depends="compile"> <mkdir dir="${build.jars}"/> <jar destfile="${build.jars}/app.jar"> <fileset dir="${build.classes}"> <include name="**/*.class"/> </fileset> <fileset dir="${resources}"> <include name="seam.properties" /> </fileset> <fileset dir="${applib}"> <include name="*.jar" /> </fileset> <metainf dir="${resources}/META-INF"> <include name="persistence.xml" /> </metainf> </jar> </target> <target name="war" depends="pojojar"> <mkdir dir="${build.jars}"/> <war destfile="${build.jars}/${projname}.war" webxml="${resources}/WEB-INF/web.xml"> <webinf dir="${resources}/WEB-INF"> <include name="faces-config.xml" /> <include name="components.xml" /> <include name="navigation.xml" /> <include name="pages.xml" /> <include name="jboss-web.xml" /> </webinf> <lib dir="${lib}"> <include name="jboss-seam.jar" /> <include name="jboss-seam-ui.jar" /> <include name="jboss-seam-debug.jar" /> <include name="jsf-facelets.jar" />
187
<include name="hibernate3.jar" /> <include name="hibernate-entitymanager.jar" /> <include name="hibernate-annotations.jar" /> <include name="ejb3-persistence.jar" /> </lib> <lib dir="${build.jars}" includes="app.jar"/> <fileset dir="${view}"/> </war> </target> <target name="war421" depends="pojojar"> <mkdir dir="${build.jars}"/> <war destfile="${build.jars}/${projname}.war" webxml="${resources}/WEB-INF/web.xml"> <webinf dir="${resources}/WEB-INF"> <include name="faces-config.xml" /> <include name="components.xml" /> <include name="navigation.xml" /> <include name="pages.xml" /> <include name="jboss-web.xml" /> </webinf> <lib dir="${lib}"> <include name="jboss-seam.jar" /> <include name="jboss-seam-ui.jar" /> <include name="jboss-seam-debug.jar" /> <include name="jsf-facelets.jar" /> <include name="jsf-api.jar" /> <include name="jsf-impl.jar" /> <include name="el-api.jar" /> <include name="el-ri.jar" /> <include name="hibernate3.jar" /> <include name="hibernate-entitymanager.jar" /> <include name="hibernate-annotations.jar" /> <include name="ejb3-persistence.jar" /> </lib> <lib dir="${build.jars}" includes="app.jar"/> <fileset dir="${view}"/> </war> </target> <target name="deploy"> <copy file="${build.jars}/${projname}.war" todir="${jboss.deploy}"/> </target> <target name="undeploy"> <delete file="${jboss.deploy}/${projname}.war"/> </target> </project>
La structure projet complte est disponible sur la page Web ddie louvrage (projet MonPOJO du chapitre 08). Il vous suft de limporter dans Eclipse et de la lancer via loutil Ant intgr dans lIDE.
188
Comme indiqu prcdemment, la diffrence principale entre un projet base dEJB3 et un projet POJO rside dans la manire dont lobjet manager est utilis.
Conception du modle mtier
La mise en uvre dun projet Seam ncessite la conception des objets mtier et de la couche de persistance associe. Selon lapproche POJO, il sagit didentier les objets mtier propres lapplication, soit ici lentit Employe dcrite dans lextrait ci-dessous :
@Entity @name ("employe") @Table(name="employe") public class Employe implements Serializable { private long id; private String name; private long salaire; private String adresse; private String comment; @Id @GenerateValue public Employe () { nomprenom =""; salaire = 0; adresse =""; comment =""; }
Examinez galement le dtail du code de la classe ManagerPojo.java, qui permet de faire le lien entre le bean mtier Employe et la modlisation des processus mtier (gestion des employs). Cette classe prsente un certain nombre de concepts Seam importants en relation avec les annotations @in, @DataModel, @DataModelSelection et @Factory, comme le montre lextrait suivant :
@Name("manager") public class ManagerPojo { @In (required=false) @Out (required=false) private Employe employe; // @PersistenceContext (type=EXTENDED) @In (create=true) private EntityManager em; // @RequestParameter Int pid; public String updateEmploye () { em.persist (employe); return "employes"; }
189
@DataModel private List <Employe> employes; @DataModelSelection private Employe selectedEmploye; @Factory("employes") public void findEmployes () { employes = em.createQuery("select emp from Employe emp") .getResultList(); } public void setPid (Long pid) { this.pid = pid; if (pid != null) { employe = (Employe) em.find(Employe.class, pid); } else { employe = new Employe (); } } public Int getPid () { return pid; } public String delete () { Employe toDelete = em.merge (selectedEmploye); em.remove( toDelete ); findEmployes (); return null; } public String update () { return "employes"; }
Vous devez injecter un objet EntityManager en utilisant lannotation Seam @In. @DataModel vous permet dutiliser une liste dlments slectionnables qui transforment le composant employes en objet DataModel JSF. Notez dans lextrait de la classe ManagerPojo lutilisation de la mthode persist() pour effectuer la persistance de lentit employe. Lors du retour de la mthode persist(), lobjet employe devient un objet entit manag dans le contexte de lobjet EntityManager. Lannotation @DataModelSelection demande Seam quel objet doit tre inject partir de la liste et qui sera slectionn dans la couche de prsentation. Cet objet selectedEmploye peut tre ensuite utilis dans la mthode de suppression delete() et tre appel partir de la page de suppression. Lannotation @Factory entre ensuite en action pour spcier le type dinitialisation du bean listEmployes et rpondre aux besoins de la page JSF pour lafchage des employs (page employes.xhtml).
190
Le processus Seam ddition et de mise jour des employs de la base se droule de la manire suivante : 1. Lutilisateur dclenche une dition de lemploy en cours via linvocation de lURL employe.seam?pid=1 par exemple. 2. La page employe.xhtml est traite, et Seam instancie le composant listEmployes pour afcher les donnes dans la page. 3. Seam injecte la valeur du pid dans lobjet ManagerPojo et appelle la mthode fabrique ManagerPojo.ndEmployes pour construire et jecter le composant listEmployes. 4. La page est afche avec le composant employes.
Le tiers prsentation JSF
Vous pouvez passer la gestion de la partie prsentation, qui va tre charge de lafchage de la liste des employs (page listEmployes.xhmtl) illustre la gure 8.17.
Figure 8.17
Comme vous pouvez le voir, chaque ligne du tableau contient les donnes de la base ainsi quun bouton et un hyperlien (colonne Action). Ce type de tableau est assez difcile construire en pur JSF, car il nexiste pas de moyen naturel dassocier un identiant denregistrement avec une gestion dvnements lie un bouton daction. Le framework Seam permet dimplmenter ce genre de tableau activable sans grande difcult, comme le montre lextrait suivant de la page employes.xhtml :
<h:dataTable value="#{employes}" var="employe"> <h:column> <f:facet name="header">Nom et Prenom</f:facet> #{employe.nomprenom} </h:column> <h:column> <f:facet name="header">Salaire</f:facet> #{fan.salaire} </h:column> <h:column> <f:facet name="header">Adresse</f:facet>
191
#{ employe.adresse} </h:column> <h:column> <f:facet name="header">Comment</f:facet> #{ employe.commentaire} </h:column> <h:column> <f:facet name="header">Action</f:facet> <h:column> <h:commandButton value="Delete" action="#{manager.delete}"/> </h:column> <h:column> <a href="employe.seam?pid=#{ employe.id}">Edition</a> </h:column> </h:column>
</h:dataTable>
Cette page afche la liste des donnes de type employe en utilisant une balise dafchage <h:dataTable> qui itre partir dun objet liste prpar par lannotation @DataModel (voir classe ManagerPojo prcdente). Chaque proprit de lentit mtier Employe est prsente sous forme de colonne dans un tableau. Le bouton Delete fait galement partie du tableau et possde sa mthode de gestion dvnement associe (#{manager.delete}). Le tableau 8.1 rcapitule les annotations associes JSF pour la couche de prsentation.
Tableau 8.1 Annotations associes JSF
Annotation
@DataModel ("nomVariable")
Description
Reprsente la liste des lments. Cette annotation permet lutilisation dobjets
La validation des donnes dun formulaire est une fonction que tout framework se doit de supporter, et Seam ne droge pas la rgle. Dans votre application de gestion des employs, vous devez pouvoir valider les champs de formulaire suivants : Nom et Prnom : saisie uniquement en caractres alphanumriques. Salaire : le montant saisi doit tre non nul et compris entre 1 500 et 3 500 . Comment : champ libre limit 10 caractres.
192
En cas dchec de la validation, la page safche nouveau avec les champs non valides accompagns dun message derreur, comme lillustre la gure 8.18.
Figure 8.18
Seam valide les entres utilisateur ct serveur. Dans une approche totalement JSF, la gestion des diffrentes conditions de validation au sein du formulaire ncessite plusieurs lignes de code, alors quavec Seam, seules quelques annotations et balises JSF sufsent, comme le montre le code de la classe Person.java suivante :
@Id @GeneratedValue public long getId() { return id;} public void setId(long id) { this.id = id; } @NotNull @Pattern(regex="^[a-zA-Z.-]+ [a-zA-Z.-]+", message="Saisir le nom et le prenom") public String getNomPrenom() { return name; } public void setNomPrenom(String name) {this.name = name;} // @Min(value=1500) @Max(value=3500) @NotNull @Range(min=1500, max=3500, message="Le salaire doit etre compris entre 1500 et 3000 _") public long getSalaire() { return salaire; } public void setSalaire(long salaire) { this.salaire = salaire; } @NotNull public String getAdresse () { return adresse; }
193
public void setAdresse (String adresse) { this.adresse = adresse; } @Length(max=10) public String getCommentaire() { return comment; } public void setCommentaire(String comment) { this.comment = comment; } }
Avec Seam, tous les formulaires sont supports par les POJO (ou les beans entit), et les contraintes de validation sont directement annotes dans les champs des POJO, comme ici dans les champs NomPrenom, Salaire, Adresse et Commentaire. Chaque annotation prend en argument un attribut message, qui contient le message afcher dans le formulaire Web si les conditions de validation ne sont pas remplies. Si lattribut message est omis, un message derreur par dfaut est utilis pour le champ annot. Lattribut @Pattern peut matcher le champ saisi nimporte quelle expression rgulire. Le tableau 8.2 rcapitule les annotations disponibles pour la validation des champs de saisie.
Tableau 8.2 Annotations de validation des champs de saisie
Annotation
@Length(max=,min=) @Max(value=)
Description
Sapplique un type de donne chane pour vr ier que la taille de la chane de caractres est bien dans lintervalle de longueur dni. Sapplique une proprit numrique ou une reprsentation chane de caractres dune valeur numrique an de vrier que la valeur de la proprit est plus basse que la valeur Max spcife en paramtre. Sapplique une proprit numrique ou une reprsentation chane de caractres dune valeur numrique an de vrier que la valeur de la proprit est plus grande que la valeur Min spcife en paramtre. Sapplique nimporte quel type de proprit pour vrier que cette proprit est non nulle. Sapplique une proprit de type Date ou Calendar pour vrier si la date est prime. Sapplique une proprit de type Date ou Calendar pour vrier si la date sapplique une date future. Sapplique une proprit de type chane pour vrier si la chane respecte lexpression rgulire en paramtre. Le paramtre ag permet de valider si lexpression respecte ou non la casse. Sapplique une proprit numrique ou une reprsentation chane de caractres dune valeur numrique an de vrier que la valeur de la proprit est comprise dans lintervalle x. Sapplique une proprit de type collection ou tableau pour vrier que le nombre dlments de la proprit est compris dans lintervalle [min,max]. Sapplique une proprit de type chane pour vrier que la valeur de la proprit est sous un format email. Sapplique nimporte quel type de proprit (collection, array ou map). Cette annotation effectue une validation rcursive sur lobjet associ.
@Min(value=)
@Range(max=,min=)
194
Mme si ces annotations couvrent la majorit des besoins de validation des applications Web, Seam offre la possibilit de construire vos propres annotations de validation. Rfrez-vous pour cela la documentation ofcielle du framework.
En rsum
Vous avez achev lexamen de loutillage Web avec Web Tools et dcouvert les fonctionnalits remarquables du framework Seam pour le dveloppement dapplications Web complexes et riches. Vous aborderez la partie III de louvrage ltude et la mise en uvre de loutillage EJB3 avec Eclipe et JBoss.
Partie III
9
Les fondamentaux EJB3
Ce chapitre rappelle la gense de la nouvelle spcication EJB3 et prsente les nombreux avantages de cette norme, voulue comme une simplication radicale de lancienne norme EJB2, juge trop complexe par la communaut des dveloppeurs Java pour les dveloppements courants.
La spcication EJB3
Apparue sous sa version nale en 2006, la spcication EJB3 dispose de nombreux atouts pour redorer un tant soit peu le blason des EJB, terni en grande partie par la complexit de lancienne norme EJB2. Comme nous allons le voir, cette nouvelle mouture a bnci des apports de frameworks tels que Spring et Hibernate et des annotations emmens par le JDK5 pour permettre la communaut des dveloppeurs J2EE/JEE de sen emparer et de ladapter leurs projets.
DEJB1 EJB3
Attendue avec impatience par la communaut Java, EJB3, dont les premires preuves ont paru en 2003, est une tape importante pour la spcication EJB, qui compte dj plus de huit ans dvolutions. Rpondant aux souhaits des dveloppeurs et aux best practices de dveloppement, cette nouvelle spcication a pour premier avantage dcomplexier fortement la prcdente. Rappelons les dates cls qui ont jalonn lvolution de la spcication : Mars 1998 : EJB 1.0 Novembre 1999 : EJB 1.1 Aot 2001 : EJB 2.0 Novembre 2003 : EJB 2.1
198
2005 : EJB 3.0 2006 : phase nale de la spcication EJB 3.0 Dnie par la JSR-220, la spcication EJB3 comporte trois documents distincts : EJB3 simplied API, qui fournit une description globale du nouveau modle de dveloppement EJB3. EJB3 Core Contracts and Requirements, qui se concentre sur les beans de types session et orients message (MDB). Java Persistence API, qui sapplique aux beans entit et aux frameworks de persistance. Le nouveau modle de composants EJB3 dnit toujours les mmes types dobjets : Les beans session, qui excutent les services et oprations mtier et orchestrent les transactions. Il existe deux types de bean session : Les beans session stateless (sans tat), qui ont une dure de vie limit et qui se limitent linvocation de la mthode et la rcupration de son rsultat (exemple : une classe MailSender charge de lenvoi de messages). Les beans session stateful (avec tat), qui permettent la conservation de ltat transactionnel (exemple : caddy virtuel). Les beans MDB, qui sont invoqus de manire asynchrone et rpondent aux vnements extrieurs par le biais dune le de messages (exemple : un bean charg de la commande darticles un centre de gestion des commandes). Les beans entit, qui disposent dun unique identiant et reprsentent les donnes persistantes du modle mtier. Ils peuvent tre utiliss pour mapper une entre dans la table de la base avec une classe Java (mapping objet-relationnel), le serveur dapplications fournissant les fonctionnalits pour charger, mettre jour et supprimer les valeurs de linstance de classe dans la base. La diffrence fondamentale entre EJB2 et EJB3 tient ce que les beans entit sont dsormais grs par un fournisseur de persistance particulier (TopLink, Hibernate, etc.), et non plus par le conteneur. Ils ne sont donc plus considrs comme de vrais beans dentreprise. Cette volont de sparer les services de persistance du conteneur est la rponse au reproche fait EJB2 de ne rendre utilisables les couches implmentes avec des EJB quau sein de conteneurs EJB, rendant problmatiques les tests unitaires. Concernant enn la persistance, EJB3 propose un nouveau modle de persistance, Java Persistence API, totalement inspir dHibernate. La spcication JEE5, qui intgre EJB3, prend la suite de J2EE 1.4 (notez labandon du 2 de J2EE, qui faisait rfrence au JDK 1.2). La version qui succde J2SE 5.0 se nomme Java SE 6, ou JSE6. Lobjectif de JEE5 est avant tout de simplier le dveloppement des applications Java dentreprise. Elle intgre bon nombre de fonctionnalits EJB3, telles que les annotations, la programmation de POJO (Plain Old Java Objects), linjection de dpendances, de nouvelles API, de nouveaux frameworks, etc. Les points forts de cette rvolution du modle EJB sont dtaills la section suivante, ainsi que dans les diffrents chapitres suivants.
199
EJB3 apporte une simplication des dveloppements grce aux annotations, une nouvelle fonctionnalit du langage Java 5.0 en lieu et place des descripteurs de dploiement. Les annotations sont des mtadonnes qui permettent certains outils de gnrer des constructions additionnelles la compilation ou lexcution ou encore de renforcer un comportement voulu au moment de lexcution (comme la nature sans tat dun composant EJB). Les annotations simplient considrablement lcriture des programmes, comme nous lavons vu au chapitre prcdent avec Seam. Les annotations permettent dattacher des informations additionnelles (couramment appeles attributs) aux classes Java et aux interfaces, ainsi quaux mthodes et aux variables qui les composent. Ces informations additionnelles apportes par les annotations peuvent tre assimiles des interfaces. Elles peuvent tre utilises dans un environnement de dveloppement tel quEclipse ou WebTools, voire Dali, comme nous le verrons au chapitre 11, et par les diffrents assistants de dploiement du conteneur JEE. Elles rendent ainsi caduques les descripteurs de dploiement de la norme EJB2 tels que ejb-jar.xml. La gure 9.1 illustre la complmentarit entre POJO et annotations.
Figure 9.1
Le chier persistence.xml fournit un mcanisme puissant et simple pour la persistance des beans entit, appele unit de persistance. En voici un exemple simple :
<persistence> <persistence-unit name="WebStockDB"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <jta-data-source>java:/WebStockDBDS</jta-data-source> <properties> <property name="hibernate.hbm2ddl.auto" value="update"/> </properties> </persistence-unit> </persistence>
Ce chier dnit le fournisseur de la source de donnes (ici le fournisseur Hibernate, adapt au conteneur JBoss). Nous dcrivons galement dans ce chier le nom de la
200
source de donnes dnie par JBoss, ou nom JNDI, qui va tre utilise pour linvoquer travers le client laide de la proprit jta-data-source. La balise <properties> comporte des proprits additionnelles, comme le fait de gnrer automatiquement le schma de la base en fonction du bean entit fourni. La valeur "update" de la proprit "hibernate.hbm2ddl.auto" indique que nous souhaitons quHibernate cre la structure de donnes automatiquement et la mette jour si ncessaire (voir la documentation en ligne http://www.hibernate.org/hib_docs/reference/en/html/tutorial.html).
Tout composant dune application utilise un tant soit peu les services dun autre composant pour rpondre ses besoins. Le principal objectif du concept dinjection de dpendances, ou DI (Dependency Injection), est de rendre les dpendances entre composants les plus tnus possibles. Cela signie que si un composant a besoin des fonctions dun autre composant ou dun gestionnaire de ressources, il doit pouvoir le faire travers une interface et en utilisant un chier de conguration adapt, au lieu dcrire du code. Cela favorise videmment la exibilit de lensemble de lapplication. Ce concept, popularis par le framework Spring et incarn par le principe dHollywood ne nous appelez pas, nous vous appellerons , permet de dcharger le dveloppeur Java de linstanciation des objets de lapplication et de la rsolution des dpendances entre eux. La gure 9.2 illustre le schma de principe de linjection de dpendances. La responsabilit du conteneur est dinjecter lobjet en se fondant sur sa dclaration, linverse, par exemple, dun lookup JNDI classique, qui ncessite que le bean fasse le travail de recherche des ressources et des beans ncessaires.
Figure 9.2
Lexemple suivant illustre lutilisation de ce principe par le biais de lannotation javax.annotation.Resource qui sapplique aux ressources de type source de donne, objets JMS, etc. Le bean dlgue au conteneur linstanciation du contexte monContexte
201
ainsi que de la datasource maBD, vitant les fastidieux lookups JNDI bien connus des dveloppeurs EJB2 :
@Resource(name="maBD", type=javax.sql.DataSource) @Stateful public class ShoppingCartBean implements ShoppingCart { @Resource SessionContext monContexte; public Collection startToShop (String prodNom) { ... DataSource prodNom = (DataSource)monContexte.lookup("maBD"); Connection conn = maBD.getConnection(): ... } ... }
Dsormais, dans JEE5, les entits persistantes sont de simples JavaBeans, les fameux POJO, dclars laide dune annotation @Entity. Dveloppe sous les auspices du JSR-220, la nouvelle spcication EJB 3.0 se veut moins acadmique que lancienne et sinspire des meilleures ides qui ont merg dans diffrents contextes : le framework Open Source Hibernate 3.0, les spcications JDO 2.0 de la JSR-243 ou des solutions commerciales comme TopLink. En contraste avec les EJB 2.x, la nouvelle API de persistance est utilisable aussi bien dans un contexte dit manag , cest--dire au sein dun serveur dapplications, que dans une application J2SE autonome.
Support des intercepteurs
EJB 3.0 intgre une approche POA (programmation oriente aspect) en introduisant la notion dintercepteur : cest une mthode qui intercepte linvocation dune mthode mtier sur un EJB session ou MDB. EJB 3.0 propose mme dassocier un EJB session une liste de classes Interceptors dont les mthodes intercepteront les invocations aux mthodes mtier de cet EJB.
Synthse des frameworks succs
Toutes ces nouveauts, qui vont vers une plus grande simplicit du modle EJB, ont dj t anticipes par des frameworks tels que Spring et Hibernate. Cest en ce sens que nous pouvons afrmer quun projet dmarr avec la technologie EJB3 bncie dassises et de ressources solides. lheure dcrire ces lignes, quelques serveurs Open Source et commerciaux supportent dj la norme JEE5 : JBoss 5 (version bta ; la version stable 4.2 supporte dj EJB3), qui sert de cadre cet ouvrage (www.jboss.com). Geronimo 2.0.1, sorti en aot 2007, de la fondation Apache (http://geronimo.apache.org).
202
Glasssh, implmentation de rfrence de Sun des spcications JEE5, qui supporte les derniers standards technologiques : JSP 2.1, JSF 1 .2, Servlet 2.5EJB 3.0, JAXWS 2.0, JAXB 2.0, Web Services Metadata for the Java Platform 1.0, (https://glasssh.dev.java.net/). BEA WebLogic 10, premier serveur commercial supportant JEE5. Curieusement, IBM ne semble pas press de sortir une version concurrente supportant EJB3. Attendons les prochaines annonces pour en savoir plus, notamment avec la version 7 du serveur WebSphere, attendue avec impatience lheure ou nous mettons sous presse.
Typiquement, un bean session est utilis pour : Modliser un traitement dont ltat ne sera pas rendu persistant et pour une dure dtermine. Modliser un traitement de gestion des employs dune socit en leur affectant un service et un prol didentication dans le systme cible en liaison avec un annuaire. Crer un bordereau de commande pour un client du systme. Grer et orchestrer les mthodes dites CRUD (cration, lecture, mise jour, suppression) sur une entit du modle mtier.
Avantages
Voici quelques-uns des avantages offerts par les beans session : Amlioration des services du serveur dapplications en apportant des fonctionnalits volues de gestion transactionnelle. Aide aux besoins de dploiement du client lorsque que lapplication cliente nest pas localise dans le mme serveur.
203
Pour crer un bean session sans tat en utilisant la spcication EJB3, il suft dutiliser lannotation @Stateless applique la classe, comme dans lexemple suivant :
package com.eyrolles.chap09.exempleSession ; public interface CalculSalaire { public final static double tauxHoraire = 7 ; public double getSalaire(int nbreHeures) ; } package com.eyrolles.chap09.exempleSession ; import javax.ejb.Local ; @Local public interface CalculSalaireLocal extends CalculSalaire {} import javax.ejb.Stateless; @Stateless public class CalculSalaireBean implements CalculSalaireLocal { public CalculSalaireBean() {} public double getSalaire(int nbreHeures) { return nbreHeures*tauxHoraire ; } }
La classe CalculSalaireBean (remarquez lextension Bean aprs le nom de la classe, qui est une convention de nommage bien pratique) nutilise pas dinterface particulire, comme javax.ejb.SessionBean, ni dinterface EJBHome ou EJBObject, si familires de gnrations de dveloppeurs EJB2.
204
Nous utilisons ici une interface locale spcie par lannotation @Local, CalculSalaireLocal, et le bean session sans tat CalculSalaireBean qui limplmente. Rappelons que lutilisation dune interface locale prcise avec lannotation @Local (optionnelle, mais utile) spcie que les mthodes qui sont dnies ici sont disponibles uniquement pour les clients qui ont invoqu cet EJB au sein du mme conteneur JEE, cette interface locale tant quivalente linterface locale utilise avec EJB2. linverse, il existe, comme en EJB2, une interface distante spcie par lannotation @Remote (annotation obligatoire). Cette interface est toutefois utiliser avec modration pour des raisons de performance, du fait du passage des paramtres par valeur et non par rfrence via RMI/IIOP entre les diffrentes machines virtuelles. Voici le code correspondant la dnition dune interface distante (Remote) quune simple annotation @Remote suft utiliser :
package com.eyrolles.chap09.exempleSession ; import javax.ejb.Remote ; @Remote public interface CalculSalaireRemote extends CalculSalaire {} package com.eyrolles.chap09exempleSession ; import javax.ejb.Stateless ; @Stateless public class CalculSalaireBean implements CalculSalaireRemote { public CalculSalaireBean() {} public double getSalaire(int nbreHeures) { return nbreHeures*tauxHoraire ; } }
Il est possible de rendre le bean CalculeSalaireBean accessible distance et localement avec les mmes fonctions et via la mme interface en modiant la signature du bean de la manire suivante :
@Stateless public class CalculSalaireBean implements CalculSalaireRemote,CalculSalaireLocal { public CalculSalaireBean() {} public double getSalaire(int nbreHeures) { return nbreHeures*tauxHoraire ; } }
Si le bean nimplmente aucune interface (dconseill), une interface mtier locale est gnre automatiquement par le conteneur. Elle prend le nom de la classe moins le sufxe Bean ou Impl en fonction de la convention de nommage utilise. Lexception leve par le conteneur RemoteException nest plus ncessaire ici, laccs distant tant compltement encapsul. Cest encore un des aspects de la simplication de la norme EJB3.
205
Une application cliente qui accde aux beans session hbergs dans un conteneur dapplications peut tre de trois types : Distante : les clients de lapplication sexcutent dans une JVM spare du bean session auquel ils accdent (voir gure 9.3). Un client distant accde au bean session travers une interface mtier distante. Un client distant peut tre un autre bean, un programme Java client ou simplement une servlet. Le principal avantage de lutilisation dune interface distante est lindpendance de la localisation des traitements. Cela se paye en contrepartie de moins bonnes performances en termes dinvocation de mthodes distantes et de la ncessit de srialiser les objets et de les passer par valeur. Locale : les clients locaux sexcutent dans la mme JVM (voir gure 9.4). Un client local peut tre un autre bean ou une application Web utilisant des servlets et des JSP/JSF. Ce type dinterface est dite location dependant. Web Service : vous pouvez publier un bean session sous forme de service Web. Ce dernier peut tre invoqu partir dun client de service Web.
Figure 9.3
Figure 9.4
Client Web accdant aux mthodes dun bean session via une interface locale
206
Le choix dun type dinterface est dtermin par les contraintes de lapplication. En rgle gnrale, une application de type client Web qui sexcute au sein de la mme JVM et qui invoque les services dun bean utilise une interface locale. linverse, un client Java riche, de type Eclipse RCP par exemple, utilise une interface distante pour invoquer ses mthodes distantes. Selon les cas, il est conseill dutiliser des interfaces mtier la fois locale et distante an que celles-ci puissent supporter les diffrents types de clients dapplication. Un client peut obtenir une interface mtier du bean session en utilisant linjection de dpendances ou par un lookup JNDI classique. En utilisant linjection de dpendances avec lannotation @EJB, vous pouvez, par exemple, obtenir une interface mtier sur le bean session SearchFacade en utilisant le code suivant :
public class SearchFacadeClientIOC { @EJB SearchFacade searchFacade; public static void main(String[] args) { SearchFacadeClientIOC SearchFacadeClientIOC = new SearchFacadeClientIOC(args); SearchFacadeClientIOC.doTest(); } public SearchFacadeClientIOC(String[] args) { } public void doTest() { InitialContext ic; try { ic = new InitialContext(); List articlesList = searchFacade.articleSearch("Disque Dur"); for (String article: (List<String>)articlesList) { System.out.println(article); } } catch (Exception e) { e.printStackTrace(); } }
Le serveur dapplications contrle entirement le cycle de vie des composants EJB dploys en gardant au besoin un pool de beans sans tat disponible, lapplication nayant aucun contrle sur linitialisation du bean.
207
La mthode create(), bien connue des dveloppeurs EJB2 qui est, rappelons-le, une mthode de fabrique utilise par les clients pour obtenir une rfrence un objet EJB , nexiste plus en EJB3. Elle est remplace par les annotations, comme le montre lextrait suivant :
import javax.ejb.Stateless; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; @Stateless public class CalculSalaireBean implements CalculSalaireLocal { @PostConstruct public void init() { // invoque toutes methodes ou composants necessaires lors de la creation du bean } @PreDestroy public void recycle() { // invoque toutes methodes ou composants necessaires lors de la destruction du bean } }
La nouveaut dans ce mcanisme est son caractre optionnel. En EJB2, le dveloppeur tait forc dcrire ces mthodes, mme si elles ntaient pas implmentes par la suite. La spcication EJB3 se sert des annotations pour dnir des mthodes de callback. Une mthode de callback peut tre nimporte quelle mthode dnie dans un bean session qui possde une annotation de callback. Le conteneur EJB appelle cette mthode des moments dtermins du cycle de vie du bean. Par exemple, la mthode de callback init() associe lannotation @PostConstruct intervient aprs toutes les injections de dpendances effectues par le conteneur et avant le premier appel de la mthode mtier. La mthode de callback associe lannotation @PreDestroy est appele au moment o linstance du bean est dtruite.
Intercepteurs
La spcication EJB3 fournit des annotations particulires, appeles intercepteurs ( opposer aux mthodes de callback, mme si le principe est assez proche), qui permettent dintercepter linvocation de mthodes mtier. Une mthode intercepteur peut tre dnie pour un bean session ou un bean orient message (MDB). Son utilisation peut se justier dans des situations trs particulires, dans lesquelles il est ncessaire deffectuer certains contrles, comme par exemple des contrles de scurit prliminaires avant une opration de transfert sur un compte. La mise en uvre dun intercepteur seffectue laide de lannotation @AroundInvoke applique une mthode particulire. Vous pouvez galement dnir une classe intercepteur dont les mthodes sont appeles avant quune mthode mtier soit invoque sur la classe du bean. Une classe intercepteur est dnie par lannotation @Interceptor sur la classe du bean laquelle elle est associe. Cette annotation sutilise lorsque plusieurs classes intercepteur sont dnies.
208
Les mthodes intercepteur associes lannotation @AroundInvoke doivent possder la signature suivante :
public Object <NOM_METHODE>( javax.ejb.InvocationContext ctx) throws java.lang.Exception
Ajoutons que vous pouvez dnir une mthode intercepteur au sein du bean lui-mme, ou dans une classe spare, sachant quil ne peut exister quune mthode intercepteur par classe. Lexemple qui suit montre une mthode intercepteur dnie dans la classe du bean EmailSystemBean et au niveau de la classe grce lannotation @Interceptors :
@Stateless @Interceptors ({TracingIntercepteur.class}) @Remote(EmailSystem.class) public class EmailSystemBean implements EmailSystem { @Interceptors({AccountsConfirmIntercepteur.class}) public void sendBookingConfirmationMessage(long orderId) { System.out.println("<Dans EmailSystemBean.sendBookingConfirmationMessage methode metier"); String email = "xyz@blabla.com"; sendMessage(email, "Enregistrement Confirme", "Votre commande " + orderId + "est confirmee !"); System.out.println("Sortie methode metier EmailSystemBean .sendBookingConfirmationMessage >"); } @AroundInvoke public Object monBeanIntercepteur(InvocationContext ctx) throws Exception { if (ctx.getMethod().getName().equals("emailLostPassword")) { System.out.println("*** EmailSystemBean.monBeanIntercepteur Nom : " + ctx.getParameters()[0]); } return ctx.proceed(); } // . . . }
public class AccountsConfirmInterceptor extends AccountsInterceptor { @Resource(mappedName="java:ConnectionFactory") QueueConnectionFactory cf; @Resource(mappedName="queue/tutorial/accounts") Queue queue; @PersistenceContext EntityManager em; QueueConnection conn;
209
Il peut exister dans une application un scnario dans lequel un bean session avec tat cache ses modications avant de les stocker dans la base de donnes. Par exemple, le bean ShoppingCartBean ne peut dcider de sauvegarder dans la base les articles accumuls dans le cache de donnes quaprs notication du conteneur EJB, en particulier lors dune notication afterCompletion. Cela seffectue par le biais de linterface javax.ejb.SessionSynchronization, qui permet de mettre en place les trois types de notications suivants par le conteneur : afterBegin : indique quune nouvelle transaction t initialise. beforeCompletion : indique que la transaction est sur le point dtre commite en base. afterCompletion : indique que la transaction a t commite. Linterface SessionSynchronization est dnie comme suit :
package javax.ejb; public interface javax.ejb.SessionSynchronization { public abstract void afterBegin( ) throws RemoteException; public abstract void beforeCompletion( ) throws RemoteException; public abstract void afterCompletion(boolean committed) throws RemoteException; }
La mthode afterCompletion() est toujours invoque, que la transaction se soit bien droule lors dun commit ou non lors dun rollback. Si la transaction a bien t acheve, ce qui signie que beforeCompletion() a t invoque, le paramtre committed de la mthode afterCompletion() est gal true ; si elle a chou, il est gal false.
Pour crer un bean session avec tat, il suft de lannoter avec @Stateful. Lextrait de code suivant cre le bean avec tat ShoppingCartBean, un exemple classique de caddy virtuel ( noter la proprit name pour le dsigner) :
package com.webstock.chap09.stateful; import javax.ejb.Remove;
210
import javax.ejb.Stateful; import com.webstock.chap09.service.ShoppingCart; @Stateful(name=ShoppingCart) public class ShoppingCartBean implements ShoppingCart, ShoppingCartLocal { // ... @PostConstruct public void initialize() { cartItems = new ArrayList(); } @PreDestroy public void exit() { System.out.println("Saved items list into database"); } @Remove public void purchase() { // persiste larticle dans la base } }
Ce code ne prsente pas de difcult particulire. Lannotation @Remove associe la mthode de callback purchase() a t ajoute an de spcier au conteneur quand librer le bean pour sa rutilisation ventuelle. Lorsque cette mthode est excute, le bean envoie un signal au conteneur, lequel pourra le recycler ultrieurement. Il est possible davoir plusieurs mthodes associes Remove, mais vous devez au moins en avoir une prcde de lannotation @Remove. Les beans session stateful supportent les vnements de callback pour la construction, la destruction, lactivation et la passivation. La gure 9.5 illustre les tats associs un bean session avec tat.
Figure 9.5
211
Type de bean
Stateful
Annotation
@Init
Description
Dsigne les mthodes dinitialisation pour le bean session avec tat. La mthode @PostConstruct est appele aprs la mthode @Init. Invoque la mthode de callback associe juste aprs quune nouvelle instance dun bean a t cre par le conteneur. La mthode de callback associe sexcute lors de linstanciation par le conteneur du bean. Exemple :
PreConstruct
Stateless et stateful
@PreConstruct
PostConstruct
Stateless et stateful
@PostConstruct
@Stateful public class ShoppingCartBean implements ShoppingCart { private float total; private Vector productCodes; public int someShoppingMethod(){...}; ... @PreDestroy endShoppingCart() {...}; }
PreActivate Stateful @PreActivate Signale que linstance vient juste dtre ractive par le conteneur. Son objectif est de permettre des beans session avec tat de maintenir les ressources ncessitant dtre ralloues durant lactivation de linstance. Exemple :
@Stateful public class MystatefulBean { ... @PreActivate public void passivate() { // open socket connections, ... } }
212
Dveloppement EJB3 avec Eclipse et Web Tools PARTIE III Tableau 9.1 vnements de callback des beans session (suite)
vnement de callback
PrePassivate
Type de bean
Stateful
Annotation
@PrePassivate
Description
Invoque juste avant que le bean passe ltat inactif et stocke son tat dans le cache. Exemple :
@Stateful public class MystatefulBean { ... @PrePassivate public void passivate() { // close socket connections, ... } }
Remove Stateful @Remove Lorsque la mthode associe lannotation @Remove est appele, le conteneur supprime linstance du bean du pool aprs que la mthode sest excute. Exemple :
@Remove public void stopSession() { //Corps de la methode pouvant etre vide System.out.println("Appel de la methode stopSession avec lannotation @Remove"); }
AroundInvoke Stateless et stateful @AroundInvoke Mise en uvre des mthodes intercepteur.
Les fondamentaux EJB3 CHAPITRE 9 Tableau 9.2 Principales diffrences entre EJB2 et EJB3 (suite)
Bean session EJB2 Bean session EJB3 Descripteur de dploiement
Fichier descripteur ejb-jar.xml requis Les descripteurs de dploiempent sont optionnels. Utilisation du chier de persistance persistence.xml requis. Fichier orm.xml optionnel.
213
214
Timestamp sent = new Timestamp(tmsg.getLongProperty("sent")); StringTokenizer st = new StringTokenizer(tmsg.getText(), ","); int start = Integer.parseInt(st.nextToken()); int end = Integer.parseInt(st.nextToken()); double growthrate = Double.parseDouble(st.nextToken()); double saving = Double.parseDouble(st.nextToken()); double result = calculate (start, end, growthrate, saving); RecordManager.addRecord (sent, result); } catch (Exception e) { e.printStackTrace (); } } // ... ... }
Voici le dtail des nouvelles annotations : @MessageDriven : dclare un bean message partir de sa classe. @ActivationCongProperty : propertyName : nom de la proprit. propertyValue : valeur de la proprit affecter. EJB : injection automatique lie un EJB (instanciation automatique). Dans lextrait de code ci-dessus, vous dnissez la conguration du bean MDB via lannotation @ActivationCongProperty (dnition du type et du nom de la le dattente de destination). Pour tre complet, voici le code du client. La JSP calculator.jsp utilise lAPI standard JMS pour obtenir la le de message cible du bean MDB en utilisant le nom de la le (queue/mdb) et envoyer ensuite le message la le :
<%@pageimport="com.test.mdb.*,javax.naming.*,java.text.*, javax.jms.*, java.sql.Timestamp"%> <% try { InitialContext ctx = new InitialContext(); queue = (Queue) ctx.lookup("queue/mdb"); QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup("ConnectionFactory"); cnn = factory.createQueueConnection(); sess = cnn.createQueueSession(false,QueueSession.AUTO_ACKNOWLEDGE); } catch (Exception e) { e.printStackTrace (); }
215
TextMessage msg = sess.createTextMessage( request.getParameter ("start") + "," + request.getParameter ("end") + "," + request.getParameter ("growthrate") + "," + request.getParameter ("saving") ); sender = sess.createSender(queue); sender.send(msg); %>
Prrequis et conguration
Nous supposons dj congurs une version dEclipse 3.3 avec le serveur JBoss 4.2 et le JDK5. Pour linstallation de loutillage Eclipse et des sous-projets associs Web Tools et Dali, nous vous conseillons dutiliser une version bundle, directement installable et prcongure pour un support JEE. Plusieurs diteurs proposent ce type de version, notamment Yoxos (http://www.yoxos.com). Vous allez commencer par dclarer le serveur JBoss Web Tools : 1. Ouvrez la page Preferences dEclipse, puis choisissez Server et Installed Server Runtime Environment. 2. Cliquez sur Add. 3. Dans la liste propose, slectionnez JBoss 4.2, puis cliquez sur Next. 4. Spciez les valeurs correspondant votre environnement (JRE compatible JDK5 et rpertoire dinstallation du serveur JBoss 4.2, par exemple C:/jboss-4.2.1.GA). 5. Cliquez sur Finish puis sur OK pour terminer la conguration du serveur. 6. Pour congurer le serveur JBoss ainsi dni, ouvrez la vue Servers. 7. Faites un clic droit dans la vue Servers, et choisissez New Server dans le menu contextuel. 8. La bote de dialogue de conguration du serveur JBoss souvre alors. Laissez les champs Servers Host Name et server runtime leur valeur par dfaut (respectivement localhost et JBoss 4.2). Cliquez sur Next.
216
9. Lcran de lassistant de conguration du serveur JBoss vous propose ladresse IP du serveur et les ports dcoute http, JNDI et de la conguration du serveur (respectivement 127.0.0.1, 8080,1099 et default). Cliquez sur Finish, terminant ainsi la conguration du serveur JBoss.
Figure 9.6
10. Dmarrez votre serveur en le slectionnant par clic droit et en choisissant Start dans le menu contextuel.
1. Ouvrez lassistant de cration de projet Eclipse via File, New et Other. 2. Slectionnez le type de projet EJB, puis cliquez sur Next. 3. Saisissez le nom de votre projet, par exemple MonProjetEJB, et laissez les autres champs inchangs (voir gure 9.7).
Figure 9.7
217
4. Cliquez sur Next. La bote de dialogue illustre la gure 9.8 afche les facets associes. Remarquez le support dEJB 3.0, Java 5.0 et JPA, contrairement la version JBoss 4.0, qui ne supporte pas nativement le conteneur EJB3. Le support de XDoclet est toujours propos pour des raisons de compatibilit avec J2EE 1.4, mais nest plus conseill pour un dveloppement JEE5.
Figure 9.8
5. Cliquez sur Finish. La structure de votre projet J2EE est cre. Contrairement aux versions antrieures de JBoss, le chemin de compilation du projet fait dsormais rfrence aux bibliothques de support EJB3, comme ejb3-persistence.jar, jboss-ejb3.jar, jboss-ejb3x.jar.
Dveloppement dun bean session sans tat
Le dveloppement dun bean session EJB3 sans tat comporte les tapes cls suivantes : 1. Dnition de linterface du composant. Crez une interface sous le package com.eyrolles.chapitre09 (sous le module ejbModule dj gnr) et contenant le code suivant :
package com.eyrolles.chapter09; import java.util.List; import javax.ejb.Remote; @Remote public interface SearchFacade { List articlesSearch(String articleType); }
218
2. Implmentez le composant en crant la classe SearchFacadeBean. Les mthodes implmentes dans le bean doivent correspondre aux mthodes mtier dclares dans linterface distante ou locale. Les autres mthodes qui ne possdent pas dquivalent au niveau de linterface mtier restent prives aux mthodes du bean. Voici le code du bean SearchFacadeBean contenant une mthode articleSearch() qui a t dclare dans linterface mtier locale et distante, celle-ci retournant une liste statique darticles bass sur la catgorie de larticle :
import import import import import import import import java.util.ArrayList; java.util.HashMap; java.util.List; javax.annotation.PostConstruct; javax.annotation.PreDestroy; javax.ejb.Stateless; javax.interceptor.AroundInvoke; javax.interceptor.InvocationContext;
@Stateless(name = "SearchFacade") public class SearchFacadeBean implements SearchFacade, SearchFacadeLocal { public SearchFacadeBean() { } HashMap stockMap = new HashMap(); public List articleSearch(String articleCategorie) { List articleList = new ArrayList(); if (articleCategorie.equals("Disque Dur")) { articleList.add("Hitachi Deskstar 7K1000"); wineList.add("Maxtor 200 Go Serial ATA II"); wineList.add("Samsung SpinPoint P - SP2014N - 200Mo"); } else if (articleType.equals("Cartes graphique")) { wineList.add("ATI Radeon 7000 - 64 Mo - AGP (ATI Radeon 7000)"); } return articleList; } @PostConstruct public void initializeStockList() { //countryMap is HashMap System.out.println("Invocation de la methode de callback initializeStockList() sur evenement @PostConstruct");
stockMap.put("Disque Dur", "210"); stockMap.put("Ecrans", "510"); stockMap.put("Claviers", "670"); stockMap.put("Cartes graphique", "289"); }
219
@PreDestroy public void destroyArticleList() { System.out.println("Invocation de la methode de callback destroyWineList() sur evenement @PredDestroy"); stockMap.clear(); } public void afterBegin() {} public void beforeCompletion() {} public void afterCompletion (boolean b){ // if (b==false) //... traitement echec transaction; } // ... }
Nous avons ajout une mthode de callback PostConstruct initializeStockList() an dinitialiser la liste des articles en stock lors de linstanciation du bean. Idalement, cette liste sera initialise partir dun back-ofce, alimente au besoin via un bean MDB connect une le de messages (typiquement MQ Series). Ici, nous avons simplement cod en dur pour des raisons de simplication ces valeurs dans une structure de type HashMap. La mthode de callback PreDestroy destroyArticleList() survient avant que le conteneur dtruise une instance du bean SearchFacade inutilise ou expire du pool dobjets. Ici, nous effaons la HashMap contenant la liste des articles et des quantits associes. Pour illustrer le mcanisme des intercepteurs, il suft dajouter lannotation @AroundInvoke au code dimplmentation du bean session SearchFacadeBean :
@AroundInvoke public Object LogMethods (InvocationContext ctx) throws Exception { String beanClassName = ctx.getClass().getName(); String businessMethodeNom = ctx.getMethod().getName(); String target = beanClassName + "." + businessMethodName ; long startTime = System.currentTimeMillis(); System.out.println ("Appel Mthode : " + target); try { return ctx.proceed(); } finally { System.out.println("Sortie mthode " + target); long totalTime = System.currentTimeMillis() - startTime; System.out.println("Methode metier: " + businessMethodeNom + " dans " + beanClassName + "prends " + totalTime + "ms pour sexcuter..."); } }
220
La mthode dinterception LogMethods permet de tracer le temps mis par chaque mthode mtier lorsque celle-ci est invoque par le client Java. Voici sa sortie dans le chier de log JBoss server.log :
cationContextImpl.articleSearch
2007-10-19 17:13:11,875 INFO [STDOUT] Sortie mthode org.jboss.ejb3.interceptor.Invo-
cationContextImpl.articleSearch
2007-10-19 17:13:11,875 INFO [STDOUT] Mthode mtier articleSearch dans
De manire similaire, vous allez dvelopper la classe dun bean session avec tat et son interface mtier destine conserver les articles ajouts par un utilisateur dans son caddy virtuel. Voici le code du bean ShoppingCartBean intgrant les mthodes mtier dnies (voir plus loin) dans les interfaces locales et distantes :
package com.eyrolles.chapitre09; import import import import import java.util.ArrayList; javax.annotation.PostConstruct; javax.annotation.PreDestroy; javax.ejb.Remove; javax.ejb.Stateful;
@Stateful(name = "ShoppingCart") public class ShoppingCartBean implements ShoppingCartRemote, ShoppingCartLocal { public ArrayList cartArticles; public ShoppingCartBean() { } public void addArticle(String article) { cartArticles.add(article); } public void removeArticle(String article) { cartArticles.remove(article); } public void setCartArticles(ArrayList cartArticles) { this. cartArticles = cartArticles; }
221
public ArrayList getCartArticles() { return cartArticles; } @PostConstruct public void initialize() { cartArticles = new ArrayList(); } @PreDestroy public void exit() { System.out.println("Sauvegarde de la liste des articles dans la base."); } @Remove public void stopSession() { System.out.println("Mthode stopSession dans lannotation @Remove"); } }
Le code prcdent peut aussi scrire de manire quivalente en utilisant les annotation @Remote et @Local :
import javax.ejb.Remote; import javax.ejb.Local; import javax.ejb.Stateful;
@Local({ShoppingCartLocal.class}) @Remote({ShoppingCart.class}) @Stateful(name = "ShoppingCart") public class ShoppingCartBean //implements ShoppingCart, ShoppingCartLocal {
// . }
Les interfaces locale et distante sont donnes ci-dessous titre dillustration, tant entendu que linterface locale sera utilise pour une utilisation au sein du conteneur Web :
package com.eyrolles.chapitre09; import javax.ejb.Local; @Local public interface ShoppingCartLocal { void addArticle(String wine); void removeArticle(String item); ArrayList getCartArticles(); }
222
package com.eyrolles.chapitre09; import javax.ejb.Remote; @Remote public interface ShoppingCartRemote { void addArticle(String wine); void removeArticle(String item); ArrayList getCartArticles(); }
Le bean ShoppingCartBean supporte des mthodes de callback pour la construction, avec lannotation @PostConstruct, dune liste darticles avec la mthode initialize(). La mthode de callback exit() (laisse ici titre dexemple, mais sans implmentation relle) se charge de la sauvegarder aprs que toutes les mthodes associes lannotation @Remove ont t excutes.
223
Votre projet est dsormais entirement recompil et redploy automatiquement chaque sauvegarde de chaque ressource chier du projet (voir gure 9.10).
Figure 9.10
Dploiement du projet
1. Crez un projet de type Java via lassistant de cration de projet Eclipse. 2. Ajoutez les bibliothques clientes illustres la gure 9.11 dans le chemin de compilation des classes (y compris le jar du projet EJB3 dploy sous JBoss).
Figure 9.11
3. Dans loption Project References, ajoutez la rfrence au projet EJB MonProjetEJB3. 4. Ajoutez les classes Java de type client distant suivantes (remarquez dans lextrait linvocation de linterface distante SearchFacade/remote dans le lookup JNDI) :
224
Voici le code du client correspondant linvocation distante des mthodes mtier du bean session sans tat, linvocation pour le bean avec tat ShoppingCart se faisant de manire similaire :
package com.eyroles.chapitre09.client; import com.eyrolles.chapitre09.*; import java.util.List; import import import import import java.util.Properties; javax.ejb.EJB; javax.naming.Context; javax.naming.InitialContext; javax.naming.NamingException;
public class SearchFacadeClient { public SearchFacadeClient() { } public static void main(String[] args) { try { Context context = new InitialContext(); SearchFacade beanRemote = (SearchFacade)context.lookup("SearchFacade/remote"); List winesList = beanRemote.articleSearch("Disque Dur"); System.out.println("Affichage liste articles"); for (String article: (List<String>)articlesList) { System.out.println(article); } } catch (NamingException e) { e.printStackTrace(); } } }
Conguration Eclipse/Web Tools/JBoss La conguration utilisant linjection de dpendances avec JNDI (en particulier lutilisation de la balise @EJB) nest apparemment pas fonctionnelle avec la conguration Eclipse/Web Tools/JBoss. Pour tester vos beans session, vous devez utiliser la conguration plus traditionnelle via le look-up JNDI, mais bien sr faon EJB3 . Nous donnons toutefois le code utilisant linjection de dpendances, que vous pourrez utiliser avec dautres environnements, comme Ant.
En rsum
Ce chapitre vous a permis de dcouvrir les aspects innovants du dveloppement EJB3 et les fondamentaux de ce nouveau modle, en particulier pour le dveloppement des beans session. Vous verrez au chapitre suivant les aspects lis aux beans entit et lAPI Java Persistence, autre apport important de la spcication EJB3.
10
LAPI JPA et la gestion des entits
Nous avons explor au chapitre prcdent les fondamentaux de larchitecture EJB3 ainsi que le modle de dveloppement des beans session support par la nouvelle spcication. Nous prsentons dans ce chapitre le modle entit introduit par la spcication EJB 3.0, qui fait lobjet dun document spcique, preuve du soin apport ce sujet sensible entre tous quest la persistance des donnes. La nouvelle API JPA (Java Persistence API) offre de nombreuses amliorations, qui tendent vers une plus grande simplicit que les prcdentes versions du modle EJB. Comme les beans session, les beans entit deviennent de simples POJO, dcoupls de leur framework de persistance. Cela permet de les utiliser lintrieur comme lextrieur de leur conteneur.
226
exibilit et la complexit de la spcication J2EE 1.4, en particulier en ce qui concerne la persistance des beans entits. Rappelons que cest pouss et inspir par les frameworks Open Source Spring, avec son mcanisme dinjection de dpendances, et Hibernate, et sa gestion de la persistance, quune grande partie des mcanismes de persistance EJB3 amens par JPA ont t construits. Un des grands atouts de lAPI JPA est quelle est indpendante de tout fournisseur. Elle peut ainsi sintgrer facilement des serveurs dapplications JEE ou JSE (Tomcat). JPA est implmente par deux produits de rfrence : TopLink, un produit commercial (Oracle) devenu libre, et Hibernate. Larchitecture de JPA et son intgration dans larchitecture n-tiers sont illustres la figure 10.1. JDBC reste toujours la couche standard utilise en Java pour laccs aux donnes.
Figure 10.1
Architecture de JPA
Les aspects importants de cette nouvelle architecture sont ses relatives stabilit et standardisation. La couche daccs aux donnes dialoguant avec les interfaces JPA, les dveloppements gagnent en souplesse, puisquil nest plus ncessaire de changer de modle O/R ni de couche DAO (pour laccs aux donnes) en fonction de loutil de mapping utilis. Quel que soit le produit qui implmente lAPI, linterface de la couche JPA reste inchange.
227
Caractristiques de JPA
Avec JPA, toute la complexit qui faisait frmir les dveloppeurs dapplications Java appels dvelopper des projets base dEJB est vacue. Ses principaux avantages sont les suivants : Disparition de la multitude dinterfaces (Home, Remote, Local, etc.). Possibilit dutiliser JPA lintrieur comme lextrieur dun conteneur JEE. Transformation des beans entit en simples POJO. Mapping O/R (objet-relationnel) avec les tables de la base facilite par les annotations. La gure 10.2 illustre le mcanisme permettant la transformation de toute classe rgulire (exemple Article) en table correspondante, en utilisant les annotations.
Figure 10.2
En rsum, JPA fournit les services suivants : Mcanisme la Hibernate permettant de dnir dclarativement le mapping O/R et de mapper un objet une ou plusieurs tables de la base de donnes grce aux annotations de J2SE 5.0. Les annotations peuvent tre utilises pour dnir des objets, des relations, du mapping O/R, de linjection et de la persistance du contexte. JPA fournit en outre une option pour utiliser les descripteurs XML au lieu des annotations. API permettant de manipuler les beans entit pour effectuer les oprations CRUD de persistance, rcupration et suppression des objets. Le dveloppeur saffranchit ainsi de toutes les tches rbarbatives dcriture du code de persistance des objets mtier via JDBC et les requtes SQL associes.
228
Langage de requte standard pour la rcupration des objets (JP QL, une extension de lEJB QL dEJB 2.x. Cest sans doute l un des aspects les plus important de la persistance des donnes, tant les requtes SQL mal construites ralentissent la base de donnes. Cette approche affranchit les applications du langage de requte SQL propritaire.
229
La gure 10.3 illustre les quatre entits principales du domaine webstock de notre tude de cas : Article, Inventaire, Commande et Client.
Figure 10.3
Les cardinalits des relations du modle sont les suivantes : One-to-One (relation entre Article et Inventaire) : un article est relatif une ligne dun inventaire en magasin. One-to-One (relation entre Article et Commande) : chaque enregistrement dinventaire contient un et un seul article. One-to-Many (relation entre Client et Commande) : spcie quune entit est associe avec une collection dautres entits. Dans notre exemple, un client peut passer plusieurs commandes (on reprsente dailleurs parfois lextrmit de la relation, ici Commande, par le caractre * , qui prcise la multiplicit). Many-to-One (relation entre Commande et Client) : relation bidirectionnelle relativement utilise pour spcier que plusieurs commandes sont associes un client. Les cardinalits et les notions de directionnalit et de proprit de la relation (notion lie la jointure du type de relation) sont essentielles dans la modlisation et le mapping O/. Nous y reviendrons lors du design de ltude de cas autour de lextrait du modle mtier webstock. La marche suivre pour utiliser une entit au sens JPA du terme est la suivante : 1. Cration dune classe reprsentant les donnes dune ou plusieurs tables, soit un simple JavaBean possdant des setters et des getters, comme ici pour Article:
public classe Article { int id; private String nomArticle;
230
//constructeurs, getter et setter, etc public Article() {} public Article(int id) { this.id = id; } public int getId() { return id; } public void setId(int id) { this.id = id; } }
2. Ajout des mtadonnes pour indiquer que la classe est une entit :
import javax.persistence.*; @Entity public class Article { int id; private String nomArticle; private String articleCategorieID; private String fournisseurID; private String description; private long poids; //constructeurs, getter et setter, etc public Employe() {} public Employe(int id) { this.id = id; } public int getId() { return id; } public void setId(int id) { this.id = id; } }
3. Marquage de la classe avec lannotation @Entity spciant au moteur de persistance que les objets crs avec cette classe peuvent utiliser le support de JPA pour les rendre persistants.
231
4. Ajout des mtadonnes de mapping O/R sous forme dannotation (ou de chier XML au besoin) :
import javax.persistence.*; @Entity(name=?Article?) @Table (name=Article, schema=webstock) public class Article { @Id @GeneratedValue @Column (name="ARTICLEID") private int articleId; private private private private private String nomArticle; String articleCategorieID; String fournisseurID; String description; long poids;
public Article() {} public Article(int id) { this.id = id; } public int getId() { return id; } public void setId(int id) { this.id = id; } // . . . }
Lajout de simples annotations la classe Article permet de la rendre persistante. Le tableau 10.1 rcapitule lensemble des annotations standards appliques aux classes entits.
Tableau 10.1 Annotations standards appliques aux classes entits
Annotation
@Entity
Description
Permet de qualier la classe comme entit, en prcisant au moteur de persistance que les instances dobjets crs partir de cette classe peuvent utiliser le support de JPA pour tre rendues persistantes. Toute entit est identi par un nom (proprit name) et si non spci avec laide de la proprit name, prend le nom de la classe. Ce nom est utilis par le langage JPQL (Java Persistence Query Language) pour rfrencer lentit dans les requtes. Remarque : si lentit est passe par valeur lors de son transfert par le biais dun bean session distant partir de clients Java externes au conteneur EJB, le bean entit doit implmenter linterface java.io.Serializable et utiliser le protocole RMI/IIOP travers HTTP. Offre la possibilit de dsigner la table sous-jacente laquelle est associe cette classe, mais galement de prciser le schma de donnes associ.
@Table
232
Dveloppement EJB3 avec Eclipse et Web Tools PARTIE III Tableau 10.1 Annotations standards appliques aux classes entits (suite)
Annotation
@Id
Description
Indique au moteur de persistance quel champ de la classe (il peut en e xister plusieurs) est la cl primaire ou lidentiant de la classe. La valeur de lidentiant du champ doit tre unique par rapport lensemble des instances dentits. En complment de cette annotation, @GeneratedValue sapplique la proprit cl primaire du champ en conjonction avec lannotation @Id an de permet une gnration automatique de la cl selon le choix de la stratgie de gnration adopte : AUTO (par dfaut), TABLE, SEQUENCE ou IDENTITY. Exemple :
@Entity public class Article { @Id @GeneratedValue (strategy=GenerationType.AUTO) private int id; }
Ce mode de cration de lidentiant gnre automatiquement une valeur par le biais du fournisseur de persistance JPA sous-jacent (Hibernate ou TopLink) qui sera insr dans le champs id de chaque entit Employ persistante. Prcisons que le mode AUTO est privilgier dans une phase de prototype ou de dveloppement, les autres modes sont privilgier en phase dindustrialisation et de production puisque sappuyant sur le moteur de base de donnes sous-jacent. @Column
Permet dindiquer que le nom de la colonne dans la base de donnes ser a diffrent de celui de lattribut dni dans la classe. Il est galement possible de spcier la taille de la colonne en nombre de caractres et de prciser si la colonne peut accepter les valeurs nulles. Exemple :
@Entity public class Flight implements Serializable { ... @Version @Column(name="OPTIONLOCK") public Integer getVersion() { ... } }
@Basic Permet de dclarer la stratgie de rcupration pour une proprit. Cette annotation inue sur les performances et la manire dont les donnes de lentit sont accdes et fonctionne en combinaison avec le type fetch. Le mode FetchType permet de prciser au fournisseur de diffrer le chargement de ltat de lattribut jusqu' ce que celui-ci soit rfrenc. Exemple :
233
Si la cl primaire dune entit mappe plusieurs colonnes de la table, cette cl primaire est dite compose. EJB3 propose deux annotations pour supporter cette fonctionnalit : @IdClass et @EmbeddedId.
Lannotation @IdClass
Lentit dclare chaque champ qui constitue la cl compose directement dans la classe de lentit, annotant chacun de ceux-ci avec @Id et spciant la classe de la cl compose qui compose ces champs avec @IdClass, comme dans lexemple suivant :
@Entity @IdClass (ArticlePK.class) public class Article { @Id @GeneratedValue @Column (name="ARTICLEID") private int articleId; @Id private String nomArticle; public Integer getArticleId() { return articleId; } public void setArticleId (Integer articleId) { this.articleId = articleId; } public void setNomArticle (String nomArticle) { this.nomArticle = nomArticle; } public String getNomArticle() { return nomArticle; } // }
Lannotation @IdClass identie un POJO ordinaire, cest--dire sans annotations. Tous les mappings requis par les champs constituant la cl primaire sont spcis dans les champs de lentit (les champs annots par @Id dans lentit doivent correspondre aux champs de la classe cl primaire composite) :
public class ArticlePK implements Serializable { private integer articleId; private String nomArticle public void setArticleId (integer articleId) { this.articleid = articleId; } public Integer getArticleId() { return articleId; } public void setNomArticle (String nomArticle) { this.nomArticle=nomArticle; } }
Lannotation @EmbeddedId
Lentit peut designer un ou plusieurs champs qui la constituent comme constituant de sa cl primaire en utilisant lannotation @EmbeddedId en combinaison avec @Embeddable. Toute annotation @EmbeddedId doit rfrencer une classe marque @Embeddable, comme le montre lextrait suivant dune variante de lentit Article:
@Entity public class Article { @EmbeddedId private ArticlePK2 articleId;
234
public Integer getArticleId() { return articleId; } public void setArticleid (Integer articleId) { this.articleId = articleId; } } @Embeddable public class ArticlePK2 { @Id @Column (name="ARTICLEID") private int articleId; String nomArticle. public void setArticleId (int articleId) { this.articleId = articleId; } public int getArticleId() { return articleId; } public void setNomArticle (String nomArticle) { this.nomArticle = nomArticle;} public String getNomArticle() { return nomArticle; } }
@IdClass assure une compatibilit avec la spcication EJB2 en cas dassociation de type M:N et si lon souhaite que la cl primaire de la table association soit compose des cls trangres vers les tables associes. Dans les autres cas, il est conseill dutiliser @EmbeddedId.
La relation dune entit une autre entit est dnie par son attribut port par la classe. Si lautre entit pointe dispose dun attribut qui pointe son tour vers lentit source, on parle de relation bidirectionnelle (entits Client/Commande). Si seulement une des entits de la relation possde une rfrence vers lautre, la relation est dite unidirectionnelle.
Cardinalit
Un concept important dans la notion de relation entre les beans entit dun modle mtier est la cardinalit, notion qui sapplique de manire identique au modle relationnel et qui permet dexprimer le nombre dentits qui existent de part et dautre de la relation liant les deux instances. Dans cette relation, chaque rle possde sa propre cardinalit indiquant sil existe une seule instance dentit ou plusieurs.
235
236
Ce type dassociation implique que chaque entit est lie une et une seule entit, et rciproquement. Typiquement, une relation de ce type lie lentit Inventaire lentit Article correspondante, comme dans les tables illustres la gure 10.4.
Figure 10.4
Ce type de mapping se dcrit laide de lannotation @OneToOne. Le mapping One-toOne possdant une colonne de jointure dans la base ncessite de surcharger le nom de la colonne laide de @JoinColumn lorsque le nom gnr par dfaut ne concide pas avec celui de la colonne de la table. Dans lextrait de code suivant, @JoinColumn est utilise pour remplacer le nom de la colonne de jointure par dfaut (soit ici Article_userId par ARTICLEID, cl trangre de lentit source Inventaire) :
Entity @Table(schema="WEBSTOCK") public class Inventaire { @Id @Column(table="Inventaire", name="inventaireId", insertable=false, updatable=false) private long numInventaire; @OneToOne @JoinColumn(name="ARTICLEID", referencedColumnName="ARTICLEID") protected Article article; protected protected protected protected protected // . } double prix; int quantite; String rayon; String region; int version;
La colonne de jointure ARTICLEID est dclare avec @JoinColumn, qui possde le paramtre supplmentaire referencedColumnName. Ce paramtre sert dclarer la colonne dans lentit cible qui sera utilise pour la jointure, soit ARTICLEID.
237
Il arrive souvent quune entit cible dune relation One-to-One possde une relation dite reverse vers lentit source. Lorsque cest le cas, nous appelons ce type de relation bidirectionnelle One-to-One. Elle est reprsente en notation UML par une double che entre les deux entits. Dans lexemple de relation entre Inventaire et Article, le code suivant met en place ce type de relation bidirectionnelle entre les deux entits :
@Entity @Table(schema="WEBSTOCK") public class Article { @Id @Column(name="ARTICLEID") @GeneratedValue protected long articleId; protected String nomArticle; @oneToOne (mappedBy=article) protected Inventaire inventaire; // }
Nous devons dans ce cas ajouter la proprit mappedBy pour indiquer que le ct qui possde la relation est lentit Inventaire et non Article. Nous devons prciser dans la valeur de lattribut mappedBy le nom de lattribut dans lentit dite propritaire de la relation et qui pointe son tour sur lentit Article, soit article. Comme lentit Article nest pas propritaire de la relation, celle-ci na pas fournir linformation de jointure et la colonne associe (pas de balise @JoinColumn).
Mapping Many-to-One
La gure 10.5 illustre le modle objet correspondant la relation de type Many-to-One unidirectionnelle entre les entits Commande et Client, relation illustrant le fait que plusieurs commandes peuvent tre lies un client. Lentit Commande est le ct many et la source de la relation, et lentit Client le ct one et la cible.
Figure 10.5
La classe Commande possde un attribut appel owner qui va contenir la rfrence une instance de Client. Ce type de mapping Many-to-One est dni en annotant lentit source (lattribut qui se rfre lentit cible) avec lannotation @ManyToOne.
238
Dans lextrait de code suivant, lannotation @ManyToOne est utilise pour mapper cette relation. Le champ owner de lentit Commande est lattribut source qui sera annot :
@Entity @Table(schema="WEBSTOCK") public class Commande { @Id @Column(name="commandeId") @GeneratedValue protected long numCommande; @Temporal(DATE) protected Date dateCommande; protected Article article; protected int quantite; @Column(name="ETATCOMMANDE") protected String etat; @ManyToOne(optional=false) @JoinColumn(name="CLIENTID", referencedColumnName = "clientId") protected Client owner; // }
La colonne de jointure est dclare avec @JoinColumn, qui ressemble lannotation @Column mais possde un paramtre de plus, nomm referencedColumnName. Ce paramtre dclare la colonne dans lentit cible qui sera utilise pour la jointure. La cl trangre est nomme CLIENTID en lieu et place de la valeur par dfaut qui serait utilise si elle ntait pas spcie par le paramtre name de lannotation @JoinColumn, soit ici CLIENT_CLIENTID (form de la concatnation de lentit cible et de sa cl primaire).
Relations multivalues
Lorsque lentit source rfrence une collection dinstances de lentit cible, une association multivalue est utilise. Ce type dassociation concerne les mappings One-to-Many et Many-to-Many.
Mapping One-to-Many
Lorsquune entit est associe une collection dentits, ce type de mapping est de type One-to-Many. (type de cardinalit 1 plusieurs ou 1..*). La gure 10.6 illustre ce type de relation entre Commande et Client.
Figure 10.6
239
Dans cette portion du modle, la cl trangre CLIENTID de la table COMMANDE qui rfrence la table CLIENT correspond dans le jargon JPA une entit Commande et une colonne de jointure caractrise par lemploi de lannotation @JoinColumn. Dans ce type de relation, lentit Commande possde la colonne, et lentit Client dispose dune relation One-to-Many utilisant lannotation correspondante @OneToMany, comme dans lextrait suivant :
public class Client { @Id @Column(table="Client") @GeneratedValue protected int clientId; protected int userid; protected String clientNom; protected String clientPrenom; protected String adresse; @Column(name="TEL") protected String telNumero; protected String comment; @Version protected int version ; @OneToMany protected Collection <Commande> commandes; // . }
Notez lusage du type gnrique paramtr Collection pour stocker les entits de type Commande, garantissant lexistence de ce seul type dans la liste et liminant lusage des oprations de cast.
Mapping One-to-Many bidirectionnel
Une relation One-to-Many est souvent bidirectionnelle par nature et implique un mapping Many-to-One inverse vers lentit source. Dans lexemple prcdent, il existe un mapping One-to-Many de lentit Client vers Commande et un mapping retour Many-toOne de lentit Commande vers Client. Le code Many-to-One examin plus haut reste inchang dans lexemple de relation bidirectionnelle puisque lentit Commande possde la colonne de jointure CLIENTID et est propritaire de la relation. Par contre, du ct oppos de la relation et de lentit Client, il faut mapper la collection de commande de lentit Commande comme relation de type Oneto-Many en utilisant lannotation @OneToMany, mais enrichie du paramtre name. Le code correspondant ce type de relation One-to-Many bidirectionnelle est le suivant :
public class Client { @Id @Column(table="Client") @GeneratedValue protected int clientId;
240
protected int userid; protected String clientNom; protected String clientPrenom; protected String adresse; @Column(name="TEL") protected String telNumero; protected String comment; @Version protected int version ; @OneToMany (mappedBy="owner") protected Collection <Commande> commandes; // . }
En rsum, dans une relation One-to-Many bidirectionnelle : Le ct Many-to-One est propritaire de la relation (owning side). Par consquent, la relation de jointure est dnie sur ce ct. Le mapping One-to-Many est le ct inverse de la relation. Llment mappedBy doit donc tre utilis en combinaison avec lannotation @OneToMany. Si ce paramtre nest pas mentionn, le fournisseur JPA la traite comme une relation unidirectionnelle de type One-to-Many utilisant une table de jointure.
Mapping Many-to-Many
Le mapping Many-to-Many reprsente un type de relation entre une collection dobjets sources et une collection dobjets cibles. Ce type de mapping, moins usit que les prcdentes relations, ncessite la cration dune table intermdiaire pour la gestion des associations entre les enregistrements sources et cibles. La gure 10.7 illustre un exemple dapplication de ce type de relation entre les entits Employe et Projet. Chaque employ peut travailler sur un ou plusieurs projets, et chaque projet peut son tour tre mis en uvre par un ou plusieurs employs.
Figure 10.7
Les mappings Many-to-Many utilisent une table contenant les colonnes des cls primaires pour les tables sources et destination. Les cls primaires composites ncessitent une colonne pour chaque champ qui constitue la cl composite. Cette table doit exister avant toute utilisation de ce type de relation. La relation est aussi exprime par lannotation @ManyToMany pour chaque
241
attribut dni de part et dautre de la relation, attribut de type collection, comme le montre lextrait suivant :
@Entity public class Employe { @Id private int id; private String nom; private String adresse; @ManyToMany Private Collection <Projet> projets; //. } @Entity public class Projet { @Id private int id; private String nom; @ManyToMany (mappedBy="projets") private Collection <Employe> employes; // }
La principale diffrence avec les autres types de mappings, en particulier One-to-Many, est le fait quil nexiste pas de colonne de jointure de part et dautre de la relation. De ce fait, la seule manire de mettre en uvre ce type de mapping est la cration dune table de jointure spare. La notion de propritaire de la relation, notion fondamentale dans ce type de relation bidirectionnelle, doit donc tre adapte ce contexte. Il est ncessaire de choisir une des deux entits faisant partie de la relation comme propritaire de la relation bidirectionnelle, lautre devant tre marque comme inverse . Dans notre exemple, nous avons choisi lentit Employe mais aurions tout aussi bien pu choisir Projet. Comme toute relation bidirectionnelle, la relation inverse doit utiliser llment mappedBy pour identier lattribut propritaire.
Figure 10.8
242
Les tables EMPLOYE et PROJET ainsi que la table de jointure EMP_PROJET qui associe les entits Employe et Projet contiennent seulement les colonnes cls trangres qui constituent la cl primaire composite. La colonne EMP_ID se rfre la cl primaire de la table EMPLOYE, PROJ_ID, laquelle se rfre la cl primaire de la table PROJET. An de pouvoir mapper les tables ainsi dcrites, il est ncessaire dajouter des informations de types mtadonnes pour la classe Employe qui a t dsigne dans notre exemple comme propritaire de la relation. Lextrait suivant dcrit la relation Many-to-Many dnie laide des annotations de jointure :
@Entity public class Employe { @Id private int id; private String nom private String adresse; @ManyToMany @JoinTable (name="EMP_PROJET", joinColumns=@JoinColumn(name="EMP_ID"), inverseJoinColumns=@JoinColumn(name="PROJ_ID")) private Collection <Projet> projets; // .. }
Lannotation @JoinTable est utilise pour congurer la table de jointure pour les relations entre les entits Employe et Projet. Cette annotation dnit un name, un tableau de colonnes de jointure et un tableau de colonnes de jointure inverse. Ces dernires sont les colonnes de la table dassociation qui rfrencent la cl primaire dEmploye (lautre extrmit de la relation).
243
Figure 10.9
244
Le tableau 10.2 rcapitule les oprations prises en charge par le gestionnaire dentits sur ses entits gres.
Tableau 10.2 Oprations prises en charge par le gestionnaire dentits
Opration
persist() remove() refresh() merge()
Description
Insre ltat dune entit dans la base de donnes. Cette nouvelle entit devient alors une entit gre. Supprime ltat de lentit gre et ses donnes correspondantes de la base . Synchronise ltat de lentit partir de la base, les donnes de la BD tant copies dans lentit. Synchronise les tats des entits dtaches avec le PC. La mthode retourne une entit gre qui a la mme identit dans la base que lentit passe en paramtre, bien que ce ne soit pas le mme objet. Excute une requte simple de recherche de cl. Cre une instance de requte en utilisant le langage JPQL. Cre une instance de requte spcique. Cre une instance de requte SQL. Spcie si lentit est manage par le PC. Toutes les modications effectues sur les entits du contexte de persistance gres par le gestionnaire dentits sont enregistres dans la BD lors dun ush du gestionnaire.
Les tats associs au cycle de vie dune instance dentit sont illustres la gure 10.10.
Figure 10.10
Pour illustrer lemploi de ces mthodes, vous utiliserez par la suite lentit Employe suivante (en supposant que lensemble des oprations sexcute en dehors du conteneur JEE, cest--dire sous le contrle dune JVM 5 et dun conteneur JEE) :
@Entity @Table (schema="WEBSTOCK", name="EMPLOYE") public class Employe {
245
@Id @Column(name="EMPLOYEID") private employeid; private String nom; private String adresse; private long salaire; public Employe() {} public Employe(int id) { this.id = id; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getNom() { return name; } public void setNom(String name) { this.name = name; } public String getAdresse() { return adresse; } public void setAdresse (String adrese) {this.adresse= adresse; } public long getSalaire() { return salaire; } public void setSalaire (long salaire) {this.salaire = salaire;} public String toString() { return "Identifiant Employe: " + getEmployeId() + " nom: " + getNom() + " Adresse: "+ getAdresse() + " Salaire: " + getSalaire(); } }
Les tapes de lutilisation de cette interface via un client JPA sont dcrites succinctement ci-aprs.
chier persistence.xml. Cette fabrique est lie une unit de persistance prcise. On se rappelle que le chier de conguration METAINF/persistence.xml permet de dnir des units de persistance et la source de donnes associe. Ce chier impos par la spcication JPA est cr automatiquement par la facet JPA suivante :
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"> <persistence-unit name="EmployeeService" transaction-type="RESOURCE_LOCAL"> <class>com.webstock.chap10.employe</class> <properties> <property name="toplink.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/> <property name="toplink.jdbc.url" value="jdbc:derby://localhost:1527/EmpServDB;create=true"/> <property name="toplink.jdbc.user" value="APP"/> <property name="toplink.jdbc.password" value="APP"/> </properties> </persistence-unit> </persistence>
246
La proprit transaction-type indique que vous fonctionnerez dans un mode non-JTA. Les transactions longues et le commit deux phases ne seront donc pas pris en charge, ce qui nest pas un souci dans cet exemple didactique. Llment class spcie la liste des entits qui font partie de lunit de persistante, ici la simple classe employe. Si vous en possdiez plusieurs, chaque entit serait rfrence entre chaque balise <class>.
TopLink TopLink, implmentation de rfrence de JPA, comporte des extensions de la norme JPA telles que la gnration automatique de table (proprit toplink.ddl-generation), associe trois valeurs possibles : none, create-tables et drop-and-create-tables. Nous ne saurions trop vous conseiller de vous rfrer la documentation du fournisseur pour en connatre les caractristiques prcises.
Contextes de persistance Un contexte de persistance ne peut appartenir qu une et une seule unit de persistance associe un ensemble de classes entits. linverse, une unit de persistance peut contenir plusieurs contextes de persistance. Il faut donc veiller ce quune entit nappartienne qu un seul contexte de persistance pour viter toute incohrence dans la base. Le gestionnaire dentits est supprim avec la mthode close() de la classe EntityManager.
Avec ce gestionnaire dentits, il est ensuite possible de travailler sur les entits persistantes du modle logique associ.
Si le gestionnaire dentits rencontre un problme en appelant la mthode persist(), il gnre une exception PersistenceException. Autrement, lemploy est stock dans la base de donnes.
247
Lorsque lappel de la mthode persist() est effectue, linstance emp renvoye est un bean entit manag, cest--dire pris en charge au sein du contexte de persistance du gestionnaire de dploiement. Lextrait suivant illustre lintgration de la mthode persist() dans la mthode createEmploye() de cration dun nouvel employ :
public Employe createEmploye(int employeid, String employenom, String adresse, long salaire) { Employe article = new Article(employeid); emp.setEmployenom (employenom); emp.setAdresse (adresse); emp.salaire (salaire); em.persist(emp); return emp; }
Le code suivant illustre lutilisation de la mthode persist() applique au contexte JEE avec lexemple dun bean session acqurant une instance dEntityManager travers linjection dun contexte automatis (@PersistenceContext) attach lunit de persistance dnie prcdemment (EmployeService) :
@Stateless public class EmployeManager { @PersistenceContext("EmployeeService ") private EntityManager em; public void createEmploye() { final Employe emp = new Employe(); emp.setNom("John Doe"); emp.setAdresse("Main street"); em.persist(emp); } }
Mthode persit() Lappel la mthode persist() ne garantit pas quune instruction SQL insert soit effectue immdiatement. Cette dcision relve du gestionnaire dentits, lequel peut dcider de le faire dans la foule ou plus tard, avant de commiter dnitivement la transaction. Si les donnes de la base ont t modies (et valides) en parallle dans la base, les donnes rcupres ne tiennent pas compte de ces modications, ce qui peut provoquer des incohrences dans la base.
Pour rcuprer une instance dEmploye, les seules informations ncessaires faire passer la mthode find() sont le nom de la classe de lentit ainsi que lidentiant de cl primaire associe.
248
La mthode find() ne prsente pas la souplesse ni la richesse dun requte SQL, loin sen faut. Heureusement, JPA fournit une API Query supportant linterrogation de la base de donnes. Les interrogations seffectuent travers les entits du modle mtier et utilisent la syntaxe JPQL (Java Persistence Query Language). LAPI Query est essentielle la jonction entre lapplication et lexcution des requtes EJB-QL. Les mthodes de celles-ci sont regroupes dans linterface javax.persistence.Query. Lintrt principal de cette API est quelle permet de crer des requtes dynamiques sous la forme de simples chanes de caractres, et non de manire statique, comme cest le cas au sein dun descripteur de dploiement ou avec les annotations. Une requte dynamique est une requte dont les clauses sont fournies lexcution, linverse des requtes nommes, abordes au chapitre suivant, o lutilisateur doit fournir les critres de la requte ainsi que son nom avant toute utilisation. Les principales mthodes de cette API sont regroupes dans linterface EntityManager :
public interface EntityManager { public Query createQuery(String requeteEJB-QL); public Query createNamedQuery(String requeteNommee); public Query createNativeQuery(String requeteSQL); public Query createNativeQuery(String requeteSQL, Class rsultat); public Query createNativeQuery(String requeteSQL, String rsultat); }
Vous vous intresserez ici la premire mthode, CreateQuery(), qui permet de crer de requtes dynamiques. Ces requtes sont moins performantes que les requtes nommes, car elles ne sont pas prcompiles avant leur excution par le moteur JPA. Lexemple simple suivant montre comment lobjet Query est cr avec linterface EntityManager et comment la chane JPQL est transmise avec les arguments de la requte excute pour avoir la liste des employs de la base :
Query query = em.createQuery ("select emp from Employe emp"); Collection emps = query.getResultList();
La chane de la requte se rfre lentit Employe et non la table Employe de la base de donnes. Elle afche la liste de tous les objets Employe associs. Lexcution proprement dite de la requte seffectue grce linvocation de la mthode getResultList(), qui retourne un objet List contenant la liste des employs satisfaisant au critre de la requte. Le code de la mthode findAllEmployes() associe retourne un objet List, auquel nous appliquons un cast pour le transformer en objet Collection, beaucoup plus facile utiliser :
public Collection<Employe> findAllEmployes() { Query query = em.createQuery ("select emp from Employe emp"); return (Collection<Employe>) query.getResulList(): }
Lexemple de requte suivant est un peu plus paramtr grce lutilisation de largument setParameter appliqu lobjet query pour le passage des arguments de la requte :
String queryString = "SELECT e FROM Employe e " + " WHERE e.salaire >= :salaire"; Query query = em.createQuery(queryString); query.setParameter("salaire", "1000"); List<Employe> liste =
249
La mthode suppressionEmploye() permet de vrier, avant toute suppression de linstance proprement dite avec la mthode remove(), son existence dans le contexte du gestionnaire dentits.
Voici, mis bout bout, le code complet de cration, lecture, modication et suppression dune entit employe, regroupes dans une seule classe des diffrentes mthodes CRUD dcrites prcdemment :
package com.webstock.chap10.model; import java.util.Collection; import javax.persistence.EntityManager; import javax.persistence.Query;
250
public class EmployeService { String texteRequete= "SELECT e FROM Employe e"; protected EntityManager em; public EmployeService(EntityManager em) { this.em = em; } public Employe createEmploye(int employeid, String nom, String adresse, long salaire) { Employe emp = new Employe(employeid); emp.setNom(nom); emp.setAdresse(adresse); emp.setSalaire(salaire); em.persist(emp); return emp; } public void removeEmploye(int employeid) { Employe emp = findEmploye(employeid); if (emp != null) { em.remove(emp); } } public Employe augmenteEmployeSalaire (int employeid, long augmentation) { Employe emp = em.find(Employe.class, employeid); if (emp != null) { emp.setSalaire(emp.getSalaire() + augmentation); } return emp; } public Employe findEmploye(int employeid) { return em.find(Employe.class, employeid); } public Collection<Employe> findAllEmployes() { Query query = em.createQuery(texteRequete); return (Collection<Employe>) query.getResultList(); } }
251
travailler avec des transactions locales une ressource. Une instance de ce type peut sobtenir laide de la mthode getTransaction() de lEntityManager. Les six mthodes de support la gestion transactionnelle offerte par cette interface sont les suivantes :
public interface EntityTransaction { public void begin(); public void commit(); public void rollback(); public void setRollbackOnly(); public void getRollbackOnly(); public void isActive(); }
Exemple :
EntityManager em; ... try { em.getTransaction().begin() ... em.getTransaction().commit(); } finally { em.close(); }
Nous enjoignons le lecteur approfondir ces aspects important lis la gestion transactionnelle en examinant les dtails de linterface EntityTransaction dans la documentation du fournisseur JPA.
Mthodes de callback
Nous avons voqu au chapitre prcdent le concept dinvocation des mthodes selon des tapes lies au cycle de vie des beans. Ce concept est applicable aux beans entit. Les mthodes peuvent tre annotes pour indiquer quelles seront appeles par le fournisseur de persistance quand une entit passera dans une tape donne de son cycle de vie. Ces mthodes peuvent appartenir une classe entit ou une classe lcoute de ces vnements (entit listener). Elles peuvent avoir nimporte quel nom, mais doivent possder une signature ne prenant aucun paramtre et possdant un type de donne void. Les mthodes de type nal ou static ne sont pas des types de callback valides. Les exceptions gnres par ces mthodes ne peuvent donc pas tre interceptes par un gestionnaire dexceptions. La transaction est en ce cas simplement abandonne. Les diffrents types de mthodes de callback sont les suivantes : @PrePersist : quand persist (ou merge) sest termine avec succs. @PostPersist : aprs insertion dans la BD. @PreRemove : quand remove est appele. @PostRemove : aprs suppression dans la BD. @PreUpdate : avant modication dans la BD.
252
@PostUpdate : aprs modication dans la BD. @PostLoad : aprs lecture des donnes de la BD pour construire lentit. Lexemple qui suit illustre une utilisation possible de ces mthodes pour la mesure du temps de la dernire synchronisation du bean entit Employe avec la base de donnes (un bean tant considr comme synchronis avec la base chaque fois que ce dernier est lu ou sauvegard dans celle-ci) :
@Entity public class Employe { @Id @Column(name="EMPLOYEID") private employeid; private String nom; private String adresse; @Transient private long syncTime; // ... @PostPersist @PostUpdate @PostLoad private void resetSyncTime() { syncTime = System.currentTimeMillis(); } public long getCachedAge() { return System.currentTimeMillis() - syncTime; } // ... }
253
import java.util.Collection; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import com.webstock.chap10.model.Employe; import com.webstock.chap10.model.EmployeService; public class EmployeCRUDJava { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("EmployeService"); EntityManager em = emf.createEntityManager(); EmployeService service = new EmployeService(em); // creation et persistance de lemploye em.getTransaction().begin(); Employe emp = service.createEmploye(10, "John Doe","Main Street", 12000); em.getTransaction().commit(); System.out.println("Employe sauvegarde: " + emp); // Recherche employe emp = service.findEmploye(10); System.out.println("Trouve " + emp); // Recherche tous les employes Collection<Employe> emps = service.findAllEmployes(); for (Employe e : emps) System.out.println("Employe trouve : " + e); // Mise a jour employe em.getTransaction().begin(); emp = service. augmenteEmployeSalaire (10, 1000); em.getTransaction().commit(); System.out.println("Employe mis a jour: " + emp); // supprime un employe em.getTransaction().begin(); service.removeEmploye(10); em.getTransaction().commit(); System.out.println("Employe 10 supprime"); // Fermeture du gestionnaire dentite EM et de lEntityManagerFactory EMF em.close(); emf.close(); } }
254
Ensuite, vous pouvez utiliser lannotation @PersistenceContexte pour dclarer une dpendance sur le contexte de persistance et permettre une acquisition automatise. Lextrait de code suivant illustre lutilisation de lannotation @PersistenceContext pour lacquisition dun gestionnaire dentits travers le mcanisme dinjection de dpendances offert par le conteneur. Llment unitName spcie le nom de lunit de persistance sur laquelle sappuie le contexte :
@Stateless public class EmployeeServiceBean implements EmployeService { @PersistenceContext(unitName="EmployeeService") EntityManager em; // ... }
Le code suivant prsente limplmentation du bean session EmployeService dcrivant les oprations CRUD sur lentit Employe dans un contexte JEE (et non plus J2SE). Mesurez au passage toutes les facilits offertes par les services du conteneur, comme @PersistenceContext, qui permet linjection automatique du contexte pour acqurir le gestionnaire dentits, et llment unitName spciant lunit de persistance :
@Stateless public class EmployeServiceBean implements EmployeService { @PersistenceContext(unitName="EmployeService") protected EntityManager em; public EntityManager getEntityManager() { return em; } public Employe createEmploye(int employeId, String nom, String adresse, long salaire) { Employe emp = new Employe(employeid); emp.setNom(name); emp.setAdresse (adresse); emp.setSalaire(salaire); getEntityManager().persist(emp); return emp; } public void deleteEmploye(int employeId) {
255
Employe emp = findEmploye(employeId); if (emp != null) { getEntityManager().remove(emp); } } public Employe updateEmployeSalaire(int employeid, long nouvSalaire) { Employe emp = findEmployee(employeid); if (emp != null) { emp.setSalaire(nouvSalaire); } return emp; } public Employe findEmploye(int employeId) { return getEntityManager().find(Employe.class, id); } public Collection<Employe> findAllEmployes() { Query query = getEntityManager().createQuery("SELECT emp FROM Employe emp "); return (Collection<Employe>) query.getResultList(); } }
// injecte une reference vers EmployeService @EJB EmployeService service; public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); printHtmlHeader(out); // process request String action = request.getParameter("action"); if (action == null) { // Ne rien faire si aucune action demandee } else if (action.equals("Creation")) { Employe emp = service.createEmploye(
256
parseInt(request.getParameter("createId")), request.getParameter("nom"), request.getParameter("adresse"); parseLong(request.getParameter("salaire"))); out.println("Employe cree: " + emp); else if (action.equals("Supression")) { String id = request.getParameter("removeId"); service.removeEmploye(parseInt(employeId)); out.println("Suppression Employe avec identifiant: " + id); else if (action.equals("Update")) { String id = request.getParameter("raiseId"); Employee emp = service.changeEmployeeSalaire( parseInt(employeid), parseLong(request.getParameter("raise"))); out.println("employe mise a jour " + emp); else if (action.equals("Find")) { Employe emp = service.findEmploye( parseInt(request.getParameter("findId"))); out.println("Trouve " + emp); else if (action.equals("FindAll")) { Collection<Employe> emps = service.findAllEmployes(); if (emps.isEmpty()) { out.println("Pas demployes trouves "); } else { out.println("Employes trouves: </br>"); for (Employe emp : emps) { out.print(emp + "<br/>"); } }
} printHtmlFooter(out); } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } private int parseInt(String intString) { try { return Integer.parseInt(intString); } catch (NumberFormatException e) { return 0; } } private long parseLong(String longString) { try { return Long.parseLong(longString); } catch (NumberFormatException e) { return 0; } } private void printHtmlHeader(PrintWriter out) throws IOException { out.println("<body>");
257
out.println("<html>"); out.println("<head><title>" + TITRE + "</title></head>"); out.println("<center><h1>" + TITRE + "</h1></center>"); out.println("<p>" + DESCRIPTION + "</p>"); out.println("<hr/>"); out.println("<form action=\"EmployeServlet\" method=\"POST\">"); // form to create out.println("<h3>Creation Employe</h3>"); out.println("<table><tbody>"); out.println("<tr><td>employeId:</td><td><input type=\"text\" name=\"createId\"/> (int)</td></tr>"); out.println("<tr><td>Nom:</td><td><input type=\"text\" name=\"nom\"/>(String) </td></tr>"); out.println("<tr><td>Adresse:</td><td><input type=\"text\" name=\"adresse\"/> (String)</td></tr>"); out.println("<tr><td>Salaire:</td><td><input type=\"text\" name=\"salary\"/> (long)</td>" + "<td><input name=\"action\" type=\"submit\" value=\"Creation\"/> </td></tr>"); out.println("</tbody></table>"); out.println("<hr/>"); out.println("<h3>Suppresion Employe</h3>"); out.println("<table><tbody>"); out.println("<tr><td>Id:</td><td><input type=\"text\" name=\"removeId\"/> (int)</td>" + "<td><input name=\"action\" type=\"submit\" value=\"Remove\"/></td> </tr>"); out.println("</tbody></table>"); out.println("<hr/>"); // form to update out.println("<h3>Mise a jour employe</h3>"); out.println("<table><tbody>"); out.println("<tr><td>Id:</td><td><input type=\"text\" name=\"raiseId\"/> (int)</td></tr>"); out.println("<tr><td>Augmentation:</td><td><input type=\"text\" name=\ "raise\"/>(long)</td>" + "<td><input name=\"action\" type=\"submit\" value=\"Update\"/> </td></tr>"); out.println("</tbody></table>"); out.println("<hr/>"); // form to find out.println("<h3>recherche employe</h3>"); out.println("<table><tbody>"); out.println("<tr><td>Id:</td><td><input type=\"text\" name=\"findId\"/> (int)</td>" + "<td><input name=\"action\" type=\"submit\" value=\"Find\"/> </td></tr>"); out.println("</tbody></table>"); out.println("<hr/>"); out.println("<h3>recherche des employee</h3>"); out.println("<input name=\"action\" type=\"submit\" value=\"FindAll\"/>"); out.println("<hr/>"); }
258
out.println("</body>"); out.close(); } }
Pour grer les dpendances externes de lapplication qui peuvent concerner des ressources de type JDBC, le de messages ou bean session, le conteneur EJB3 fournit lannotation @EJB pour une gestion des dpendances simplie. laide de cette annotation, les rfrences aux composants JEE rfrencs sont rsolus dynamiquement par le conteneur ou au sein du code de lapplication lorsque linstance du composant est cre. Le code complet de ces exemples est disponible sur la page Web ddie louvrage (chapitre 10).
En rsum
Ce chapitre a mis en lumire la puissance et la richesse de lAPI JPA, fondement de la spcication EJB3. Vous avez vu notamment comment mettre en uvre les principales annotations JPA appliques au mapping des relations inter-entits, des mthodes de callback appliques aux entits ainsi que des principales oprations permises sur une entit par le biais de linterface du gestionnaire dentits. Le chapitre suivant prsente le projet Dali, qui vise simplier le mapping O/R.
11
Mapping JPA avec Dali
Au chapitre prcdent, vous avez dcouvert les concepts fondamentaux de lAPI JPA. Extraits de code lappui, vous avez vu sa relative facilite de mise en uvre en mme temps que sa puissance. Dans ce chapitre, vous allez la mettre en uvre dans Dali, un sous-projet de Web Tools dont le but est de faciliter la mise en uvre de cette API. Les outils de support lAPI JPA sur plate-forme Eclipse ont trouv leur maturit avec le projet Dali. Issu de la mouvance Eclipse, il complte harmonieusement loutillage Web Tools en offrant des outils de mapping capables de transformer un type de donne objet en son pendant relationnel dans la base de donnes. Eclipse Web Tools 2.0 intgre compltement le projet Dali, rendant plus facile sa mise en uvre dans les dveloppements autour de la plate-forme Europa.
Le projet Dali
Lobjectif de Dali (http://www.eclipse.org/dali/) est de faciliter la mise en uvre de JPA (Java Persistence API). Lanc en 2005 par Oracle, Dali a rejoint JBoss n 2005. La cible du projet est le support de la persistance des EJB 3.0 via lAPI JPA. Depuis son lancement (la version courante est la version Dali 1.5), Dali supporte limplmentation de rfrence JPA TopLink Essentials, contribution dOracle. Ce projet offre en particulier les fonctionnalits suivantes : Conguration dun projet Java pour le support de JPA et des annotations pour lenvironnement Java SE ou JEE. Support des approches de dveloppement top-down (descendante), bottom-up (ascendante) et meet-in-the-middle (mixte). Support simpli des diffrentes bases de donnes via les nombreux connecteurs disponibles et les diffrentes vues et perspectives de manipulation des donnes.
260
Intgration doutils de mapping en liaison avec des vues ddies, comme JPA Details et JPA Structure, qui permettent de naviguer dans les champs persistants des entits et de la classe, de changer les types de relation, etc. Gnration des chiers de persistance persistence.xml et orm.xml pour le support des mtadonnes.
Une fois dnie la bibliothque personnalise, il suft de lassocier loption JPA en prenant bien soin de cliquer sur Apply pour valider lenvironnement, comme lillustre la gure 11.2. Vous pouvez ce stade ajouter votre projet Java le support JPA en choisissant Properties, Java Build Path, Add Library et User Library dans le menu contextuel du projet puis en slectionnant la bibliothque JPA prcdemment cre.
261
Le chemin daccs aux bibliothques JPA se prsente comme illustr la gure 11.3.
Figure 11.3
Avec votre chemin de compilation correctement positionn, vous pouvez crer et compiler vos entits (ici Employe) aprs import des annotations ncessaires. Le code annot est compil dans lditeur Eclipse, comme illustr la gure 11.4.
Figure 11.4
262
Nous supposons installe et congure votre base WEBSTOCKDB (voir en annexe pour la conguration de la base HSQLDB livre en standard avec JBoss 4.2). Notez que Dali permet de rgnrer le modle physique partir de DDL en entre. Nous supposons galement congur (via le menu Preferences dEclipse) le driver Hypersonic DB, comme illustr la gure 11.6. Limplmentation de rfrence de TopLink JPA est disponible en tlchargement sur le site de lditeur Oracle ladresse http://www.oracle.com/technology/products/ias/toplink/jpa/download.html.
Pour la congurer, il suft douvrir une sessions DOS et de saisir la commande suivante (selon la version de TopLink JPA, ici la v2, build 41) :
java -jar glassfish-persistence-installer-v2-41.jar
Lacceptation des conditions de licence a pour effet de dcompresser dans le rpertoire courant lensemble des bibliothques TopLink requises. Il faut ensuite dmarrer le serveur JBoss pour amorcer le dmarrage de la base HSQLDB.
263
264
Figure 11.7
Persistent class management Dans la zone Persistent class management , Dali permet dindiquer si le runtime JPA doit dcouvrir les entits dynamiquement ou si elles doivent tre listes dans le chier persistence.xml. La case cocher Create orm.xml permet de spcier un chier de mapping XML au lieu des annotations standards.
Figure 11.8
7. Dans lassistant de cration de prol de connexion, donnez un nom cette connexion, par exemple HSQLDBConn, et cochez loption Auto-connect at startup pour une connexion automatique la source de donnes (voir gure 11.9). Cliquez sur Suivant.
265
8. Lcran suivant permet de congurer la connexion la base HSQLDB, ici SAMPLE (voir gure 11.10).
Figure 11.10
9. Cliquez sur le bouton Test Connection pour valider la connexion, puis cliquez sur OK pour terminer la conguration de la connexion.
266
Vous pouvez vrier le succs de la connexion dans la vue Data Source Explorer, qui contient une rfrence la source de donnes Hypersonic dnie prcdemment et la liste des tables du modle webstock, comme lillustre la gure 11.11.
Figure 11.11
Le nom de lunit de persistance est par dfaut celui de votre projet. Ce dernier est associ la connexion dnie plus haut.
267
Vous avez achev la dnition de lunit de persistance du projet avec les proprits associes la connexion la base WebStockDB. Votre projet est prt utiliser lAPI JPA avec Dali.
Attribut
numInventaire article quantite prix rayon region
Type java
long article int double string string int string string integer string double string long date article string int string int int string string string string string int
Colonne associe
numeroinventaire articleid quantite prix rayon region articleid nomarticle articlecategorieid fournisseurid description poids image_url numerocommande datecommande articleid clientid quantite etatcommande clientid userid clientnom clientprenom adresse tel comment version
Article
Commande
Client
268
5. Pour la classe Inventaire, gnrez les getters et setters pour les champs suivants, sauf pour lattribut numInventaire :
public class Inventaire { private long numInventaire; protected Article article; protected double prix; protected int quantite; protected String rayon; protected String region; protected int version; public double getCost() { return cost; } public void setCost(double cost) { this.cost = cost; } public Article getArticle() { return article; } public void setArticle(Article article) { this.article = article; } public double getPrix() { return prix; } public void setPrix(double prix) { this.prix = prix; } // A completer
6. Pour la classe Article, gnrez les getters et setters pour les champs suivants :
public class Article { protected protected protected protected protected protected protected } int articleId; String nomArticle; String articleCategorie; int fournId; String desc; double poids; String image_url;
7. Pour la classe Commande, gnrez les getters et setters pour les champs suivants :
public class Commande { protected long numCommande; protected Date dateCommande; protected List <Article> articles; protected int quantite; protected String etat; protected Client owner; }
269
8. Pour la classe Client, gnrez les getters et setters pour les champs suivants :
public class Client { protected int clientId; protected int userid; protected protected protected protected protected protected protected String clientNom; String clientPrenom; String adresse; String telNumero; String comment; int userid; int version;
Votre modle est cr. Vous pouvez passer la cration des entits persistantes et les associer aux tables correspondantes de la base.
Mapping des classes avec le modle physique de donnes
Vous allez transformer chacune des classes en entit persistante en associant chaque entit du modle avec sa table de la base : 1. Ouvrez le chier Article.java dans la vue Package Explorer dEclipse. Vous pouvez voir safcher la vue JPA Structure correspondante. 2. Slectionnez la classe Article, puis, dans la vue JPA Details, slectionnez dans la liste droulante Map As la valeur Entity, comme illustr la gure 11.12.
Figure 11.12
270
Schema Il ne faut pas omettre de prciser le schma webstock dans loption Schema de la vue JPA Details an de mapper exactement la table de la base lentit.
Vous pouvez constater quune balise @Entity a t automatiquement ajoute dans le code de la classe Article, indiquant quelle est devenue une entit persistante. 3. Dans la vue Package Explorer, faites un clic droit sur le chier persistence.xml, et slectionnez JPA Tools puis Synchronize Classes. Cela a pour effet de mettre jour le chier descripteur avec la nouvelle entit ajoute (voir balise <class>). Notez que Dali a automatiquement associ lentit Article la table Article correspondante de la base. Vous devez ce stade voir safcher des erreurs dans la vue Problems dEclipse, du fait que certaines colonnes ne sont pas identiques au nom des colonnes associes dans la base. Vous rsoudrez un peu plus loin ce problme de mapping. 4. Rptez les mmes tapes pour les deux autres entits du modle webstock extrait (Inventaire et Commande) et leurs tables associes.
Mapping des champs de la classe
Dans cette tape, vous allez mapper les attributs des classes avec ceux de la table de la base. Pour cette application, vous utiliserez les types de mappings suivants : identiant de cl de base One-to-One One-to-Many
Cration des mappings didentiant de cl
Vous devez spcier lidentiant de cl primaire associ chaque entit. 1. Dans lexplorateur de package, ouvrez la classe Article.java. 2. Slectionnez le champ articleId dans la vue JPA Structure. La vue JPA Details afche les proprits du champ. 3. Dans la liste droulante Map As, slectionnez Id. Cela a pour effet dajouter lannotation @Id dans le code de la classe Article, permettant de dnir cette colonne comme cl primaire. 4. Positionnez Insertable et Updatable false. Cela a pour effet dajouter les annotations suivantes :
@Column(insertable=false, updatable = false)
Ces annotations JPA permettent de spcier si la colonne doit tre utilise en mode insert ou update. Remarquez dans la vue JPA Structure que le champ articleId a t identi comme cl primaire avec le symbole associ (voir gure 11.13).
271
5. Rptez les mmes tapes pour lentit Inventaire associe la cl numInventaire pour lentit et la colonne numeroInventaire et pour lentit Commande associe la cl numCommande et la colonne numeroCommande. Pour ces deux champs, comme le nom de la colonne dans la base et celui de lattribut dans lentit sont diffrents, il faudra gnrer lannotation @Column via la liste droulante Column/Name, comme illustr la gure11.14.
Figure 11.14
Cela aura pour effet de gnrer le code suivant (pour lentit Commande) :
@Id @Column(name="NUMEROCOMMANDE", insertable = false, updatable = false)
Dali permet de gnrer le code annot associ au mode de gnration des cls primaires laide de la balise @GeneratedValue. Cela seffectue dans la vue JPA Details via la conguration des listes droulantes Strategy et Table Generator, comme illustr la gure 11.15.
272
Figure 11.15
Le tableau 11.2 rcapitule les proprits de conguration associes la mise en uvre dune stratgie de gnration de cls primaires.
Tableau 11.2 Conguration dune stratgie de gnration de cls primaires
Proprit
Primary Key Generation Strategy
Description
Dnit comment la cl primaire est gnre. Ce champ correspond lannotation @Generated Value. Auto Sequence : les valeurs dincrment sont assignes par le biais dune table sequence. Identity : les valeurs dincrment sont assignes par une colonne Identity de la colonne de la base de donnes. Table : les valeurs dincrment sont assignes par une table de la base. Nom unique pour la valeur gnre
Auto
Generator Name
Table Generator : les champs qui suivent vont dnir les tables de la base utilises pour gnrer la cl primaire et qui vont tre associes lannotation @TableGenerator. Ces champs ne sappliqueront que si la stratgie est de type Table. Name Table Primary Key Column Value Column Primary key Column value Nom unique du gnrateur Table qui va stocker les valeurs de squence gnres. Colonne dans la table de gnration qui va contenir la cl primaire. Colonne qui va stocker la valeur gnre. Valeur associe la colonne cl primaire dans la table servant de gnration.
Sequence Generator : ces champs dnissent la squence spcique utilise pour gnrer la cl primaire et correspondent lannotation @SequenceGenerator. Les champs qui suivent ne sappliquent que lorsque la stratgie est Sequence. Name Sequence Nom de la table squence utiliser Nom unique de la squence
273
Pour les trois entits de votre portion de modle webstock, Article, Commande et Client, vous devez spcier un mode de stratgie de gnration de cls primaires de type Auto (gnration automatique), qui est le mode par dfaut. Pour ce faire, procdez comme suit : 1. Cochez loption Primary Key Generation 2. Spciez la stratgie par dfaut, Auto. 3. Laissez le champ Generator Name vide. 4. Mappez les attributs restants avec leurs correspondants dans la table de la base (en particulier, pour lentit Article, les attributs articleCategorie avec ARTICLECATEGORIEID, fournId avec FOURNISSEURID et desc avec DESCRIPTION, et, pour lentit Commande, lattribut etat avec la colonne ETATCOMMANDE). Vous avez achev la premire tape de la conguration. Vous pouvez passer au mapping des types de donnes de chacun des attributs des entits concernes.
274
Embedded Embedded Id Id Many to Many Many to One One to Many One to One Transient Version Le tableau 11.3 dtaille chacune de ces proprits et fournit des exemples dapplication associe chaque situation avec le code annot gnr. Cela vous sera utile pour lapplication des diffrents types de mapping associs votre portion de modle webstock avec Dali.
Tableau 11.3 Proprits du champ Map As
Proprit Description Valeur par dfaut
Basic
Map As
Dnit trois types de mappings : Basic Mapping : correspond lannotation @Basic et ne concer ne que les types de donnes Java de base et les wrappers : string, byte, char, character, date, calendar, time, timestamp, bigDecimal, bigInteger ainsi que tout autre type qui implmente linterface Serializable. Embedded Mapping : utiliser lorsque vous souhaitez mapper un attribut de lentit une instance de type embeddable class, ou classe embarque. Une classe embarque est une classe dont les instances sont stoc kes comme une partie de lentit mre et qui partage lidentiant de cette dernire. Cela correspond lutilisation d@Embedded combine @Attr ibuteOverride, qui permet de surcharger la colonne dun objet embarqu pour une entit donne et sur une proprit particulire. Exemple :
@Embeddable public class EmploymentPeriod { java.util.Date startDate; java.util.Date endDate; ... } @Entity public class Employee implements Serializable { ... @Embedded @AttributeOverrides({ @AttributeOverride(name="startDate", column=@Column("EMP_START")), @AttributeOverride(name="endDate", column=@Column("EMP_END")) ) public EmploymentPeriod getEmploymentPeriod() { ... La classe EmploymentPeriod peut tre embarque dans la classe entit Employee en utilisant les attributs annots @AttributeOverrides.
Mapping JPA avec Dali CHAPITRE 11 Tableau 11.3 Proprits du champ Map As (suite)
Proprit Description Valeur par dfaut Sapplique au mapping suivant
275
Map As (suite)
Embedded Id : permet de spcier la cl primaire dun identiant dentit de type Embeddable. Ce type de mapping correspond @EmbeddedId. Constitu dun ensemble composite de cls primaires appartenant lentit, il se rencontre lorsque le mapping est effectu partir de systmes dit legacy, dont la cl est constitue de plusieurs colonnes. Il sapplique des entits de type embarqu. Exemple :
Embeddable public class EmployeePK implements Serializable { private String name; private long id; public EmployeePK() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public long getId() { return id; } public void setId(long id) { this.id = id; } public int hashCode() { return (int) name.hashCode() + id; } public boolean equals(Object obj) { if (obj == this) return true; if (!(obj instanceof EmployeePK)) return false; if (obj == null) return false; EmployeePK pk = (EmployeePK) obj; return pk.id == id && pk.name.equals(name); } } @Entity public class Employee implements Serializable { EmployeePK primaryKey; public Employee() { }
276
Dveloppement EJB3 avec Eclipse et Web Tools PARTIE III Tableau 11.3 Proprits du champ Map As (suite)
Proprit Description Valeur par dfaut
Basic
Map As (suite)
@EmbeddedId public EmployeePK getPrimaryKey() { return primaryKey; } public void setPrimaryKey(EmployeePK pk) { primaryKey = pk; }
Les relations de type Many-to-One, Many-to-Many, One-to-Many, One-toOne ont ts dcrites dans ce chapitre. Elles gnrent les annotations de support aux relations correspondantes.
Column
Par dfaut, les colonnes sont supposes avoir le mme nom que les attributs de lentit.
Table Fetch
Nom de la table de la BD qui contient le nom de la colonne slectionne. Dnit la stratgie de chargement des donnes de la BD : Eager : les donnes sont charges au pralable avant leur utilisation. Lazy : les donnes sont charges seulement au besoin. Exemple: Eager
@Entity public class Employee implements Serializable { ... @Basic(fetch=LAZY) protected String getName() { return name;
} Optional Temporal Spcie si le champ peut tre null. Spcie si le champ mapp appartient un des types suivants : Date : java.sql.Date Time : java.sql.Time Timestamp : java.sql.Timestamp Ce champ correspond lannotation @Temporal. Exemple : True
@Entity public class Employee { ... @Temporal(DATE) protected java.util.Date startDate; ... }
Mapping JPA avec Dali CHAPITRE 11 Tableau 11.3 Proprits du champ Map As (suite)
Proprit Description Valeur par dfaut Sapplique au mapping suivant
277
Enumerated
Spcie la manire dont les types de donnes Enum vont persister dans la base : Soit vers une colonne ordinale (en stockant le numro ordinal de l'enum). Soit vers une colonne de type chane de caractres (en stockant la chane de caractres reprsentant lEnum). La reprsentation de la persistance, par dfaut ordinale, peut tre surcharge grce l'annotation @Enumerated, comme lillustre la proprit PayScale de lexemple suivant, dans laquelle lEnum persiste en tant que string :
public enum EmployeeStatus {FULL_TIME, PART_TIME, CONTRACT} public enum SalaryRate {JUNIOR, SENIOR, MANAGER, EXECUTIVE} @Entity public class Employee { ... public EmployeeStatus getStatus() { ... } @Enumerated(STRING) public SalaryRate getPayScale() { ...
} Lob Indique que la proprit devrait tre persiste dans un Blob ou un Clob selon son type : java.sql.Clob, Character[], char[] et java.lang.String seront persists dans un Clob. java.sql.Blob, Byte[], byte[] et les types srialisables seront persists dans un Blob. Ce champ correspond lannotation @Lob. Exemple :
@Lob public String getFullText() { return fullText; } @Lob public byte[] getFullCode() { return fullCode; }
Target Entity Mapped By Entit persistante sur laquelle lattribut est mapp. Champ de la table qui possde la relation. Lassociation peut tre bidirectionnelle, et, dans ce cas, une des extrmits doit tre responsable de la mise jour des colonnes de lassociation. Cest l que se mesure lutilit de cet attribut, qui doit tre spci avec @OneToOne dans lentit qui ne dnit pas de colonne de jointure, comme dans lexemple suivant entre lentit Employ et Badge: Tout type de mapping de relation Mapping de relations de type mono values
@Entity public class Employe { @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name="badge_fk") public Badge getBadge() { ... }
278
Dveloppement EJB3 avec Eclipse et Web Tools PARTIE III Tableau 11.3 Proprits du champ Map As (suite)
Proprit Description Valeur par dfaut Sapplique au mapping suivant
Mapping de relations de type mono values
Mapped By (suite)
@Entity public class Badge { @OneToOne(mappedBy = "badge") public Employe getOwner(){ ... }
Spcie si le champ peut tre null. Spcie une colonne mappe pour joindre une entit. Ce champ correspond lattribut @JoinColumn et correspond la colonne de jointure. Fonctionne si lattribut Override Default est coch. Spcie quels types doprations sont propages travers lentit : All : toutes les oprations. Persist : effectue en cascade l'opration de persistance (cration) sur les entits associes si persist() est appele ou si lentit est supervise (par le gestionnaire d'entits). Merge : effectue en cascade lopration de fusion sur les entits associes si merge() est appele ou si l'entit est supervise. Remove : effectue en cascade lopration de suppression sur les entits associes si delete() est appele. Spcie lordre des objets retourns par une requte : No Ordering (liste non ordonne). Primary Key Order (liste trie par la cl primaire). Custom Ordering (ordre spci). Une entit peut hriter des proprits dautres entits comme dans un modle objet classique. Dali permet de spcier une stratgie spcique pour grer ce type de relation : Strategy : Dali propose trois types de stratgies dhritage : Single Table (par dfaut) : toutes les classes dans la hirarchie sont mappes vers une et une seule table ; Joined table : la racine de larborescence est mappe vers une seule table, et toutes les entits lles mappent vers leur propre table ; One Table per class (une table par classe concrte) : chaque classe de la hirarchie dhritage est mappe vers une table. Cette stratgie prend en charge les associations de un vers plusieurs bidirectionnelles mais prsente un certain nombre dinconvnients, en particulier pour les relations polymorphes. La stratgie choisie est dclare au niveau de la classe de lentit la plus haute dans la hirarchie en utilisant l'annotation @Inheritance. Discriminator Column : utilise pour spcier le nom de la colonne discriminante si la stratgie dhritage utilise est de type Single Table ou Joined table. Discriminator Type : utilise pour positionner le type de diffrenciateur Char ou Integer. La proprit Discriminator Value doit se conrmer ce type (par dfaut string). Discriminator Value : spcie la valeur discriminante utilise pour diffrencier une entit dans la hirarchie dhritage (string, char, integer). La valeur doit tre conforme la valeur spcie dans Discriminator Type. Valeur par dfaut string. Ce champs correspond lannotation @DiscriminatorValue. Primay Key Yes
Mapping de type multi valu Mapping de type mono valu Mapping de type multi values et mono values
Cascade
Order by
Inheritance
Single Table
Mapping JPA avec Dali CHAPITRE 11 Tableau 11.3 Proprits du champ Map As (suite)
Proprit Description Valeur par dfaut
Single Table
279
Inheritance (suite)
Exemple
@Entity @Inheritance(strategy=InheritanceType.SINGLE_TABLE) @DiscriminatorColumn( name="Vehiculetype", discriminatorType=DiscriminatorType.STRING ) @DiscriminatorValue("Vehicule") public class Vehicule { ... } @Entity @DiscriminatorValue("Passat") public class Xantia extends Vehicule { ... }
Dans cet exemple, la classe parente Vehicule dnit la stratgie dhritage (single table) et la colonne discriminante laide de lannotation @DiscriminatorColumn. Lannotation @DiscriminatorValue dnit la valeur utilise pour diffrencier la classe dans la hirarchie. Le nom de la colonne discriminante est VehiculeType. @Inheritance et @DiscriminatorColumn devraient seulement tre dnies sur l'entit la plus haute de la hirarchie.
Dali identie automatiquement par dfaut les colonnes des entits construites comme mapping par dfaut. Il faut laisser le mapping basic pour chaque attribut des entits Inventaire, Commande et Article. Pour lattribut dateCommande de lentit Commande, il faut positionner le champ Temporal dans la vue JPA Details Date. La balise @Temporal (DATE) est automatiquement ajoute.
Dans votre modle, le champ article de lentit Inventaire possde une relation One-toOne vers lentit Article, chaque article dinventaire possdant un et un seul article. 1. Dans la vue Package Explorer, ouvrez la classe Inventaire.java. 2. Dans la mme vue, slectionnez le champ article de lentit Inventaire. La vue JPA Details afche les proprits du champ. 3. Dans la liste droulante Map As de la vue JPA Detail, slectionnez la proprit Oneto-One, et laissez les autres proprits par dfaut.
280
4. Cochez loption Overide default, an de spcier la colonne de jointure. Dali propose la dnition de jointure article_ARTICLEID->ARTICLEID. 5. Cliquez sur Edi pour diter la jointure. La bote de dialogue illustre la gure 11.17 safche alors.
Figure 11.17
7. Dans la vue JPA Structure, un symbole safche sur lattribut article, preuve que la relation One-to-One a t prise en compte. 8. Sauvegardez la classe Article.java. Pour transformer cette relation en One-to-One bidirectionnelle, vous devez ajouter un champ relation lentit Article an de pointer en retour sur Inventaire:
@Entity public class Article { // @OneToOne (mappedBy="article") protected Inventaire inventaire; }
281
Mapping One-to-Many
Dans votre modle, lattribut commandes de lentit Client possde une relation de type One-to-Many vers lentit Commande (chaque client peut avoir plusieurs commandes). Lannotation @OneToMany est ajoute a un attribut relation de type Collection, o lentit lautre bout de la relation possde ou non un champ relation ou dispose dune relation monovalue (Many-to-One) qui pointe en retour sur lentit. 1. Slectionnez lentit Client dans la vue Package Explorer. 2. Dans la vue JPA Structure, slectionnez le champ commandes, puis, dans le champ Map As, choisissez One-to-Many. 3. Dans la liste Mapped By, slectionnez le champ owner de lentit Commande, comme illustr la gure 11.18.
Figure 11.18
282
La vue JPA Structure rete le type de mapping One-to-Many associ au champ commandes (voir gure 11.19).
Figure 11.19
Mapping Many-to-One
Vous avez dni une relation de type mapping retour (back mapping), partir de la relation One-to-Many dnie prcdemment. Ce type de mapping sera de type Many-toOne. Vous pouvez ainsi disposer dune relation bidirectionnelle entre les deux entits. Ce type dassociation sera port par lattribut owner de lentit Commande, que lon pourrait rsumer de la faon suivante : Il existe plusieurs commandes quun client peut passer. 1. ditez lentit Commande partir de la vue Package Explorer, si ce nest dj fait. 2. Dans la vue JPA Structure, slectionnez le champ owner de lentit Commande. 3. Dans le champ Map As, slectionnez Many-to-One, et cochez loption Override Default. 4. ditez la colonne de jointure pour quelle fasse rfrence explicitement la cl trangre CLIENTID de lentit Client (voir gure 11.20), et laissez les autres champs inchangs.
Figure 11.20
283
5. Sauvegardez vos modications. 6. Vriez la prise en compte par Dali de la relation ainsi dnie en examinant le symbole port par le champ owner. Voici le code gnr par Dali en fonction de la relation Many-to-One :
Public class Commande { @Id @Column (name=?NUMEROCOMMANDE?) @GeneratedValue protected long numCommande; @Temporal (DATE) protected Date dateCommande; protected Article article; protected int quaantite; @Column (name=?ETATCOMMANDE?) protected String etat; @ManyToOne(optional=false) @JoinColumn(name="CLIENTID", referencedColumnName = "clientId") protected Client owner; }
En utilisant un type de collection gnrique, comme <Commande>, Dali est capable de dterminer le type dentit lautre bout de la relation, avantage apprciable pour la productivit du dveloppeur JEE. Tout ce qui reste rsoudre en termes de rfrence de mapping pour la partie @OneToMany de la relation est le nom de la proprit sur cette entit, dans votre cas owner.
Cette modication a pour effet dajouter un symbole devant lattribut Version dans la vue JPA Structure. Vous avez achev le mapping des entits de votre modle. Vous pouvez passer ltape de dnition des requtes nommes (named queries) associes aux entits du modle mtier.
284
Une entit peut dclarer des instructions JPQL au sein des annotations @NamedQuery pour dnir des requtes rutilisables . Les noms @NamedQuery dnis doivent tre uniques au niveau de lunit de persistance. La requte ndCommndeByNumCommande possde un paramtre, numcommande, mais elle peut galement prendre un paramtre index, comme la requte ndCommandeByEtat prcdente.
Liaison des paramtres de la requte
Les requtes nommes peuvent prendre des paramtres lors de leur invocation ou des paramtres indexs. En supposant que la requte FindClientByUserid dnie plus haut soit appele partir dun code client de type bean session, vous aurez :
@Stateless public class GestionCommandeClient implements CommandeMgr { @PersistenceContext(unitName = "MonProjetJPA-Unit") private EntityManager em; /** <code>select o from Commande o</code> */ public List<Commande> CommandeFindAll() { return em.createNamedQuery("Commande.findAll").getResultList(); }
285
/** <code>select o from Commande o where numcommande = :numcommande</code> */ public List <Commande> FindByNumCommande(Object numcommande) { return em.createNamedQuery("Client.findCommandeByNumeroCommande") .setParameter("numcommande",numcommande).getResultList(); } }
Intgration des entits du modle logique et mise en uvre dun bean client faade
Une fois le modle logique conu avec les diffrentes entits correspondantes selon une approche de conception top-down ou bottom-up (conception partant du modle logique ou inversement partant du schma physique sous-jacent), il importe dinvoquer vos entits conues avec Dali partir dun client Java. Pour ce type de conception, vous vous appuierez sur un classique bean session, qui va servir de faade pour vos entits du modle. Le bean session CommandeManager (voir le code source complet sur la page Web ddie louvrage) expose les oprations CRUD sous forme de service, permettant aux clients daccder aux entits Client et Commande. Vous pourrez implmenter selon le mme canevas les oprations de traitement CRUD entre les entits Inventaire et Article, mais en utilisant cette fois la relation One-to-One. Les services offerts par le bean session faade autorisent la gestion transactionnelle et le maintien de la liaison entre les entits du domaine et la base sous-jacente.
286
public int getClientId() { return clientId; } public void setClientId(int clientId) { this.clientId = clientId; } public int getUserid() { return userid; } public void setUserid(int userid) { this.userid = userid; } public String getClientNom() { return clientNom; } public void setClientNom(String clientNom) { this.clientNom = clientNom; } public String getClientPrenom() { return clientPrenom; } public void setClientPrenom(String clientPrenom) { this.clientPrenom = clientPrenom; } public String getAdresse() { return adresse; } public void setAdresse(String adresse) { this.adresse = adresse; } public String getTelNumero() { return telNumero; } public void setTelNumero(String telNumero) { this.telNumero = telNumero; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; }
287
public int getVersion() { return version; } public void setVersion(int version) { this.version = version; } public Collection <Commande> getCommandes() { return commandes; } public void setCommandes(Collection <Commande> commandes) { this.commandes = commandes; }
} @Entity @Table(schema="WEBSTOCK") public class Commande { @Id @Column(name="NUMEROCOMMANDE") @GeneratedValue protected long numCommande; @Temporal(DATE) protected Date dateCommande; protected Article article; protected int quantite; @Column(name="ETATCOMMANDE") protected String etat; @ManyToOne(optional=false) @JoinColumn(name="CLIENTID", referencedColumnName = "clientId") protected Client owner;
public long getNumCommande() { return numCommande; } public void setNumCommande(long numCommande) { this.numCommande = numCommande; } public Date getDateCommande() { return dateCommande; } public void setDateCommande(Date dateCommande) { this.dateCommande = dateCommande; } public Article getArticle() { return article; } public void setArticle(Article article) { this.article = article; }
288
public int getQuantite() { return quantite; } public void setQuantite(int quantite) { this.quantite = quantite; } public String getEtat() { return etat; } public void setEtat(String etat) { this.etat = etat; } public Client getOwner() { return owner; } public void setOwner(Client owner) { this.owner = owner; } }
289
/** <code>select o from Client o</code> */ public List<Commande> queryCommandeFindAll() { return em.createNamedQuery("Commande.findAll").getResultList(); } public void removeCommande(Commande commande) { commande = em.find(Commande.class, commande.getNumCommande()); em.remove(commande); } /** <code>select o from Client o where userid = :userid</code> */ public List<Client> queryClientFindByUserid(Object userid) { return em.createNamedQuery("client.findByuserid").setParameter("userid", userid).getResultList(); } }
import java.util.List; import javax.ejb.Remote; @Remote public interface CommandeMgr { Object mergeEntity(Object entity); Object persistEntity(Object entity); List<Client> queryClientFindAll(); void removeClient(Client client); List<Commande> queryCommandeFindAll(); void removeCommande(Commande commande); List<Client> queryClientFindByuserid(Object userid); }
Voici le chier de persistance associ, adapt un dploiement nal sur la base de donnes Derby :
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation ="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/ persistence_1_0.xsd"> <persistence-unit name="default" transaction-type="RESOURCE_LOCAL"> <class>org.eclipse.dali.example.jsf.inventory.model.Inventory</class> <class>com.webstock.chap10.Article</class> <class> com.webstock.chap10..Inventaire> <class> com.webstock.chap10.Commande </class> <classe> com.webstock.chap10.Client </class> <properties> <property name="toplink.logging.level" value="FINEST"/> <property name="toplink.jdbc.driver" value ="org.apache.derby.jdbc.ClientDriver"/>
290
<property name="toplink.jdbc.url" value="jdbc:derby://localhost:1527/WebStockDB; create=true"/> <property name="toplink.jdbc.user" value="dali"/> <property name="toplink.jdbc.password" value="dali"/> </properties> </persistence-unit> </persistence>
Enn, voici un extrait du code client de test invoqu partir dune instance dune JVM sur les mthodes distantes du bean :
public class CommandeClient { public static void main(String [] args) { try { final Context context = getInitialContext(); CommandeMgr commandeMgr = (CommandeMgr)context.lookup ("java:comp/env/ejb/CommandeManager"); // Invocation des methodes distantes du bean commandeMgr.mergeEntity( entity ); commandeMgr.persistEntity( entity ); System.out.println(commandeMgr.queryClientFindAll( ) ); System.out.println(commandeMgr.queryCommandeFindAll( ) ); } catch (Exception ex) { ex.printStackTrace(); } } }
Vous pouvez rcuprer sur la page Web ddie louvrage le code complet de ces extraits et les dployer sur le serveur JBoss 4 en utilisant les scripts Ant de dploiement prvus.
En rsum
Ce chapitre vous a permis de mettre en uvre loutillage Dali pour le mapping O/R ainsi que les concepts ayant trait lutilisation de lAPI JPA. Le chapitre suivant vous fournira loccasion de mettre prot tous ces concepts la lumire dune approche de dveloppement centre sur les modles et automatise, avec la solution EclipseUML de lditeur Omondo.
12
Mise en uvre de lapplication webstock
Dans ce chapitre, vous allez mettre en uvre ltude de cas webstock laide des technologies EJB3/JSF, en suivant une dmarche de dveloppement MDA (Model Driven Architecture), ou pilote par le modle.
www.omondo.com).
Vous utiliserez pour loutil de conception EclipseUML, de lditeur Omondo (http:// Ce dernier couvre dsormais lintgralit du cycle de dveloppement JEE et permet de gnrer une grande partie du code de lapplication grce au gnrateur de code Java AndroMDA. An de construire ltude de cas avec EJB3, vous vous appuierez sur le projet Web Tools. Vous complterez ainsi votre panoplie du parfait dveloppeur JEE. Rappelons quEclipseUML Studio, disponible sur plate-forme Windows/Linux et Eclipse 3.3 Europa, est entirement gratuit. La version payante Eclipse Studio offre toutefois la possibilit dexporter certains diagrammes et de gnrer une documentation projet. Un certain nombre de concepts cls comme la notion de mthodologie MDA, de strotypes, de prols UML et de modlisation UML2 seront rappels. Pour en savoir plus, voir la documentation mentionne en annexe.
Larchitecture MDA
La dmarche de dveloppement MDA, concept trs en vogue dans les projets J2EE/JEE actuels, sera mise en uvre dans ce chapitre avec latelier EclipseUML for JEE. Soutenue par lOMG (Object Management Group), MDA (Model Driven Architecture) vous permet de modliser votre application indpendamment de son implmentation cible (niveau matriel ou logiciel), permettant ainsi une bonne rutilisation de vos modles. Cette approche de dveloppement couvre lensemble du cycle du projet, de la conception au dploiement. Elle sappuie sur une association des modles crs, ou PIM (Platform Independant Model), qui reprsentent laspect mtier, avec des modles PM (Platform Model),
292
transforms pour obtenir in ne un modle dapplication spcique, dit PSM (Platform Specic Model). La gure 12.1 illustre larchitecture de lapproche MDA.
Figure 12.1
Approche MDA
Des outils de gnration automatique de code permettent de crer le programme directement partir des modles. En rsum, la mise en uvre de MDA est entirement fonde sur les modles et leurs transformations. Le fait quelle soit indpendante de toute plate-forme assure un dveloppement portable des langages et technologies sous-jacentes.
293
AndroMDA est un puissant gnrateur, qui permet, partir dun modle mtier spci en UML, de gnrer une grande partie des couches ncessaires la construction dune application Java, et ce indpendamment de la technologie sous-jacente. La gnration de code commence par la modlisation dun PIM (Plateform Independant Model), gnralement laide dUML. Ce PIM est ensuite traduit en PSM laide des cartouches du gnrateur de code (templates). Le PSM reprsente le code de lapplication.
294
Les cartouches gnrent du code en fonction du strotype et des valeurs balises appliques aux lments du modle. Comme vous le verrez, un ensemble de prols UML ont t dvelopps pour dsigner ces lments et les classier.
Notion de prol Un prol est une extension du mtamodle UML permettant dajouter de nouveaux types et dinclure des caractristiques relatives un domaine particulier. C'est un jeu de strotypes, de valeurs balises et de contraintes OCL (Object constraint langage) permettant dafner les lments du modle. AndroMDA a dni un prol pour chacune des couches des applications JEE. Vous les utiliserez au fur et mesure de la modlisation de lapplication webstock.
La gure 12.3 donne un aperu de latelier EclipseUML : Zone 1 : diteur de classes de latelier. Zone 2 : vue Outline panoramique de lditeur ouvert en mode dition. Zone 3 : afche le code Java de la classe sur laquelle lutilisateur opre. Rappelons quEclipseUML assure une synchronisation entre le code et le modle. Zone 4 : vue Front and Colors permettant dditer laspect visuel des lments des diffrents diagrammes. Zone 5 : vue Properties offrant un accs rapide aux proprits des lments du diagramme de classes. Zone 6 : vue Explorateur des modles des projets de modlisation.
Figure 12.3
Atelier EclipseUML
295
AndroMDA Il est recommand de se documenter sur loutil de gnration AndroMDA (http://www.andromda.org), qui sappuie sur un certain nombre de strotypes. Voir en particulier lexcellente traduction de Getting Started with AndroMDA for Java par Sbastien Arbogast, disponible ladresse ftp://ftp-developpez.com/
sarbogast/chiers/andromda-intro.pdf.
Lapplication webstock
Webstock est une application simple de gestion dun stock darticles destine illustrer les aspects avancs du dveloppement JEE.
Cette application couvre les besoins de la chane de vente darticles et de pices dtaches informatiques WebStore. Ces besoins peuvent slargir la consultation du systme central de la chane de magasins. Dans le cadre des tapes de cration de lapplication, le cycle MDA devrait comprendre les itrations suivantes : Modlisation UML du contexte mtier du domaine webstock Srialisation et export XMI du modle UML Gnration de code Dploiement et tests Dans un premier temps, vous allez vous focaliser sur la modlisation de lapplication et sur le modle mtier correspondant.
Environnement de travail
Votre environnement de dveloppement sera Eclipse 3.3 avec Web Tools. Pour les besoins de ltude de cas, les prrequis sont les suivants : EclipseUML version free pour Europa, tlchargeable ladresse http://www.ejb3.org/. Web Tools 2, la version compatible Eclipse 3.3, rcuprable partir du site Eclipse, ladresse http://www.eclipse.org/Web Tools/. JBoss 4.2.1, pour un dploiement supportant EJB3.
la gnration du code, EclipseUML fournit lossature dune application n-tiers selon les bonnes pratiques JEE (en particulier en sappuyant sur les principaux modles de conceptions existants, dont un certain nombre sont abords dans ce chapitre).
296
Le modle MVC est inhrent votre application. Pour une meilleure performance de la dmarche MDA, vous vous focaliserez sur la modlisation des diffrents comportements de chacune des couches. Pour ce faire, vous utiliserez les trois diagrammes de base suivants : diagrammes de use cases, pour expliciter les points dentre de lapplication et son interaction avec lutilisateur physique ; diagrammes de classes, pour exprimer le modle mtier de lapplication ainsi que les DAO ; diagrammes dtat, pour expliciter le droulement du processus mtier pour chacun des use cases du modle.
Modle mtier
Pour crer votre modle mtier de lapplication webstock compose de beans entit EJB3 (voir gure 12.4), commencez par crer un projet Java usuel laide dEclipse. 1. Dans le rpertoire source, crez un nouveau rpertoire appel, par exemple, book.webstock.entities. Ce dossier contiendra lensemble de vos entits. 2. Dans la vue Package Explorer, faites un simple clic sur le dossier que vous venez de crer. 3. Cliquez sur File, New, Other, UML Diagrams et UML Class Diagram. 4. Saisissez le nom de votre diagramme. 5. Dans lditeur qui safche, modlisez vos entits comme illustr la gure 12.3.
Figure 12.4
297
Cration des beans entit EJB3 Un bean entit EJB3 sous EclipseUML est une classe portant le strotype Persistence::Entity.
1. Dans la palette de lditeur du diagramme de classes en cours, cliquez sur le bouton Cration dune classe. 2. Dans la fentre qui safche, entrez le nom de votre entit. 3. Pour appliquer le strotype correspondant, faites un clic droit sur la classe EJB. 4. Dans le menu qui souvre, cliquez sur properties. 5. Dans longlet Stereotype de la fentre properties, cliquez sur New Stereotype pour choisir le strotype appliquer : pour les entits Persistence::Persistence. Ces tapes sont rsumes la gure 12.5.
Figure 12.5
298
Cas dutilisation
Vous allez dcomposer votre modle en un ensemble cohrent de cas dutilisation. Tout cas dutilisation doit porter le strotype FrontEndUseCase. Un seul dentre eux sera apte porter le strotype FrontEndApplication. Ce strotype dsignera la page daccueil, home ou index, de votre application, ici la page Liste des clients. Plusieurs cas dutilisation sont prvoir pour lapplication webstock, notamment les suivants : Ajout/Suppression et afchage de chacune des entits de lapplication WebStock. Login, permettant de se connecter via un login/password lapplication. Pour crer ces use cases avec EclipseUML, procdez comme suit : 1. Cliquez sur File, New, Other et UML Use Case Diagram. 2. Entrez le nom du diagramme dans la fentre qui safche. 3. Cliquez sur le bouton Package de la palette de lditeur du diagramme de use case pour crer un nouveau package destin contenir un de vos cas dutilisation. 4. Une fois le package cr, dessinez le use case lintrieur de celui-ci. 5. Appliquez le strotype Presentation::FrontEndUseCase partir de la vue properties. 6. Appliquez le strotype Presentation::FrontEndApplication pour dsigner le use case reprsentant le point dentr par dfaut de votre application (voir gure 12.6).
Figure 12.6
299
Pensez donner des noms explicites vos use cases, car ceux-ci vont reprsenter les lments du menu gnral de lapplication.
Services de lapplication webstock
Lutilisation de beans session permet de proposer des services la couche mtier. Vous utiliserez le classique pattern faade quimplmentent les beans session pour fournir une interface pour les beans entit an de limiter le nombre dappels distants ces objets. Vous crerez, pour chacun des beans entit, un bean service qui interfacera tous leurs accs. Les services reprsenteront la passerelle entre la couche prsentation et la couche mtier de lapplication. Citons parmi eux les services ClientsService et WebStockAccessService : ClientService est un bean session sans tat interfaant lentit Client pour encapsuler les appels CRUD cet objet. WebStockAccessService est un bean session avec tat permettant de se connecter lapplication webstock via un login/mot de passe.
Palette EclipseUML Pour modliser ces beans, EclipseUML offre une palette intuitive et congurable mettant disposition de nouveaux lments dj strotyps pour EJB, Hibernate, JSF, Struts et les Web Services.
Pour activer un de ces menus, il suft de faire un clic droit sur le fond du diagramme puis, dans le menu Prfrences PSM, de choisir les technologies qui vous intressent. Dans votre cas, vous activerez EJB pour AndroMDA et JSF. La gure 12.7 illustre la palette EJB de lditeur de diagramme de classes EclipseUML.
Figure 12.7
Pour modliser ces services, vous pouvez galement dessiner une classe Java usuelle en lui appliquant le strotype Service::Service partir du menu Properties.
300
Les contrleurs sont des classes permettant de faire communiquer la couche Web et la couche mtier. Vous allez modliser un contrleur pour chacune des requtes susceptibles dtre lances par lutilisateur. Vous disposerez ainsi dun contrleur pour chaque use case, comme lillustre la gure 12.8.
Figure 12.8
1. Faites un clic droit sur la classe reprsentant le contrleur dans le diagramme de classes. 2. Dans le menu pop-up qui safche, choisissez Liens et Lien Interface Web. 3. Dans la fentre qui souvre, cherchez dans le menu droulant le use case en question pour le slectionner. 4. Cliquez sur OK. Un nouveau strotype va tre appliqu cette classe, portant linformation du use case dont elle assure le traitement.
301
La gure 12.9 illustre lattribution du contrleur ListeClientsController au cas dutilisation Liste des clients.
Figure 12.9
Diagrammes dtat
Vous allez raliser un diagramme dtat pour chacun de vos cas dutilisation an dexpliciter leur comportement et de redessiner laspect dynamique du systme. La palette graphique EclipseUML pour les diagrammes dtat est assez riche. Elle donne accs plusieurs des lments illustrs la gure 12.10.
Figure 12.10
302
Rappelons quelques notions de base sur les diagrammes dtat : Un diagramme dtat doit obligatoirement avoir un point de dpart, lequel doit possder une ou deux transitons qui en drivent. Chaque tat du diagramme reprsente un tat donn du processus mtier modliser. Les tats qui demandent une interaction utilisateur avec le systme doivent porter le strotype Presentation::FrontEndView. Les tats qui dsignent un comportement ct serveur ne sont pas censs porter un strotype. Vous devez ajouter un vnement, ou effect , aux transitions issues dun tat strotyp FrontEndView. Un effect doit passer des paramtres de ltat source ltat destination. Les strotypes appliqus sur les attributs dune transition dun tat ct client spcient le type dafchage de ceux-ci dans le formulaire correspondant. Sil existe un tat nal, il doit porter le nom du use case implment par le diagramme. La gure 12.11 illustre le diagramme dtat associ au cas dutilisation Ajout dun nouveau client. La gure illustre vos trois tats intermdiaires : Dbut Ajout Client, Formulaire ajout client et Persister nouveau client. Le deuxime reprsente un formulaire de saisie des paramtres du nouveau client et est donc associ la couche de prsentation. Pour cette raison, lui est appliqu le strotype Presentation::FrontEndView. Dans le troisime tat, vous allez excuter la mthode ajoutClient du contrleur AjoutClientController, qui implmente le cas dutilisation Ajout dun nouveau client. Pour avoir accs cette mthode via ce diagramme dtat, il faut dabord attribuer ce diagramme au cas dutilisation quil reprsente. Il suft pour cela de faire un clic droit sur le cas dutilisation, puis, dans le menu droulant, de choisir Liens et Liens Struts/JSF, et enn de slectionner le diagramme dtat dsign.
303
La gure 12.12 illustre ce processus. Pour raliser votre diagramme dtat, procdez de la faon suivante : 1. Commencez par dessiner les diffrents tats du diagramme en utilisant les lments de la palette de lditeur correspondant. 2. Crez les diffrents tats (environ cinq) concernant le processus Ajout client, y compris les tats initiaux et naux. 3. Appliquez le strotype FrontEndView ltat Formulaire ajout client via le menu Properties accessible par clic droit sur celui-ci (voir gure 12.12).
Figure 12.12
304
4. Crez les transitions entre les diffrents tats. Puisque ltat Formulaire ajout client reprsentera une page Web, il devra passer des paramtres ltat suivant, lesquels reprsentent les champs du formulaire afchs sur cette page. Pour ce faire, vous devez ajouter un effet sur la transition qui en drive. 5. Pour ajouter un effet la transition persisterClient, faites un clic droit sur la transition, puis choisissez Ajouter Behavior et Effect. 6. Donnez un nom leffet, par exemple AjoutParamsEffect. Dans ltat Persister Nouveau Client, vous allez excuter la mthode AjoutClient du contrleur AjoutClientController. Cette mthode utilisera les paramtres transmis par la transition entrante laquelle vous venez dattribuer leffet. 7. Ouvrez la fentre Properties de ltat en question, accessible via son menu pop-up correspondant. 8. Choisissez longlet Connection pour ajouter une nouvelle activit qui reprsentera la mthode du contrleur excuter en franchissant ltat en cours. 9. Dans la fentre de dnition de la nouvelle activit, saisissez le nom de lactivit et son type, et spciez le moment de son excution et lopration excuter. 10. Cliquez sur New Opration pour pointer vers lopration AjoutClient de la classe AjoutClientController. La gure 12.13 illustre le processus dajout dune nouvelle activit un tat du diagramme.
Figure 12.13
Vous allez maintenant vrier leffet que vous venez dajouter la transition issue de ltat Formulaire ajout client. 11. Choisissez Properties dans le menu pop-up de leffet. Observez les paramtres de leffet (au nombre de quatre) : nom, prnom, adresse et tlphone (voir gure 12.14). Ces paramtres sont ceux que prend la mthode
305
AjoutClient qui va sexcuter dans ltat cible de cette transition et qui devront tre saisis dans le formulaire de ltat source. Par dfaut, le gnrateur gnre pour ltat Formulaire ajout client un formulaire dont les champs sont des textes. Il est possible de changer le type des champs en appliquant des valeurs balises sur ces derniers. 12. Pour ce faire, slectionnez le paramtre en question et, dans la partie Parameter Stereotypes, choisissez une valeur balise du strotype Presentation::Presentation (voir gure 12.14).
Figure 12.14
306
Cette phase de srialisation est importante. Cest dans cette forme standard que le modle va subir les transformations du gnrateur de code pour vous fournir le corps de votre application.
XMI (XML Metadata Interchange) EclipseUML utilise EMF (Eclipse Modeling Farmework) pour sauvegarder ses modles en XMI. XMI est un des standards sur lesquels repose MDA. Cest une forme standard dnie par lOMG, qui suppose une structuration des modles sous forme XML permettant lchange et le partage des modles et des mtadonnes entre les diffrents outils de modlisation.
307
Figure 12.16
Projet JEE Chacune des couches du projet JEE est compatible Web Tools et na donc pas tre congure an de lui ajouter les bibliothques et descripteurs indispensables. Le gnrateur EclipseUML le fait pour vous.
308
Gnration de code
Cette tape correspond la gnration du code pour un dploiement sur le serveur JBoss. 1. Faites un clic droit sur le chier .uml du projet de modlisation, puis choisissez JEE UML Code Generation et Build all components (voir gure 12.18). 2. Dans lassistant en cours, choisissez le projet que vous venez de crer (cest le projet qui sera choisi pour contenir le code gnr), puis cliquez sur Finish. Vous donnez ainsi la main AndroMDA, qui va lancer son processus de gnration. Ce dernier peut prendre plusieurs minutes. Si aucune erreur de validation du modle nest notie, la gnration seffectue avec succs.
Figure 12.18
Code gnr
Nous nentrons pas ici dans le dtail du code gnr, car les concepts fondamentaux dEJB3 ont t abordes au chapitre prcdent. Par contre, nous donnons quelques extraits de code pour illustrer comment ces notions ont t appliques via les spcications UML.
309
Beans entit
Comme vous venez de modliser vos entits mtier, vous allez passer la concrtisation de votre application et la gnration de code. Pour une meilleure visibilit, la gure 12.19 illustre les classes gnres pour lentit Client. Le diagramme a t obtenu par Reverse UML du code gnr par EclipseUML.
Figure 12.19
Reverse UML EclipseUML supporte plusieurs nouvelles fonctionnalits, dont le Reverse Engineering partir du code source pour obtenir le modle. Le reverse est accessible via le menu pop-up des projets Java UML, puis Create et Update UML Model. Cette fonctionnalit vous permet de garder trace de votre modle, non seulement travers XMI mais aussi travers son code mtier. Vous pouvez ainsi reverser votre code pour obtenir un modle que vous pourrez facilement migrer vers dautres plates-formes cibles.
Le reverse cible plusieurs plates-formes, dont EJB3/2 et Hibernate 3/2. Pour plus dinformations, consultez la documentation EclipseUML (http://www.ejb3.org). La gure 12.20 illustre lassistant EclipseUML pour le reverse JEE. Le reverse est assez dle votre modle de base, tout en tant plus dtaill. Le gnrateur gnre plusieurs notions pour vous sans que vous ayez les modliser ou ajouter des valeurs balises supplmentaires. Le reverse intercepte ces dtails et les reporte au niveau du diagramme. Citons titre dexemple la gnration des ID (identicateurs) pour chaque entit, sachant que, pour modliser une telle proprit pour un bean entit, vous devez ajouter une nouvelle proprit portant la valeur balise Persistence::Identier. Rappelez-vous cependant que
310
vous navez pas effectu de telles manipulations sur vos entits et que le gnrateur a automatiquement gnr un identicateur ainsi que dautres notions, comme les NamedQuery.
Figure 12.20
Reverse JEE
EclipseUML a gnr quatre classes pour chaque entit modlise : La classe du bean entit portant son nom. Un bean session portant le nom du bean suivi du prxe DAOBase. Linterface locale du bean session avec le prxe Dao. Une dernire classe tendant la classe du bean session, que lutilisateur peut utiliser pour ajouter son code propre an de personnaliser le comportement de la session. Cette classe porte le prxe DaoImpl. La classe la plus intressante en termes de code gnr est la classe Commande. Celle-ci possde plusieurs relations avec dautres beans, dont des relations un plusieurs, un un et plusieurs plusieurs. Voici le code de lentit Article:
@javax.persistence.Entity @javax.persistence.Table(name = "ARTICLE")
311
@javax.persistence.NamedQuery(name = "Article.findAll", query = "select article from Article AS article") public class Article implements java.io.Serializable, Comparable<Article> { private static final long serialVersionUID = 1016923637013396942L; // ----------- Attribute Definitions -----------private private private private float poids; java.lang.String nomArticle; java.lang.String description; java.lang.Long id;
// --------- Relationship Definitions ----------private java.util.Set<unnamed.Fournisseur> fournisseur = new java.util.TreeSet <unnamed.Fournisseur>(); private java.util.Set<unnamed.Inventaire> inventaire = new java.util.TreeSet <unnamed.Inventaire>(); private java.util.Set<unnamed.Categorie> categorie = new java.util.TreeSet <unnamed.Categorie>(); private java.util.Set<unnamed.Commande> commande = new java.util.TreeSet <unnamed.Commande>(); /** * Default empty constructor */ public Article() {} /** * Implementation for the constructor with all POJO attributes except auto incremented identifiers. * This method sets all POJO fields defined in this class to the values provided by * the parameters. * * @param poids Value for the poids property * @param nomArticle Value for the nomArticle property * @param description Value for the description property */ public Article(float poids, java.lang.String nomArticle, java.lang.String description) { setPoids(poids); setNomArticle(nomArticle); setDescription(description); } /** * Constructor with all POJO attribute values and CMR relations. * * @param poids Value for the poids property * @param nomArticle Value for the nomArticle property * @param description Value for the description property * @param fournisseur Value for the fournisseur relation * @param inventaire Value for the inventaire relation
312
* @param categorie Value for the categorie relation * @param commande Value for the commande relation */ public Article(float poids, java.lang.String nomArticle, java.lang.String description, java.util.Set<unnamed.Fournisseur> fournisseur, java.util.Set<unnamed.Inventaire> inventaire, java.util.Set<unnamed.Categorie> categorie, java.util.Set<unnamed.Commande> commande) { setPoids(poids); setNomArticle(nomArticle); setDescription(description); setFournisseur(fournisseur); setInventaire(inventaire); setCategorie(categorie); setCommande(commande); } @javax.persistence.Column(name = "POIDS", nullable = false, insertable = true, updatable = true) public float getPoids() { return poids; } /** * Set the poids property. * @param value the new value */ public void setPoids(float value) { this.poids = value; } // limplmentation des autres accesseurs /** * Get the id property. * * @return java.lang.Long The value of id */ @javax.persistence.Id @javax.persistence.GeneratedValue(strategy = javax.persistence .GenerationType.AUTO) @javax.persistence.Column(name = "ID", nullable = false, insertable = true, updatable = true) public java.lang.Long getId() { return id; } /** * Set the id property. * @param value the new value */ public void setId(java.lang.Long value) {
313
this.id = value; } // ------------- Relations -----------------/** * Get the fournisseur Collection * * @return java.util.Set<unnamed.Fournisseur> */ @javax.persistence.ManyToMany(mappedBy = "articles") public java.util.Set<unnamed.Fournisseur> getFournisseur() { return this.fournisseur; } /** * Set the fournisseur * * @param fournisseur */ public void setFournisseur (java.util.Set<unnamed.Fournisseur> fournisseur) { this.fournisseur = fournisseur; } /** * Get the inventaire Collection * * @return java.util.Set<unnamed.Inventaire> */ @javax.persistence.OneToMany(mappedBy = "article", fetch = javax.persistence .FetchType.EAGER) public java.util.Set<unnamed.Inventaire> getInventaire() { return this.inventaire; } /** * Set the inventaire * * @param inventaire */ public void setInventaire (java.util.Set<unnamed.Inventaire> inventaire) { this.inventaire = inventaire; } /** * Get the categorie Collection * * @return java.util.Set<unnamed.Categorie> */ @javax.persistence.ManyToMany() @javax.persistence.JoinTable ( name = "ARTICLE2CATEGORIE",
314
joinColumns = {@javax.persistence.JoinColumn(name = "ARTICLE_IDC", referencedColumnName = "ID")}, inverseJoinColumns = {@javax.persistence.JoinColumn(name = "CATEGORIE_IDC", referencedColumnName = "ID")} ) public java.util.Set<unnamed.Categorie> getCategorie() { return this.categorie; } /** * Get the commande Collection * * @return java.util.Set<unnamed.Commande> */ @javax.persistence.OneToMany() public java.util.Set<unnamed.Commande> getCommande() { return this.commande; } //reste de limplmentation } //fin classe
La deuxime classe intressante est le bean session ArticleDaoBase (gnr pour le bean entit Article), qui implmente les mthodes CRUD donnant accs ce bean entit. Voici le code de cette classe :
/** * <p> * Base EJB3 DAO Class: is able to create, update, remove, load, and find * objects of type <code>unnamed.Client</code>. * </p> * * @see unnamed.ClientDao */ @javax.ejb.TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRED) @javax.ejb.Local({unnamed.ClientDao.class}) public abstract class ClientDaoBase implements unnamed.ClientDao { // ------ Session Context Injection -----@javax.annotation.Resource protected javax.ejb.SessionContext context; // ------ Persistence Context Injection -------/** * Inject persistence context testNG */ @javax.persistence.PersistenceContext(unitName = "testNG") protected javax.persistence.EntityManager emanager; /** * @see unnamed.ClientDao#load(int,)
315
*/ public Object load(final int transform, final java.lang.Long id) throws unnamed.ClientDaoException { if (id == null) { throw new IllegalArgumentException( "Client.load - 'id' can not be null"); } try { final Object entity = (unnamed.Client)emanager. find(unnamed.Client.class, id); return transformEntity(transform, (unnamed.Client)entity); } catch (Exception ex) { throw new unnamed.ClientDaoException(ex); } } /** * @see unnamed.ClientDao#load() */ public unnamed.Client load( final java.lang.Long id) throws unnamed.ClientDaoException { return (unnamed.Client)this.load(TRANSFORM_NONE, id); } /** * @see unnamed.ClientDao#loadAll() */ @SuppressWarnings({"unchecked"}) public java.util.Collection<unnamed.Client> loadAll() throws unnamed.ClientDaoException { return (java.util.Collection<unnamed.Client>)this.loadAll(TRANSFORM_NONE); } /** * @see unnamed.ClientDao#loadAll(int) */ public java.util.Collection loadAll(final int transform) throws unnamed.ClientDaoException { // implmentation } /** * @see unnamed.ClientDao#create(unnamed.Client) */ public unnamed.Client create(unnamed.Client client) throws unnamed.ClientDaoException { return (unnamed.Client)this.create(TRANSFORM_NONE, client); }
316
/** * @see unnamed.ClientDao#create(int transform, unnamed.Client) */ public Object create(final int transform, final unnamed.Client client) throws unnamed.ClientDaoException { if (client == null) { throw new IllegalArgumentException( "Client.create - 'client' can not be null"); } try { emanager.persist(client); emanager.flush(); return this.transformEntity(transform, client); } catch (Exception ex) { throw new unnamed.ClientDaoException(ex); } } /** * @see unnamed.ClientDao#create(java.util.Collection<unnamed.Client>) */ @SuppressWarnings({"unchecked"}) public java.util.Collection<unnamed.Client> create(final java.util.Collection <unnamed.Client> entities) throws unnamed.ClientDaoException { return create(TRANSFORM_NONE, entities); } /** * @see unnamed.ClientDao#create(int, java.util.Collection<unnamed.Client>) */ @SuppressWarnings({"unchecked"}) public java.util.Collection create(final int transform, final java.util .Collection<unnamed.Client> entities) throws unnamed.ClientDaoException { if (entities == null) { throw new IllegalArgumentException( "Client.create - 'entities' can not be null"); } java.util.Collection results = new java.util.ArrayList(); try { for (final java.util.Iterator entityIterator = entities.iterator(); entityIterator.hasNext();) { results.add(create(transform, (unnamed.Client) entityIterator.next())); } }
317
catch (Exception ex) { throw new unnamed.ClientDaoException(ex); } return results; } /** * @see unnamed.ClientDao#create(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) */ public unnamed.Client create( java.lang.String comments, java.lang.String telephone, java.lang.String adresse, java.lang.String prenom, java.lang.String nom) throws unnamed.ClientDaoException { return (unnamed.Client)this.create(TRANSFORM_NONE, comments, telephone, adresse, prenom, nom); } /** * @see unnamed.ClientDao#create(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) */ public Object create( final int transform, java.lang.String comments, java.lang.String telephone, java.lang.String adresse, java.lang.String prenom, java.lang.String nom) throws unnamed.ClientDaoException { unnamed.Client entity = new unnamed.Client(); entity.setComments(comments); entity.setTelephone(telephone); entity.setAdresse(adresse); entity.setPrenom(prenom); entity.setNom(nom); return this.create(transform, entity); } /** * @see unnamed.ClientDao#update(unnamed.Client) */ public void update(unnamed.Client client) throws unnamed.ClientDaoException { if (client == null) { throw new IllegalArgumentException( "Client.update - 'client' can not be null"); } try {
318
emanager.merge(client); emanager.flush(); } catch (Exception ex) { throw new unnamed.ClientDaoException(ex); } } /** * @see unnamed.ClientDao#update(java.util.Collection<unnamed.Client>) */ public void update(final java.util.Collection<unnamed.Client> entities) throws unnamed.ClientDaoException { // implmentation } /** * @see unnamed.ClientDao#remove(unnamed.Client) */ public void remove(unnamed.Client client) throws unnamed.ClientDaoException { if (client == null) { throw new IllegalArgumentException( "Client.remove - 'client' can not be null"); } try { emanager.remove(client); emanager.flush(); } catch (Exception ex) { throw new unnamed.ClientDaoException(ex); } } /** * @see unnamed.ClientDao#remove(java.lang.Long) */ public void remove(java.lang.Long id) throws unnamed.ClientDaoException { if (id == null) { throw new IllegalArgumentException( "Client.remove - 'id' can not be null"); } try { final unnamed.Client entity = this.load(id); if (entity != null) { this.remove(entity); } }
319
catch (Exception ex) { throw new unnamed.ClientDaoException(ex); } } /** * @see unnamed.ClientDao#remove(java.util.Collection<unnamed.Client>) */ public void remove(java.util.Collection<unnamed.Client> entities) throws unnamed.ClientDaoException { // implmentation } protected Object transformEntity(final int transform, final unnamed.Client entity) { // Implmentation de la mthode } protected void transformEntities(final int transform, final java.util .Collection entities) { // Implmentation de la mthode }}
Il est inutile de reporter le code gnr pour les classes ArticleDaoImpl et ArticleDao, qui sont respectivement linterface pour personnaliser le bean session ArticleDaoBase et linterface locale de ce dernier. Le lecteur souhaitant sy plonger peut se reporter au code complet associ ce chapitre, disponible sur la page Web ddie louvrage.
Beans session
La gure 12.21 illustre les classes gnrs pour le bean session ClientsService.
Figure 12.21
320
Les classes gnres sont les suivantes : ClientsServiceBase: classe du bean session. ClientsServiceRemote: interface distante du bean session. ClientsServiceBean: classe implmentant la classe du bean session. Remarquez dans lexplorateur de projets que cette classe se trouve dans le dossier source src/main/java. Cela signie quelle peut tre dite par lutilisateur et quelle ne sera donc pas crase lors de la prochaine gnration de code. La gure 12.22 illustre les classes gnres pour la classe ClientsService modlise.
Figure 12.22
321
// ------ DAO Injection Definitions -------/** * Inject DAO ClientDao */ @javax.ejb.EJB private unnamed.ClientDao clientDao; // --------------- Constructors --------------public ClientsServiceBase() { super(); } // ------ DAO Getters -------/** * Get the injected DAO ClientDao */ protected unnamed.ClientDao getClientDao() { return this.clientDao; } // -------- Business Methods -------------@javax.ejb.TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRED) public void ajoutClient(java.lang.String nom, java.lang.String prenom, java.lang.String adresse, java.lang.String telephone, java.lang.String comments) { // implmentation de la mthode } /** * Performs the core logic for {@link #ajoutClient(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)} */ protected abstract void handleAjoutClient(java.lang.String nom, java.lang.String prenom, java.lang.String adresse, java.lang.String telephone, java.lang.String comments) throws java.lang.Exception; @javax.ejb.TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRED) public void listeDesClients() { implmentation de la mthode } /** * Performs the core logic for {@link #listeDesClients()} */ protected abstract void handleListeDesClients() throws java.lang.Exception; @javax.ejb.TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRED) public void suppressionClient(long id) {
322
implmentation de la mthode } /** * Performs the core logic for {@link #suppressionClient(long)} */ protected abstract void handleSuppressionClient(long id) throws java.lang.Exception; }
Descripteurs gnrs
Trois descripteurs sont gnrs pour la couche mtier ou le projet EJB : ejb-jar.xml (non utile pour un dveloppement EJB3), jboss.xml et persistence.xml, comme lillustre la gure 12.23.
Figure 12.23
La gure 12.24 illustre le descripteur jboss.xml gnr pour lapplication webstock dclarant les beans session de la couche mtier.
Figure 12.24
Descripteur jboss.xml
La gure 12.25 donne un aperu du descripteur ejb-jar.xml de lapplication webstock dclarant les diffrents beans (session et entit) de lapplication.
323
Descripteur ejb-jar.xml
La gure 12.26 illustre une partie du chier de conguration persistence.xml gnr permettant de congurer lunit persistante utilise pour lapplication webstock.
Figure 12.26
Descripteur persistence.xml
Couche Web
Un ensemble de facelets sont gnres pour chacune des pages Web de lapplication. Prenons comme exemple la page dajout dun nouveau client dans la base webstock. Les deux facelets suivantes sont gnres : formulaire-ajout-client.xhtml formulaire-ajout-client-ajout-client-effect.xhtml Voici le code du facelet formulaire-ajout-client.xhtml :
324
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:c="http://java.sun.com/jstl/core"> <ui:composition template="/layout/layout.xhtml"> <ui:define name="title"> <c:set var="title" value="#{messages['formulaire.ajout.client.title']}" scope="request"/> </ui:define> <ui:define name="content"> <ui:include src="/book/webstock/clients/ajout/formulaire-ajout-client-ajoutclient-effect.xhtml"/> </ui:define> </ui:composition> </html>
325
<af:commandButton text="#{messages['ajout.client.effect']}" action="#{ajoutClientController.formulaireAjoutClient AjoutClientEffect}"/> </af:panelButtonBar> </f:facet> </af:panelForm> <a:validator client="false"/> </h:form> </ui:composition> </html>
Laction du bouton de validation de ce formulaire passe la requte la classe ajoutClientController. Cette classe sera personnalise via son implmentation ajoutClientControllerImpl.
Personnalisation du code
Le code produit est sufsamment fonctionnel pour tre dploy sur le serveur JBoss. Prenons lexemple du scnario dinsertion dun nouveau client dans la base. Pour complter ce processus, vous devez diter un certain nombre de classes, dont AjoutClientControllerImpl.java et ClientsServiceBean.java. Les ditions de code tant mineures, nous ne donnons ici que les classes implmenter. Voici limplmentation de la mthode ajoutClient du contrleur AjoutClientControllerImpl:
/** * @see book.webstock.clients.ajout.AjoutClientController */ public class AjoutClientControllerImpl extends AjoutClientController { private static final long serialVersionUID = 1L; /** * @see book.webstock.clients.ajout.AjoutClientController#ajoutClient (java.lang.String nom, java.lang.String prenom, java.lang.String adresse, java.lang.String telephone, java.lang.String comments) */ public void ajoutClient(AjoutClientForm form) { book.webstock.services.ClientsServiceRemote clientsService; try { clientsService = (book.webstock.services.ClientsServiceRemote) ServiceLocator.instance().getService("testNG-1.0.0/ClientsServiceBean/ remote");
326
Vous devez galement implmenter la mthode handleAjoutClient de la classe ClientsServiceBean en accdant au bean ClientDao inject travers le bean session ClientServiceBase. Cela permet daccder sa mthode create(Client), qui cre votre nouveau client et linsre dans la base. Voici le code de la mthode handleAjoutClient:
protected void handleAjoutClient(java.lang.String nom, java.lang.String prenom, java.lang.String adresse, java.lang.String telephone, java.lang.String comments) throws java.lang.Exception { getClientDao().create(comments, telephone, adresse, prenom, nom); }
Une fois que vous avez dit votre code comme indiqu prcdemment, vous devez relancer la gnration de code. Celle-ci met jour vos sources sil y a eu des changements du modle ; sinon, cest une phase de compilation et de packaging (voir gure 12.27).
Figure 12.27
Consultez le dossier target du projet EAR de lapplication EJB3_JSF_WebStock-app. Celui-ci contient larchive EAR ainsi que le chier XML de conguration de la datasource que vous devrez copier dans le dossier de dploiement de votre serveur.
Dploiement sur le serveur JBoss
Vous allez utiliser JBoss comme serveur dapplications. Vous choisirez la version 4.2, qui implmente la spcication EJB3. Cette version est la plus stable actuellement. 1. Copiez lEAR et le cher XML de conguration de la datasource sous les dossiers $JBOSS_HOME/server/default/deploy. 2. Aprs avoir dmarr le serveur, vriez que le dploiement sest achev avec succs. Pour ce faire, voyez si les tables relatives vos entits EJB3 ont t cres automatiquement, comme spci dans le descripteur persistence.xml. 3. Accdez pour cela la base Hypersonic via la console JMX (http://127.0.0.1 :8080/JMXconsole/) en cliquant sur database=localDB,service=Hypersonic puis startDatabaseManager(). La gure 12.28 illustre les tables de lapplication cres avec succs lors du dploiement. 4. Vous pouvez galement vrier si vos beans session ont t dploys avec succs en consultant la liste des rfrences JNDI du serveur via service=JNDIView puis List of MBean operations partir de la console JMX du serveur (voir gure 12.29).
327
Figure 12.29
5. Pour tester votre application, entrez ladresse http://127.0.0.1:8080/EJB3_JSF_WebStock. La page dajout dun nouveau client safche comme page daccueil de lapplication (voir gure 12.30).
328
Figure 12.30
En rsum
Ce chapitre vous a permis de mettre en uvre sur un exemple concret les concepts EJB3 abords au cours des chapitres prcdents. Le processus MDA a t mis en uvre laide de loutil EclipseUML for JEE, qui vous a permis dconomiser vos efforts de codage pour vous concentrer sur la modlisation mtier. Le chapitre suivant traite des fonctionnalits avances de la nouvelle plate-forme Seam de Jboss. Celles-ci permettent dallger le contexte de vos applications par une meilleure collaboration entre la couche Web et la couche mtier.
13
Conguration EJB3 avance avec Seam
Au chapitre prcdent, vous avez bti votre application sur EJB3 et JSF et mis en uvre les innovations apportes par la nouvelle spcication. Dans cet ultime chapitre, vous reprendrez lapplication exemple webstock en partie gnre laide de latelier EclipseUML dOmondo. Vous utiliserez pour ce faire le framework Seam, prsent au chapitre 8, mais cette fois appliqu au dveloppement EJB3. Vous dcouvrirez les aspects avancs de ce framework, en particulier pour la gestion des contextes, un des points forts de Seam.
La possibilit de grer plusieurs conversations simultanes est une fonctionnalit remarquable de Seam permise par le support du contexte conversationnel, qui permet de simuler virtuellement des sessions multiples sans avoir les crer physiquement. Pour Seam, tous les composants dune application en cours dexcution sont des objets avec tat (stateful). Ces objets sont souvent des EJB, comme dans notre exemple.
330
Chaque instance dun composant est associe un contexte dni et possde un nom permettant de la rfrencer. Par dnition, un contexte est une vue sur les composants dune application base de conteneur en cours dexcution, comme lillustre la gure 13.2.
Figure 13.2
Une application Web classique comporte plusieurs contextes traditionnels, comme Session, Requte et Application. Seam ajoute quatre nouveaux contextes au modle existant (voir gure 13.3) : Stateless Conversation Page Processus mtier (Business)
Figure13.3
Les contextes Seam sont crs et dtruits par le conteneur JBoss. Ils ne sont plus contrls avec une API Java spcique, mais grs dune manire explicite, dclare laide des annotation JDK5.
331
Chaque type de composant Seam possde un contexte par dfaut, que le dveloppeur peut modier laide de lannotation @Scope. Le tableau 13.1 rcapitule les contextes par dfaut de Seam.
Tableau 13.1 Contextes par dfaut de Seam
objet
Beans stateless Beans entit Beans session stateful JavaBeans (POJO)
Rappelons brivement les rles des contextes Seam : Stateless. Les objets sans tat vivent dans le contexte Stateless traditionnel dune application Web. Tout JavaBean peut tre dsign comme tant un objet Seam sans tat. Ce contexte est utilis lorsquil nest pas ncessaire de persister ltat du contexte durant plusieurs appels de la classe. Voici un exemple de JavaBean helloworld stateless :
@Name ("statelessHelloWorld") @Scope (ScopeType.STATELESS) public class StatelessHelloWord { @RequestParameter ("nom") String nom; public String getText() { return "Hello World ! " + nom; } }
Event. Cest le contexte le plus simple et le plus utilis dans les applications Web. Les objets enregistrs dans le cadre de ce contexte sont dtruits la n de la requte. Les JavaBeans sont stocks par dfaut dans ce contexte vnementiel. Page. Les composants de ce contexte sont attachs une page spcique. Vous avez accs ces composants pour tout vnement mis partir de cette page. Conversation. Ce contexte est dtaill ultrieurement dans ce chapitre. Session. Gre ltat associ la session utilisateur an de garder trace de certaines informations relatives cet utilisateur et des donnes susceptibles dtre partages entre diffrentes conversations. Business. Cest le contexte associ aux processus mtier de longue dure. Ltat de ce contexte est gr et persist par le moteur de workow JBoss jBPM (JBoss Business Process Management). Rappelons quun processus mtier est un ensemble dactions rparties sur diffrents types dutilisateurs. Ltat de ce contexte est partag entre ces diffrents utilisateurs selon une rglementation dnie. Application. Utilis pour garder les informations statiques relatives une application donne, comme les mtamodles ou les objets de rfrence. Par exemple, Seam persiste ses congurations et mtamodles dans le contexte de lapplication.
332
Gestion des tats de composants Seam Les instances de composants Seam sont associes une variable de contexte. Le nom du composant est attribu via lannotation @Name et le contexte auquel il sera associ laide de lannotation @Scope.
Contexte conversationnel
La conversation est un concept bien connu du dveloppement J2EE. JBoss Seam est toutefois le premier framework limplmenter compltement et lenrichir avec le scope de conversation. Une conversation peut tre vue comme un genre de pas--pas. Cest une action qui stend sur plusieurs petites actions et qui permet a lutilisateur de se promener aisment davant en arrire, sans se soucier de la perte de ses donnes, mais sans pour autant les persister dans la base. Toutes les informations utilises pendant une conversation sont stockes dans le scope de conversation. La notion de conversation est introduite par Seam travers le support de ses nouveaux contextes. Pour Seam, une conversation est une requte utilisateur qui stend sur plusieurs pages avant dtre close. Le panier dachats en ligne en est un exemple. Chaque cycle requte/ rponse est aussi une conversation lmentaire entre la page qui expose le formulaire de la requte et la page de rponse. En dautres termes, une conversation est une unit de travail lmentaire : ce quon fait un moment donn sur une page donne. Par dfaut, les objets Seam avec tat (stateful) ont une conversation de type Scope. Le contexte conversationnel par dfaut se rsume ainsi : le composant est instanci quand la premire page est mise puis est dtruit quand la page de rponse est dnitivement afche. Les composants utilisent des conversations temporaires, qui ont lieu tout au long de la requte avant dtre dtruites lafchage de la page de rponse.
POJO Un POJO Seam qui ne porte que lannotation @Name est un objet avec tat et est enregistr dans le contexte conversationnel du conteneur du serveur dapplications.
333
Figure 13.4
Le premier listener appel est SeamListener (org.jboss.seam.servlet.SeamListener), que vous devez dclarer dans le chier descripteur de lapplication web.xml (voir listing suivant). Ce listener est appel chaque instanciation dune nouvelle session.
<listener> <listener-class> org.jboss.seam.servlet.SeamListener </listener-class> </listener> <!Faces Servlet Maping -- > <servlet-mapping> <servlet-name>faces Servlet</servlte-name> <url-pattern>*.seam</url-pattern> </servlet-mapping>
334
Cest travers cet objet que vous invoquerez la servlet FacesServlet. Ce listener fait partie du cycle de vie de la servlet FacesServlet, comme dcrit dans lextrait suivant (notez le package org.andromda.presentation utilis par AndroMDA pour la gnration JSF avec EclipseUML) :
<lifecycle> <phase-listener> org.andromda.presentation.jsf.MessagePhaseListener </phase-listener> org.jboss.seam.jsf.SeamPhaseListener</phase-listener> </lifecycle>
Pour intgrer Seam la couche mtier, vous devrez utiliser SeamInterceptor an dintercepter les appels aux EJB et composants mtier :
<?xml version="1.0" encoding="UTF-8"?> <ejb-jar xmlns=http://java.sun.com/xml/ns/javaee xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd" version="3.0" <interceptors> <interceptor> org.jboss.seam.ejb.SeamInterceptor</interceptor-class> </interceptor> <interceptors>
La gure 13.5 illustre ce principe dintgration dintercepteurs travers les couches Web et mtier des applications EJB3/JSF.
Figure 13.5
Intercepteurs Seam
Conguration de Seam
Linstallation du framework Seam est dcrite en annexe de louvrage. Dans le cadre de ce chapitre, vous aurez besoin des JAR jboss-seam.jar et jboss-seam-ui-jar que vous copiez sous la racine de votre EAR, sans oublier dajouter ces dpendances au chier application.xml :
<module> <java>jboss-seam.jar</java> </module>
335
Vous disposez prsent dune structure projet prte fonctionner avec Seam. La section suivante reprend certains cas dutilisation de lapplication webstock an de les adapter cette plate-forme.
Figure 13.6
Vous allez reprendre cette chane dinvocation des objets EJB3 an de la refactorer selon le principe Seam. La mthodologie Seam stipule quil faut supprimer tout bean manag pour laisser la main la plate-forme. Il vous est simplement demand dajouter les annotations ncessaires. Voici les listing des diffrentes classes invoques lors du droulement du cas dutilisation aprs leurs adaptation pour une intgration Seam.
336
DataModel Client:
@Name("Client") @javax.persistence.Entity @javax.persistence.Table(name = "CLIENT") @javax.persistence.NamedQuery(name = "Client.findAll", query = "select client from Client AS client") public class Client implements java.io.Serializable, Comparable<Client> { // ----------- Attribute Definitions -----------private private private private private private java.lang.String comments; java.lang.String telephone; java.lang.String adresse; java.lang.String prenom; java.lang.String nom; java.lang.Long id;
// --------- Relationship Definitions ----------private java.util.Set<unnamed.Commande> commande = new java.util.TreeSet <unnamed.Commande>(); @NotNull @Range(min=3, max=100, message="Prenom must be between 3 and 100") @javax.persistence.Column(name = "PRENOM", nullable = false, insertable = true, updatable = true) public java.lang.String getPrenom() { return prenom; } @NotNull @Pattern(regex="^[a-zA-Z.-]+ [a-zA-Z.-]+", message="Vous devez un commentaire")
@javax.persistence.Column(name = "COMMENTS", nullable = false, insertable = true, updatable = true) public java.lang.String getComments() { return comments; } @javax.persistence.Column(name = "TELEPHONE", nullable = false, insertable = true, updatable = true) public java.lang.String getTelephone() { return telephone; } @Length(max=250)
337
@javax.persistence.Column(name = "ADRESSE", nullable = false, insertable = true, updatable = true) public java.lang.String getAdresse() { return adresse; }
La classe Client.java porte lannotation @Name lui permettant davoir un nom dans le contexte Seam. Aucun tag @Scope ntant dclar, le contexte par dfaut est utilis. Dans ce cas, lentit client est enregistre comme tant un objet nomm Client dans le contexte conversationnel Seam. Certaines annotations abordes au chapitre 8 sont utilises ici pour la validation. Elles permettront de dclencher la validation JSF des attributs quelles annotent. Le formulaire Ajout dun nouveau client en est un exemple. La seconde classe modier est le bean session ClientsServiceBean qui dclare toutes les mthodes CRUD relatives au bean Client:
@Name("ClientsServiceBean") @Scope(ScopeType.CONVERSATION) public class ClientsServiceBean extends book.webstock.services.ClientsServiceBase { @In(required=true,create=true) @Out Client client; public Client getClient() { return client; } public void setClient(Client client) { this.client = client; } public void ajouterClient(){ try { getClientDao().create(client); } catch (Exception e) { e.printStackTrace(); } } // --------------- Constructors --------------public ClientsServiceBean() { super(); } }
Le service "ClientsServiceBean" est enregistr comme tant un objet Seam appel ClientsServiceBean vivant dans le scope conversationnel. Remarquez bien linjection du paramtre client dans le bean session.
338
Maintenant que vous avez enregistr vos deux composants dans le contexte conversationnel, vous pouvez les invoquer directement sans passer par les beans manags habituels de JSF. Pour ce faire, reprenez votre facelet ajoutClient.xhtml pour une refactorisation Seam. Voici le code du facelet avant refactoring :
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:c="http://java.sun.com/jstl/core" xmlns:t="http://myfaces.apache.org/tomahawk" xmlns:a="http://www.andromda.org/cartridges/jsf" xmlns:af="http://xmlns.oracle.com/adf/faces"> <ui:composition> <h:form id="ajoutDUnNouveauClientFormulaireAjoutClientAjoutClientEffectForm" enctype="multipart/form-data"> <af:panelForm> <af:inputText id="nom" value="#{ajoutDUnNouveauClient FormulaireAjoutClientAjoutClientEffectForm.nom}" label ="#{messages['nom']}:" required="false" readOnly="false"> </af:inputText> <af:inputText id="prenom" value="#{ajoutDUnNouveauClient FormulaireAjoutClientAjoutClientEffectForm.prenom}" label ="#{messages['prenom']}:" required="false" readOnly="false"> </af:inputText> <af:inputText id="adresse" value="#{ajoutDUnNouveauClient FormulaireAjoutClientAjoutClientEffectForm.adresse}" label ="#{messages['adresse']}:" required="false" readOnly="false"> </af:inputText> <af:inputText id="telephone" value="#{ajoutDUnNouveauClient FormulaireAjoutClientAjoutClientEffectForm.telephone}" label ="#{messages['telephone']}:" required="false" readOnly="false"> </af:inputText> <af:inputText id="comments" value="#{ajoutDUnNouveauClient FormulaireAjoutClientAjoutClientEffectForm.comments}" label ="#{messages['comments']}:" required="false" readOnly="false" rows="3" columns="40"> </af:inputText> <f:facet name="footer"> <af:panelButtonBar> <af:commandButton text="#{messages['ajout.client.effect']}" action="#{ajoutClientController.formulaireAjoutClient AjoutClientEffect}"/> </af:panelButtonBar> </f:facet> </af:panelForm> <a:validator client="false"/> </h:form> </ui:composition> </html>
Le code du facelet aprs sa refactorisation est le suivant (remarquez au passage que le code est plus compact) :
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"
339
xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:c="http://java.sun.com/jstl/core" xmlns:t="http://myfaces.apache.org/tomahawk" xmlns:a="http://www.andromda.org/cartridges/jsf" xmlns:af="http://xmlns.oracle.com/adf/faces"> <ui:composition> <h:form > <af:panelForm> <af:inputText id="nom" value="#{Client.nom}" label="#{messages['nom']}:" required="false" readOnly="false"> </af:inputText> <af:inputText id="prenom" value="#{Client.prenom}" label="#{messages['prenom']}:" required="false" readOnly="false"> </af:inputText> <af:inputText id="adresse" value="#{Client.adresse}" label="#{messages['adresse']}:" required="false" readOnly="false"> </af:inputText> <af:inputText id="telephone" value="#{Client.telephone}" label="#{messages['telephone']}:" required="false" readOnly="false"> </af:inputText> <af:inputText id="comments" value="#{Client.comments}" label="#{messages['comments']}:" required="false" readOnly="false" rows="3" columns="40"> </af:inputText> <f:facet name="footer"> <af:panelButtonBar> <af:commandButton text="#{messages['ajout.client.effect']}" action="#{ClientsServiceBean.ajouterClient}"/> </af:panelButtonBar> </f:facet> </af:panelForm> <a:validator client="false"/> </h:form> </ui:composition> </html>
Maintenant que tout est prt, il ne vous reste qu ajouter le chier components.xml pour JBoss Seam, comme dans le listing suivant :
<?xml version="1.0" encoding="UTF-8"?> <components xmlns="http://jboss.com/products/seam/components" xmlns:core="http://jboss.com/products/seam/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation= "http://jboss.com/products/seam/core http://jboss.com/products/seam/ core-1.1.xsd http://jboss.com/products/seam/components http://jboss.com/ products/seam/components-1.1.xsd"> <core:ejb installed="false"/> <component name="client" class="unnamed.Client" scope="CONVERSATION"/> <component name="ClientsServiceBean"
340
Ce chier doit se trouver sous le rpertoire META-INF du projet EJB. Il utilise ici une description minimale pour dclarer les objets Seam (noms, classes et contexte correspondant). Le code complet est disponible sur la page Web ddie louvrage. Tout est prt pour excuter lapplication webstock avec son revtement Seam. Vous navez plus besoin de passer par les beans manags ni par les contrleurs, vitant ainsi les redondances et laissant Seam grer en toute transparence les synchronisations entre les couches mtier et Web. La gure 13.7 illustre votre use case aprs lintgration Seam.
Figure 13.7
Conversation Seam
Vous allez prsent appliquer une conversation Seam lapplication WebStock. Vous prendrez cette fois le cas classique du Login, ou identication lapplication. Voici le listing du bean session WebStockAccessServiceBean :
@javax.ejb.TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRED) @javax.ejb.Remote({book.webstock.services.WebStockAccessServiceRemote.class}) @Scope(ScopeType.CONVERSATION) @Name(WebStockAcess) public class WebStockAccessServiceBean extends book.webstock.services.WebStockAccessServiceBase {
341
// ------ Session Context Injection -----@javax.annotation.Resource protected javax.ejb.SessionContext context; @In @Out WebstockAccess user; @In FacesMessages facesMessages;
@RequestParameter("login") String login; @RequestParameter ("password") String password; // ------ Persistence Context Definitions -------/** * Inject persistence context EJB3_JSF_SEAM_Webstock */ @javax.persistence.PersistenceContext(unitName = "EJB3_JSF_SEAM_Webstock") protected javax.persistence.EntityManager emanager; // ------ DAO Injection Definitions -------/** * Inject DAO WebstockAccessDao */ @javax.ejb.EJB private WebstockAccessDao webstockAccessDao; // --------------- Constructors --------------public WebStockAccessServiceBase() protected WebstockAccessDao getWebstockAccessDao() { return this.webstockAccessDao; } // -------- Business Methods -------------/** * */ @Begin @javax.ejb.TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRED) public boolean login(java.lang.String login, boolean password) { try { return this.handleLogin(login, password); } catch (Throwable th) {
342
throw new book.webstock.services.WebStockAccessServiceException( "Error performing 'book.webstock.services.WebStockAccessService .login(java.lang.String login, boolean password)' --> " + th, th); } } /** * Rechercher le user ayant ce login et ce password pour voir */ Public WebStockAccess getUser(login, password){ return getWebstockAccessDao.findUser(login, password); } @End public void displayLoginResult(){ if (user==null) facesMessages.add("Error login action"); else{facesMessages.add("you're logged in");} } /** * Performs the core logic for {@link #login(java.lang.String, boolean)} */ protected abstract boolean handleLogin(java.lang.String login, boolean password) throws java.lang.Exception; public void logOut(WebstockAccess user){ try { handlelogOut(user); } catch (Throwable th) { throw new book.webstock.services.WebStockAccessServiceException( "Error performing 'book.webstock.services.WebStockAccessService .logout(user)' --> " + th, th); } } protected abstract boolean handlelogOut(WebstockAccess user) throws java.lang.Exception;
si a existe
/** * Remove lifecycle method */ @Remove @Destroy public void destroy() { handleDestroy(); } /** * Performs the core logic for {@link #destroy()) */ protected abstract void handleDestroy()}}
343
Le service WebStockAccessServiceBean est un bean session avec tat qui implmente la logique mtier de connexion lapplication webstock via un nom dutilisateur et un mot de passe. La requte de login est lue pour tre conversationnelle selon les termes Seam. Le tableau 13.2 rcapitule les annotations utilises jusquici dans la gestion du contexte Seam (voir en annexe pour plus de dtails).
Tableau 13.2 Annotations de gestion des contextes Seam
Annotation Seam
@Scope(ScopeType.CONVERSATION) @Begin
Description
Permet au bean dtre enregistr dans le contexte conversationnel Seam. Permet de dbuter la conversation Seam si la mthode quelle marque est invoque. Dans le cas du Bean WebStockAccessBean, cest la mthode login(). Permet darrter la conversation si la mthode quelle annote est invoque. Dans ce cas, la mthode displayLoginResult() arrte la conversation. Utilise pour tout clean-up effectu par Seam Informe la plate-forme que le bean session doit tre dtruit aprs linvocation de la mthode quelle marque.
@End
@Destroy @Remove
@Destroy et @Remove Dans Seam, tous les beans session avec tat doivent dclarer une mthode marque @Destroy et @Remove. Cest la mthode EJB Remove() qui est invoque quand Seam dtruit le contexte Session.
En rsum
Tout au long de cette partie consacre au dveloppement EJB3 avec la plate-forme JBoss, vous avez pu apprcier toute la souplesse et la simplicit de la nouvelle norme EJB3, complte par la richesse de lAPI JPA et des sous-projets associs (Dali en particulier). Avec lapport du framework Seam, conjugu une dmarche de dveloppement centre sur le modle avec MDA voir SOA, la spcication EJB3 devrait atteindre toute sa puissance pour le dveloppement dapplications Web 2.0 complexes daujourdhui et de demain.
Annexes
Cette partie comporte trois annexes regroupant un ensemble dinformations synthtiques destines servir de complment cet ouvrage : Annexe A : procdures dinstallation des produits utiliss dans louvrage : Eclipse Europa, SVN et Tortoise SVN, EclipseUML, JBoss 4.2 et Apache Derby. Annexe B : description dtaille des principales annotations du framework Seam. Annexe C : principaux strotypes et valeurs balises du prol EJB 3.0 pour AndroMDA utilis par loutil EclipseUML de lditeur Omondo.
A
Procdures dinstallation
Eclipse Europa
Plate-forme de dveloppement :
Windows 2000 Professionnel, avec ServicePack 2 ou ultrieur. Windows XP Professionnel, Windows Vista. Windows NT Workstation ou Serveur Version 4.0 avec ServicePack 6a ou ultrieur. Linux. MacOS.
JRE (Java Runtime Environment) :
JDK 5 JDK 6
Serveur dapplications :
Derby, Hypersonic Europa est le nom de code de la dernire version nalise dEclipse 3.3, disponible depuis le 29 juin 2007. Plusieurs prols sont offerts pour aider le dveloppeur installer Eclipse avec les outils qui concident avec ses prfrences. Dans notre cas, nous avons choisi le prol du dveloppeur JEE pour Windows. Nous aurons donc un Eclipse enrichi de loutillage Java et comportant WTP, ainsi que loutillage de dveloppement de plug-ins et dapplications RCP. Tlchargement ladresse :
http://www.eclipse.org/downloads/download.php?le=/technology/epp/downloads/release/20070927/eclipsejee-europa-fall-win32.zip
348
JEE5 ANNEXES
La gure A.1 rcapitule les plug-ins disponibles pour les diffrents prols Eclipse (doubles coches : inclus avec le code source ; simples coches : inclus ; coche estompe : partiellement inclus).
Figure A.1
Installation de TortoiseSVN
349
2. Cliquez sur Next puis Install, et attendez la n du processus dinstallation. 3. Cliquez sur Finish. Lassistant vous propose de redmarrer votre poste pour que les changements prennent effet. Reprenez ensuite les tapes de conguration du repository ainsi que du dmarrage du serveur sous forme de service (voir le chapitre 3).
8. La base de donnes est cre dans le rpertoire de lancement de la JVM. 9. Pour excuter un script SQL, par exemple MonScript.sql , entrez :
Ij> run monScript.sql ;
EclipseUML
Pour installer EclipseUML Europa, vous devez tlcharger linstallateur Omondo, ladresse http://www.ejb3.org/download_studio_JEE_eclipse_3.3.html. 1. Double-cliquez sur le jar rcupr pour dmarrer linstallation. 2. Si vous nobservez pas la premire page de lassistant, ouvrez une console DOS, et entrez la commande java jar, suivie de ladresse vers votre installateur, comme illustr la gure A.3.
Figure A.3
350
JEE5 ANNEXES
3. La page qui safche permet lutilisateur de choisir la langue de linstallateur, mais pas dEclipseUML (attention), comme lillustre la gure A.4.
Figure A.4
4. Cliquez sur OK. Vous tes redirig vers la page de bienvenue de linstallateur. 5. Cliquez sur Suivant. 6. La page suivante vous propose des informations sur la licence EclipseUML. Acceptez-en les termes pour poursuivre linstallation. 7. Cliquez sur Suivant. 8. Mentionnez le chemin dinstallation de votre Eclipse Europa.
Figure A.5
9. La bote de dialogue de conguration des paquetages installer safche comme illustr la gure A.6. Notez bien si vous avez install Eclipse. 10. Le processus dinstallation proprement dit dbute. 11. Cliquez sur Quitter une fois linstallation termine.
351
Figure A.6
12. Pour vrier quEclipseUML est bien install, slectionnez Help puis About Eclipse Plateform (voir gure A.7).
Figure A.7
352
JEE5 ANNEXES
2. Faites en sorte que le chier eclipse.ini ressemble celui illustr la gure A.8.
Figure A.8
Fichier eclipse.ini
JBoss 4.2
La version 4.2 de JBoss supporte nativement la spcication EJB3, contrairement a version JBoss 4.0, qui ncessitait une installation spcique du conteneur EJB3. 1. Si vous souhaitez installer la version 4.0.x, utilisez linstallateur graphique (http:// prdownloads.sourceforge.net/jboss/jems-installer-1.2.0.CR1.jar?download). 2. Une fois tlcharg, excutez linstallateur en double-cliquant sur le chier (si les chiers JAR ne sont pas associs Java, lexcution de linstallateur peut se faire via la commande java -jar ems-installer-1.2.0.CR1.jar. Pour les versions de JBoss suprieures 4.2, linstallation de JBoss 4.2.x.GA, disponible sur le site de sourceforge (http://labs.jboss.com/jbossas/downloads/) se limite une simple dcompression de larchive sous le rpertoire, en supposant un JDK5 install (positionnement de la variable JAVA_HOME pralable avant installation du serveur JBoss).
Seam
1. Pour installer Seam, assurez-vous que vous possdiez un JDK1.5, Ant (ou Eclipse) et une installation JBoss avec support dEJB3. 2. Tlchargez larchive Seam (http://www.jboss.com/products/list/downloads#seam), et dcompressez-la sur votre disque en dehors de larborescence serveur JBoss que vous venez dinstaller. 3. ditez le chier build.properties se trouvant sous la racine du projet Seam an quil pointe la variable JBOSS_HOME vers le chemin dinstallation du serveur JBoss. 4. partir dEclipse ou travers une console DOS (si vous avez Ant proprement install), excutez le script build.xml situ sous la racine du projet Seam.
353
5. la n de lexcution du script, un nouveau rpertoire est cr, jboss-seam, suivi de la date du jour, par exemple : jboss-seam-Octobre 18 2007. Ce rpertoire comporte les jars Seam ncessaires pour dvelopper votre projet. 6. Dans le cadre de lapplication exemple de louvrage, vous navez besoin que du chier jboss-seam.jar, que vous devez copier sous la racine de votre ear (sans oublier dajouter cette dpendance au chier application.xml) :
<application> <display-name> Seam pour les debutants </display-mode> <module> <web> <web-uri>MonAppliWebSeam.war</web-uri> <context-root>/monAppliSeam</context-root> </web> </module> <module> <ejb>monEJBs.jar</ejb> </module> <module> <java>jboss-seam.jar</java> </module> </application>
7. Si vous dployez votre application sous la forme de chier war, vous navez qu copier le chier jboss-seam.jar dans le rpertoire WEB-INF/lib de larchive. En plus de ce chier il existe plusieurs bibliothques de support que vous pouvez ou non inclure larchive de lapplication, selon la manire dont vous utilisez Seam dans vos projets. Les diffrents chiers de conguration sont rcapituls au tableau suivant.
Nom de la ressource
META-INF/application.xml
Description
Descripteur de dploiement de lapplication JEE dnissant les modules et les war de lapplication ear Descripteur de dploiement EJB3 pour les EJB.jar dnissant les diffrents intercepteurs Permet de congurer lunit persistante. Utilis pour congurer le ClassLoader JBoss Descripteur de dploiement pour le microconteneur JBoss Descripteur de dploiement pour le war Dclare les rgles de navigation et les composants JSF. Descripteur de dploiement JBoss pour un war Dnit les action Seam (Seam page action) avant dafcher une page donne. vnements Seam Fichier de conguration des composants Seam Utilis pour la conguration dHibernate Conguration JBPM Fichier de ressource Seam
Contrainte
Non utilis par Seam
META-INF/ejb-jar.xml META-INF/persistence.xml META-INF/jboss-app.xml META-INF/jboss-beans.xml WEB-INF/web.xml WEB-INF/faces-cong.xml WEB-INF/jboss-web.xml WEB-INF/pages.xml WEB-INF/events.xml Seam.properties Hibernate.cfg.xml Jbpm.cfg.xml Classes/messages.properties
Ncessaire pour dclarer lIntercepteur SeamInterceptor de Seam pour la couche mtier Non utilis par Seam Non utilis par Seam Non utilis par Seam Non utilis par Seam Non utilis par Seam Non utilis par Seam Peut tre vide. Peut tre vide. Peut tre vide. Non utilis par Seam Non utilis par Seam Peut tre vide.
354
JEE5 ANNEXES
Installation des bibliothques EJB3 embarques Vous pouvez utilisez le conteneur JBoss EJB 3.0 embarqu avec Seam dans votre application. Le fait dutiliser le conteneur embarqu EJB 3.0 dans votre application vous permet dexcuter vos composants EJB 3.0 sans avoir vous soucier des fonctionnalits de votre serveur dapplications. Vous pouvez de la sorte excuter diffrentes applications sur votre serveur, comme certaines embarquant un environnement EJB 2.1, dautres le conteneur embarqu EJB 3.0. Les bibliothques spciques requises sont les suivantes (localises dans le rpertoire lib de la distribution Seam) : hibernate-all.jar, qui inclut toutes les classes Hibernate que le conteneur embarqu utilise pour limplmentation JPA. thidparty-all.jar, qui inclut des chiers utilitaires supplmentaire utiliss par le conteneur. jboss-embedded-all.jar, qui contient toutes les classes implmentant le conteneur EJB 3.0 proprement dit. Ces bibliothques peuvent tre incluses dans le rpertoire racine de votre chier ear ou dans le rpertoire WEB-INF/lib de votre chier WAR, en fonction du mode de packaging et de dploiement de votre application.
355
Les composants Seam sont ajouts dans le dossier source src. Les classes de test pour testNG sont ajoutes dans le dossier source test (il faut galement congurer les chiers de conguration de tests components.xml et testNG.xml). Dans le META-INF du projet Web, on trouve le descripteur JPA persistence.xml pour la conguration de la source de donnes du projet. Sous le WEB-INF, on trouve le reste des descripteurs pour Seam et pour lapplication Web.
B
Annotations Seam
Nous prsentons ici les principales annotations Seam, dont un certain nombre sont dnies dans la spcication EJB 3.0.
Dnit le nom du composant pour la classe (requise pour tous les composants Seam).
@Name (" MonComposant" )
@Scope
Dnit le contexte par dfaut du composant. Les valeurs possibles sont dnies par lnumration ScopeType, soit EVENT, PAGE, CONVERSATION, SESSION, BUSINESS_PROCESS , APPLICATION, STATELESS. Lorsque la porte nest pas explicitement spcie, la valeur par dfaut dpend du type de composant. Pour les beans session stateful, la valeur par dfaut est CONVERSATION. Pour les composants JavaBeans la valeur par dfaut EVENT.
@Scope(ScopeType.CONVERSATION)
@Role
Permet un composant Seam dtre reli plusieurs variables contexte. Proprits name : nom de la variable contexte. scope : porte de la variable contexte.
@Role (name=" monRole" , scope=ScopeType.SESSION)
358
JEE5 ANNEXES
@BypassInterceptors
Dsactive tous les intercepteurs Seam sur un composant particulier ou une mthode dun composant.
@JndiName
Spcie que la porte du composant est conversationnelle, ce qui signie quaucune mthode du composant ne peut tre appele moins quune conversation longue ne soit active.
@JndiName("ejb/session/MonBeanSession") Public class MonBeanSession{ }
@Startup
Utilise en combinaison avec @Scope, spcie quun composant de porte application est dmarr immdiatement lors de linitialisation de lapplication (utile par exemple pour dmarrer certaines ressources critiques, comme les sources de donnes). Paramtres depends : spcie le nom du composant qui doit tre dmarr en premier.
@Scope (SESSION) @Startup (depends= "org.jboss.seam.bpm.jbpm")
@Install
Spcie si le composant doit tre ou non install par dfaut. Labsence de cette annotation indique que le composant doit tre install. Proprits dependencies : spcie que le composant doit tre install si les composants lists comme dpendants sont aussi installs. genericDependencies : spcie quun composant doit tre install si un composant implment avec une classe particulire est install. classDependencies : spcie la prcdence du composant. Sil existe plusieurs composants de mme nom, cest celui ayant la plus haute priorit qui est install. Les valeurs de priorits sont les suivantes (ordre ascendant) : BUILT_IN : priorit sur tous les composants Seam installs. FRAMEWORK : priorit dutilisation pour les composants des frameworks qui tendent Seam. APPLICATION : priorit sur les composants de lapplication (priorit par dfaut). DEPLOYMENT : priorit dutilisation pour les composants qui surchargent les composants de lapplication dans un dploiement spcique. MOCK : priorit pour les objets simuls (MOCK) utiliss pour les tests.
@Install(precedence=BUILT_IN)
359
@Synchronized
Spcie quun composant est accd de manire concurrente par plusieurs clients et que Seam doit srialiser les requtes. Si la requte est dans limpossibilit dobtenir un verrou sur le composant pendant la priode spcie par le paramtre timeout, une exception est leve. Proprits timeout : dure en seconde de lattente du verrou partir de laquelle une exception est leve.
@Synchronized (timeout=2000)
@ReadOnly
Spcie quun composant JavaBean ou une mthode dun composant ne ncessite pas de rplication de ltat la n de linvocation.
@AutoCreate
Spcie quun composant sera automatiquement cr, mme si le client ne spcie pas create=true.
Spcie que lattribut dun composant est inject dans une variable de contexte au dbut de chaque invocation du composant. Si la variable de contexte est nulle, une exception est leve. Proprits value : spcie le nom de la variable de contexte qui peut tre substitue par une expression JSF EL, dlimite par le caractre #{}. create : spcie que Seam doit instancier le composant avec le mme nom que la variable de contexte si cette dernire est indnie pour tous les contextes. required : spcie que Seam doit lever une exception si la variable de contexte est indnie pour tous les contextes.
@In(required=false) @In private User user
@Out
Spcie que lattribut du composant est outjected vers une variable de contexte une fois la mthode appele (principe dinjection de dpendances). La variable spcie par lannotation dans le contexte est automatiquement substitue aprs chaque appel. Si lattribut est nul, une exception est leve. Proprits value : spcie le nom de la variable de contexte, par dfaut le nom de lattribut du composant.
360
JEE5 ANNEXES
required : spcie que lattribut du composant Seam est outjected vers la variable de contexte la n de linvocation. Lattribut peut tre null (required=false) durant loutjection. scope : spcie quun attribut du composant qui nest pas du type de composant Seam doit tre outjected vers un scope spcique la n de linvocation. Si aucun scope nest explicitement spci, le scope du composant avec lattribut @Out est utilis (ou le scope EVENT si le composant est stateless).
@In(create=true) @Out private User currentUser;
@Factory
Spcie que la mthode du composant est utilise pour initialiser la valeur de la variable de contexte spcie, lorsque la variable de contexte na pas de valeur. Proprits value : spcie le nom de la variable de contexte, par dfaut le nom de lattribut du composant. required : spcie que lattribut du composant Seam est outjected vers la variable de contexte la n de linvocation. Lattribut peut tre null (required=false) durant loutjection. scope : spcie quun attribut du composant non-Seam doit tre outjected vers un scope spcique la n de linvocation. Si aucun scope nest explicitement spci, le scope du composant avec lattribut @Out est utilis (ou le scope EVENT si le composant est stateless).
@Factory("items") public void getItems() { if ((items==null) || (index != firstItem) ){ getNextItems(); }
Spcie que la mthode doit tre invoque lorsquune instance du composant est instancie par Seam. Les mthodes create sont uniquement applicables pour les JavaBeans et les beans session stateful.
@Name("DatabaseUtils") Public class DatabaseUtils{ @Create() public void initDatabase(){ } }
361
@Destroy
Spcie que la mthode doit tre appele lorsque le contexte se termine et que les variables de contexte associes au contexte sont supprimes. Les mthodes destroy sont uniquement supportes par les JavaBeans et les beans session stateful.
@Name("DatabaseUtils") Public class DatabaseUtils{ @Destroy() public void closeDbResources(){ } }
@Observer
Spcie que la mthode doit tre appele lorsquun vnement sur un composant survient. Paramtres value : spcie le nom de la variable de contexte, par dfaut le nom de lattribut du composant. create : si linstance nexiste pas et que create est false, lvnement produit est ignor. Par dfaut true.
@Observer(value="ModificationEffectuee",create=false)
Marque la mthode comme dmarrant une conversation longue Seam. Paramtres join : valeur true ou false. Spcie que si une conversation longue est dj en progression, le contexte conversationnel est simplement propag. Si false (dfaut), linvocation de la mthode begin dans le scope dune conversation en cours provoque une exception. Nested : valeur true ou false. Si actif (valeur true), et si une conversation est en cours, dmarre une conversation imbrique, au lieu de continuer dans le contexte de la conversation existante. Flushmode : positionne le mode ush pour chaque session Hibernate Seam manage ou contexte persistant JPA cr durant la conversation (par dfaut AUTO). Pageow : nom de la dnition du processus jBPM dnie pour le ux de la page pour une conversation particulire.
// Specify that this method starts a long running conversation @Begin public String find() { hotel = null; String searchPattern = searchString == null ? "%" : '%' + searchString.toLowerCase().replace('*', '%') + '%';
362
JEE5 ANNEXES
hotels = em.createQuery("from Hotel where lower(name) like :search or lower(city) like :search or lower(zip) like :search or lower(address) like :search") .setParameter("search", searchPattern) .setMaxResults(50) .getResultList(); log.info(hotels.size() + " hotels found"); return "main"; }
@End
Spcie quune conversation longue Seam se termine et supprime les variables de contexte associes. Paramtres Beforeredirect : valeur true ou false. Par dfaut (valeur=false), la conversation nest pas rellement dtruite, moins quune redirection nait t effectue. Sinon (valeur true), spcie que la conversation est dtruite la n de la requte courante et que la redirection est traite dans un nouveau contexte de conversation temporaire.
@End @Destroy @Remove public String confirm() { if (booking == null || hotel == null) return "main"; em.persist(booking); log.info("booking confirmed"); return "confirmed"; }
@StartTask
Dmarre une tche jPBM. Paramtres taskIdParameter : nom du paramtre de la requte sous lequel localiser lidentiant de la tche qui doit tre lance. ushmode : positionne le mode ush pour nimporte quel gestionnaire dentit utilis pour cette conversation.
@BeginTask
Reprend la tche jBPM prcdemment dmarre. Proprits taskIdParameter : nom du paramtre de la requte sous lequel localiser lidentiant de la tche qui doit tre reprise. ushmode : positionne le mode ush pour nimporte quel gestionnaire dentit utilis pour cette conversation.
363
@EndTask
Termine une tche jBPM. Proprits transition : nom de la transition jBPM dclenche lorsque la tche est termine (par dfaut, nom de la transition par dfaut). beforeRedirect (valeur true ou false) : permet de spcier si la conversation est dtruite avant toute redirection. Le comportement par dfaut propage la conversation travers le redirect et la dtruit la n de la requte de redirection.
@CreateProcess
Cre une nouvelle instance de processus jBPM. Proprits denition : nom de la dnition du processus org.jboss.seam.bpm.jbpm.processDenitions.
@ResumeProcess
jPBM
dploy
via
Entre nouveau dans le scope dune instance jBPM existante. Proprits processIdparameter : nom du paramtre de la requte sous lequel localiser lidentiant du processus qui doit tre repris.
@Transition
Spcie une mthode pour la transition jBPM aprs que celle-ci retourne un rsultat non null et sans exception. Proprits value : nom de la transition (par dfaut, nom de la mthode).
@Transition("cancel")
Annotations pour lutilisation des composants JavaBean Seam dans un environnement J2EE
Les annotations suivantes permettent de spcier la stratgie de dmarcation transactionnelle.
@Transactional
Spcie quun composant JavaBean doit avoir un comportement transactionnel similaire au comportement par dfaut dun composant bean session. Les invocations de mthodes doivent prendre place dans la transaction. Si aucune transaction nexiste lorsque la mthode est invoque, une transaction est dmarre juste pour cette mthode. Proprits value : type de programmation transactionnelle.
364
JEE5 ANNEXES
Provoque un dbranchement vers la page spcie par le paramtre viewId. Proprits viewId : spcie lidentiant de la page JSF pour la redirection. Vous pouvez galement utiliser une expression JBoss EL (Expression Language). message : message qui sera afch. end : spcie quune conversation longue doit se terminer (par dfaut, false).
@Redirect (viewId="error.jsp")
@HttpError
Provoque une erreur HTTP. Proprits errorcode : le code erreur http (par dfaut, 500). message : message qui sera envoy avec lerreur HTTP (par dfaut, le message dexception). end : spcie quune conversation longue doit se terminer (par dfaut, false).
@HttpError (errorCode=404)
Spcie que la mthode distante annote peut tre appele partir dun client JavaScript. Proprits exclude : proprit optionnelle permettant aux objets dtre exclus du graphe dobjets produit.
@Local public interface HelloLocal { @WebRemote public String sayHello(String name); }
365
Met en uvre le mcanisme dinterception Seam. Proprits Stateless : valeur true ou false. Spcie que lintercepteur est stateless. type : spcie que lintercepteur est de type client et quil est invoqu avant le conteneur EJB (type=CLIENT). around : spcie lordre de prcdence de lintercepteur. within : spcie que lintercepteur est positionn plus profondment dans la pile que les intercepteurs spcis.
@Interceptor(around={unIntercepteur.class, unAutreIntercepteur.class}) @Interceptor(within={unIntercepteur.class, unAutreIntercepteur.class})
Spcie que lappel de la mthode est effectu de manire asynchrone. Ce mcanisme sadapte parfaitement lutilisation du framework AJAX lorsque le client peut interroger le serveur de manire automatique pour recevoir le rsultat dune tche fonctionnant en arrire-plan. Proprits Les annotations @Duration, @Expiration, @IntervalDuration sutilisent conjointement avec @Asynchronous pour permettre une planication des mthodes asynchrones associes.
@Local public interface PaymentHandler { @Asynchronous public void processScheduledPayment(Payment payment, @Expiration Date date); @Asynchronous public void processRecurringPayment(Payment payment, @Expiration Date date,0 @IntervalDuration Date interval)' }
366
JEE5 ANNEXES
@DataModel
Outjecte une proprit (la proprit devenant ainsi accessible aux variables JSF) de type List, Map, Set ou Objects, comme type DataModel JSF dans la porte du composant propritaire (ou dans la porte event si le composant propritaire est stateless). Dans le cas particulier dun type Map, chaque ligne de DataModel est une Map.Entry. Proprits value : nom de la variable de contexte de conversation (par dfaut, nom de lattribut). scope : si scope=ScopeType.PAGE est explicitement spcie, DataModel est conserv dans le contexte PAGE.
@DataModel private List<Book> books;
@DataModelSelection
Injecte la ligne de donne slectionne de lobjet DataModel utiliser conjointement avec lannotation @DataModel. Proprits value : nom de la variable de contexte de conversation (non requis sil existe une annotation @DataModel dans le composant).
@DataModel private List<Book> bookList; @DataModelSelection Book book;
@DataModelSelectionIndex
Injecte la ligne de donne slectionne de lobjet DataModel utiliser conjointement avec lannotation @DataModel. Proprits value : nom de la variable de contexte de conversation (non requis sil existe une seule annotation @DataModel dans le composant).
@DataModel private List<Book> bookList; @DataModelSelection Book book;
Spcie que lannotation est de type databinding, cest--dire quelle rsulte de loutjection dune reprsentation enveloppe de la valeur de lattribut du composant annot.
@DataBinderClass(DataModelBinder.class)
367
@DataSelectorClass
Spcie que lannotation est une annotation de slection de donne, cest--dire quelle rsulte de linjection de llment slectionn de type de donne databound.
@DataSelectorClass(DataModelSelector.class)
Spcie la conguration de lespace de nom du package Java contenant lensemble des composants Seam. Proprits value : espace de nom de la conguration pour le packaging. prex (en option) : spcie le prxe du nom du composant appliquer pour les noms de composants spcis dans le chier de conguration XML.
@Namespace(value="http://jboss.com/products/seam/core", prefix="org.jboss.seam.core")
C
Annotations AndroMDA pour le prole EJB3
Cette section prsente les principaux strotypes et valeurs balises du prol EJB3 pour AndroMDA mis en uvre avec latelier de modlisation MDA EclipseUML for JEE. Rappelons quun strotype est un nom qui apparat sur un diagramme. Souvent dsign par la chane <<MonStereotype>>, il peut tre appliqu nimporte quel lment dun diagramme UML.
Les l ments du prol sont organiss selon trois lments cls du diagramme de classes,
savoir la description des lments du prol applicables pour les classes, les attributs et les mthodes. Les tableaux suivants rcapitulent les lments principaux du prol EJB 3.0 pour AndroMDA. Davantage dinformations sont disponibles ladresse http://web.aanet.com.au/
persabi/andromda/prole.html.
Sapplique
Bean entit
Valeurs possibles
Chane de caractres
Description
Utilise sur les entits pour permettre leur cration synthtique (autognration) Si true, gnration automatique de la cl primaire
true false
370
JEE5 ANNEXES Valeurs balises du prol EJB3 Persistence::Persistence pour les classes
Valeur balise
inheritance @andromda.persistence.inheritance
Sapplique
Entit
Valeurs possibles
SINGLE_TABLE TABLE_PER_ClASS JOINED
Description
utilise pour rednir lhritage par dfaut pour les entits
Entity_cache : @andromda.persistence.entity.cache
Entit
discriminator_column_name : @andromda.persistence.discriminator.column.name discriminator_column_denition : @andromda.persistence.discriminator.column.denition Table : @andromda.persistence.table discriminator_type : @andromda.persistence.discriminator.type discriminator_column_length : @andromda.persistence.discriminator.column.length
Entit
Optionnelle : dnit le nom de la colonne discriminante. Optionnelle : indique le fragment SQL utilis pour la gnration du DDL pour la colonne discriminante. Dnit la table relationnelle utilise pour lentit persiste. Utilise pour rednir le type de discriminateur dni dans la proprit entityDiscriminatorType du namespace. Indique la longueur de la colonne des discriminateurs en chanes de caractres. Ignore pour les autres types de discriminateurs.
Entit
fragment SQL
Chaine de caractres
Entit
Sapplique
Bean session Classe Classe Classe Classe
Description
Strotype utilis pour dsigner un bean session Identie un contexte de persistence. Dnit une classe Listener pour les beans entit, session ou MDB. Utilis pour injecter une ressource javax.transaction.UserTransaction Produit une faade de MDB JMS qui reoit les messages.
Annotations AndroMDA pour le profile EJB3 ANNEXE C Valeurs balises du prol EJB3 Persistence::Service pour les classes
Valeur balise
persistence_context_unit_name : @andromda.service.persistence.context.unit.name persistence_context_datasource : @andromda.service.persistence.context.datasource jndi_remote : @andromda.service.jndi.remote jndi_local @andromda.service.jndi.local security_permitall : @andromda.service.security.permitAll security_denyAll : @andromda.service.security.denyAll
371
Sapplique
Bean session ou classe strotype PersistenceContext Bean session ou classe strotype PersistenceContext Bean session Bean session Bean session Bean session ou une de ses oprations
Valeurs possibles
Chane de caractres Nom JNDI de la source de donnes Nom JNDI de linterface distante Nom JNDI de linterface locale true false true false
Description
Utilise pour dnir le nom du contexte de persistence Utilise pour dnir le nom JNDI de la source de donnes du contexte de persistence Spcie manuellement le nom JNDI de linterface distante. Spcie manuellement le nom JNDI de linterface locale. Donne des permissions sur lexcution de lopration du Bean. Interdit les permissions sur lexcution de lopration du Bean.
Sapplique
Opration dun service ou attribut dune entit
Valeurs possibles
NotSupported Supports Required RequiresNew Mandatory Never remote (default) local both
Description
Dnit le type de transaction.
viewType : @andromda.ejb.viewType
Dnit le type de vue pour un bean session au niveau classe et au niveau de lopration pour chaque mthode session.
Sapplique
Attribut dune entit
Valeurs possibles
string
Description
Dnit un nom unique qui sera rfrenc par une ou plusieurs classes pour tre le gnrateur dun bean entit. Spcie la prcision pour une colonne dcimale. Spcie la stratgie de gnration de la cl primaire.
Valeur dcimale
column_denition : @andromda.persistence.column.denition
372
JEE5 ANNEXES Valeurs balises du prol EJB3 Persistence::Persistence pour les attributs (suite)
Valeur balise
collection_type : @andromda.persistence.collection.type column : @andromda.persistence.column temporal_type : @andromda.persistence.temporal.type optional : @andromda.persistence.optional Column_update @andromda.persistence.column.update generator_initial_value : @andromda.persistence.generator.initial.value order_by : @andromda.persistence.orderBy
Sapplique
Association ends entre deux entits
Valeurs possibles
set map list bag Chaine de caractres date (default) time timestamp none true false true false
Description
Utilise pour dnir le mapping des collections EJB3
Attribut dune entit Attribut dune entit ou paramtre dune mthode tagge (nderMethod) Attribut dune entit
Reprsente le nom de la colonne utilise pour lattribut. Cette valeur balise est spcie sur les attributs de type java.util.Date ou java.util.Calendar ou les paramtres des mthodes Finder. Dnit lannotation non-null relationship. Si elle est mise false, une relation non nulle doit toujours exister. Spcie si une colonne doit tre incluse dans le sql update. true est la valeur par dfaut. Spcie la squence de dpart pour la gnration du ID pour le gnrateur de PK dune entit.
Association End
Nom de colonne
Spcie le(s) nom(s) de colonne(s) qui seront utilises pour le tri des collections retournes ; avec ASC ou DESC optionnellement. Sans valeur, la cl primaire est assume. Spcie le type dnumration du champ persistant. Spcie le nombre incrmenter lallocation dun id pour le gnrateur. Spcie le nom de table qui stocke les identiants gnrs ou le nom de la squence de base de donnes utilise pour obtenir les identiants. Spcie si lattribut peut tre null.
enumeration_type : @andromda.persistence.enumeration.type generator_allocation_size : @andromda.persistence.generator.allocation.size generator_source_name : @andromda.persistence.generator.source.name column_nullable : @andromda.persistence.column.nullable fetch_type : @andromda.persistence.fetch.type column_scale : @andromda.persistence.column.scale association_cache : @andromda.persistence.association.cache
Attribut
Nom de table
Indique lchelle utiliser pour une colonne dcimale. Dnit la stratgie du cache pour une association entre deux entits de type collection.
column_insert : @andromda.persistence.column.insert
Annotations AndroMDA pour le profile EJB3 ANNEXE C Valeurs balises du prol EJB3 Persistence::EJB pour les attributs
Valeur balise
queryUseCache : @andromda.ejb.query.useCache viewType : @andromda.ejb.viewType
373
Sapplique a
operations Query Services ou mthodes dune classe service
Valeurs possibles
true false remote (default) local both
Description
Active/dsactive le cache pour les requtes. Dnit le type daccs au bean session (remote, local...).
Sapplique
Mthodes dune classe Entity Mthodes dune classe Entity
Description
Associe cette mthode une requte SQL pour retrouver cette entit. Spcie que lopration associe est une mthode de callback pour un Bean entit et qu'elle sera invoque aprs que l'entit aura t cre en base et qu'elle sera applique en cascade pour toutes les entits relies. Spcie que lopration associe est une mthode de callback pour un bean entit et quelle sera invoque juste aprs le chargement des donnes partir de la base et leur association avec lentit. Spcie que lopration associe est une mthode de callback pour un bean entit et qu'elle sera invoque aprs la mise jour de la base. Utilise pour annoter la mthode Create dun EJB Spcie que lopration associe est une mthode de callback pour un bean entit et quelle sera invoque avant la mise jour de la base. Spcie que lopration associe est une mthode de callback pour un bean entit, quelle sera invoque aprs/avant la suppression de lentit de la base et quelle sera applique en cascade pour toutes les entits relies. Spcie que lopration associe est une mthode de callback pour le bean entit et quelle sera invoque aprs que lentit aura t cre en base.
PostLoad
PostUpdate
CreateMethod PreUpdate
PostRemove/PreRemove
PostConstruct
Index
A Actuate 127 AJAX 21, 179 AndroMDA 291, 293, 334 annotations 178, 197 de persistance 228 Apache Derby 130, 141 Geronimo 201 Struts 166 API JPA 225 Query 248 ATF (Ajax Toolkit Framework) 11, 104 B BEA (WebLogic_10) 202 bean entit 198, 228 annotations de persistance 228 interface Entity Manager 242 invocation partir dun client Java et dun client Web 252 manag 247 mapping des relations 235 mthodes de callback 251 mthodes de cycle de vie 243 mise jour 249 persistance 246 principales oprations disponibles 246 relations 234 requtes JPQL 247 suppression 249 tables de jointure 241 MDB 198 message 213 session 202 avec tat 209 vnements de callback 211 faade 285 sans tat 203 stateful 198 stateless 198 BIRT (Business Intelligence and Reporting Tools) 13 ajout de rgles mtier 13 mise en forme 13 rcupration des donnes 13 transformation des donnes 13 C CDT (C/C++ Development Tools) 19 client lger 21 riche exemple darchitecture 22 Cloudscape 131 CMF (Connectivity Management Framework) 128 Computer Associates 87 Compuware 87 QaLoad 88 conception du modle de donnes 127 conversations 332 couverture des tests 87 CVS (Concurrent Versions System) 55 adaptateur Eclipse 58 ajout dutilisateurs avec pserver 65 branches 58 conguration du rfrentiel dans Eclipse 65 conits 72 fonctionnalits 61 installation et conguration de CVSNT 62 intgration dans Eclipse 55 mise en uvre dans Eclipse 61 rfrentiel dquipe 59 scnario de dveloppement parallle 60 squentiel 60 synchronisation du rfrentiel 69 validation 73 versionnement des ressources dun projet 74 CVSNT 59 installation 62 D Dali 10, 104, 215, 259 conguration 260 cration dun projet JPA et connexion une source de donnes 263 des entits persistantes du modle et mapping vers la base 267 des mappings de base 273 dnition des requtes nommes de linterface Query 284 intgration des entits du modle logique 285 mapping de version 283 des relations interentits 279
376
JEE5
Many-to-One 282 One-to-Many 281 One-to-One 279 mise en uvre dun bean client faade 285 de lAPI JPA 262 scnarios de dveloppement 260 Dali JPA Tools 11 Derby 14, 130, 141, 162, 289 design dapplication Web 141 dveloppement collaboratif avec CVS 55 EJB3 avec Eclipse et Web Tools 195 avec JBoss et Web Tools 215 Web Seam 165 Web Tools 101, 139 DI (Dependency Injection) 200 DLTK (Dynamic Languages Toolkit) 10 Draw2D 16 DTP (Data Tools Platform) 14, 127 architecture 128 CMF 128 connexion la base Apache Derby 130 cration dun prol de connexion 133 gnration du DDL 137 mise en uvre 130 Model Base 128 script SQL de cration du schma de base de donnes 135 sous-projets 128 SQL Development Tools 129 vue SQL Results 136 DTP 1.5 128 E Eclipse architecture plugable 58 assistant de gnration de getters/setters 153 conguration du rfrentiel CVS 65 console CVS 70 contrle de version 70
dcorateurs 69 dveloppement en quipe 55 Europa 178 gestion de conguration intgre 57 historique local 56 mise jour des ressources CVS 72 mise en uvre de CVS 61 perspective Rfrentiels CVS 74 rfrentiel partageable 57 SCMS 59 support de CVS 55 Web Tools 101, 168 Eclipse RCP 21 ajout de fonctionnalits 32 architecture 22 classes principales 29 dmarrage de lapplication 28 dveloppement dune application 25 exemples dapplications 24 mise en uvre 25 points dextension de plug-ins 43 Eclipse Studio 291 Eclipse 3.3 1, 90, 108, 114, 215 EclipseUML Studio 291 utilisation de svn 83 Web Tools 295 EclipseUML 291, 293, 334 Europa 293 EclipseUML Studio 291 Ecore 15 EJB 3.0 178 JPA 225 EJB3 178, 195 annotations 199 bean entit 228 message 213 session avec tat 209 sans tat 203 cration de beans entit 297 descripteur de la persistance des donnes 199 diffrence fondamentale avec EJB2 198 tude de cas 291 vnements de callback 211
fondamentaux 197 injection des dpendances 200 Java Persistence API 198 mthodes de cycle de vie dune entit 243 mise en uvre avec Web Tools et JBoss 215 principales diffrences avec EJB2 212 principales nouveauts 199 Seam (conguration avance) 329 spcication 197 support des intercepteurs 201 synthse des frameworks succs 201 EMF (Eclipse Modeling Framework) 14, 89, 128 EMF 2.3 90 Entity Manager 242 ESB (Enterprise Service Bus) 178 Europa 1, 4, 90, 108, 114, 259 DTP 1.5 128 EclipseUML 293 EclipseUML Studio 291 EMF 15 import de projets avec copie 7 intgration des ux RSS 7 liens vers des ressources chier 7 nettoyage de code 8 nouveauts V, 3, 345 restructuration de scripts 8 Seam 178 sous-projets 4, 9 support de la langue franaise 25 vue Cheat Sheet 7 explorateur de projets 4 Filtres 6 historique 5 Nettoyage 8 Restructuration 8 TPTO 12 Europa 3.3 262 F facelets Seam 182 facets 111, 245
Index
377
G GEF (Graphical Editor Framework) 16 afcheur de diagrammes UML 16 GEF 3.3 90 Geronimo 2.0.1 201 gestion des entits 225 gestionnaire de versions Subversion 75 Glasssh 202 GMF (Graphical Modeling Framework) 16 cinmatique dutilisation sous Eclipse 17 diteur UML 17 gnrateur de modles 17 plug-in Visual Editor 18 Google Maps 21 H Hibernate 104, 178, 197, 198 gestion de la persistance 226 JPA 183 Hibernate_3.0 201 HSQLDB 262 Hyades 12, 87 Hypersonic 130, 306 Hypersonic DB 262 I IBM 10, 87, 127, 131 alphaworks 18 Notes 24 WebSphere_7 202 Workplace Client Technology Rich Edition 22 injection de dpendances 178, 200 Intel 87 J J2EE 1.4 103 J2SE 5.0 227 JAAS (Java Authentication and Authorization Service) 105 JBI (Java Business Integration) 178 JBoss 103, 162 AS 4.2.x et 5.x 181 Dali 259
dploiement de lapplication 163 EL (Expression Language) Enhancement 181 HSQLDB 262 jBPM 179 mise en uvre du dveloppement EJB3 215 Seam 165, 178, 329 JBoss Portal 179 JBoss 4.0 111 JBoss 4.0.5 110, 117 JBoss 4.2 144, 215 HSQLDB 262 support de JSF_1.2 168 JBoss 4.2.0 GA 179 JBoss 4.2.1 295 JBoss 5 201 jBPM (JBoss Business Process Management) 331 JCM (J2EE Core Model) 105 JDBC (excution dune requte) 139 JDK5 215, 228 annotations 197 JDO 2.0 201 JEE5 104, 178 EJB3 198 nouvelle API de persistance 201 JFace 23 JNDI 105 JPA (Java Persistence API) 183, 225 architecture 226 beans entit 228 caractristiques 227 contexte de persistance 246 cration dun projet et connexion une source de donnes 263 Dali 259 gestionnaire dentits 243 mapping O/R 227 mise en uvre avec Dali 262 TopLink 246 TopLink Essentials 260 JPQL (Java Persistence Query Language) 248 JSE6 198
JSF (JavaServer Faces) 104, 166 approche oriente composant 167 conguration de la cinmatique des pages 174 diteur de conguration Web Tools 175 fondamentaux 167 limitations 167 mise en uvre avec Web Tools 168 JSF Tools (JavaServer Faces Tools) 11 JSF 1.1 121 JSF 1.2 11, 168 JSP (JavaServer Pages) 166 JST (J2EE Standard Tools) 10, 103, 104 architecture 105 assistant de cration de projet 108 gestion des serveurs 109 outillage J2EE standard 106 serveurs dapplications supports 110 standards JCP supports 104 JVMPI (Java Virtual Machine Proler Interface) 90 L loadRuner 88 M mapping cardinalit 234 de version 283 directionnalit de la relation 234 JPA avec Dali 259 Many-to-Many 240 Many-to-One 237, 282 One-to-Many 238, 281 bidirectionnel 239 One-to-One 236, 279 bidirectionnel 237 tables de jointure 241 MDA (Model Driven Architecture) 291 Mercury (loadRuner) 88 Message Driven Beans 213 mesure des performances 87
378
JEE5
mtadonnes 199, 230 Model Base 128 modle de donnes 127 MOF (MetaModel Facility) 15 MVC2 166 Mylyn 10 MySQL 5 131 O ObjectWeb 10 Omondo 15, 195 EclipseUML 291, 293 Oracle 11 Dali 259 TopLink 226 TopLink Essentials 259 OSGI (Open Services Gateway Initiative) 23 P patterns 139 Commande 154 persistance des donnes 199 POA (programmation oriente aspect) 201 POJO (Plain Old Java Objects) 178, 198 proling de code 87, 88 Q QaLoad 88 R Rational 16 RCP (Rich Client Platform) 21 rfrentiel dquipe (CVS) 59 Reverse UML 309 RIA (Rich Internet Applications) 21 Ruby 10 S SAP 87 Scapa Technologies 87 SCMS (Software Conguration Management System) 57, 59 Seam 165, 178, 228, 306 AJAX 179 annotations 178 associes JSF 191 de gestion des contextes 343 de validation des champs de saisie 193 Ant_1.6 181
caractristiques 178 composants fondamentaux de larchitecture 179 conguration 334 avec les composants POJO 183 EJB3 avance 329 contexte 329 conversationnel 332 contextes 179 conversation 329, 340 dveloppement fond sur les POJO 178 DI (Dependency Injection) 178 Hibernate 181 intgration dans larchitecture MVC 333 intercepteurs 333 mise en uvre 181 tiers prsentation JSF 190 utilisation des facelets 182 SOA Tool Platform 10 Spring 165, 197, 201 injection de dpendances 200, 226 SQL Development Tools 129 Struts 165 limitations 167 Subclipse 83 Subversion 75 Sun 166 Glasssh 179, 202 JPA 225 JSF_1.2 168 SWT 16 Sybase 127 T Tomcat 104, 179, 226 TopLink 198, 201, 246 JPA 226 TopLink Essentials 259 TortoiseSVN 79 TPTP (Test & Performance Tools Platform) 11, 87 analyse des informations de proling 98 architecture 88 composants 89 mise en uvre 90
Monitoring Tools Project 12, 87 ouverture de la vue de proling 94 Platform Project 12, 87 Test Tools Project 12, 87 Tracing and Proling Tools Project 12, 87 vues de proling 91 U UML Visual Editor 18 V Velocity 104 VisualAge for Java 56 W Web Tools 101, 103, 295 artefacts du projet et vues JEE 125 assistant de publication 143 compltion de code 146 conguration dun projet de dveloppement Web 118 de lenvironnement dexcution 115 de la source de donnes du serveur 162 des bibliothques additionnelles spciques 117 cration de la page daccueil 142 de la servlet LoginServletTask 148 des classes daccs aux donnes 154 des composants servlets et JSP 157 des pages Login.jsp et LoginSuccess.jsp 145 Dali 259 design de lapplication Web 141 de la partie mtier 153 diteur de conguration 174 de JSP 147 HTML intgr 142
Index
379
tude de cas 291 excution dune requte JDBC 139 GMF 18 mise en uvre 114 de JSF 168 du dveloppement EJB3 215 patterns Commande et Singleton 154 proprits du projet 123 Seam 165, 178 Singleton 154 sous-projets JST 104 WST 111 structure et contenu du projet 124
Web Tools 2.0 90, 120, 262 Dali 259 WebLogic_10 202 WebSphere_7 202 Widgets Toolkit 22 Working Set 6 WST (Web Standard Tools) 10, 103, 111 assistant de cration et de publication de services Web 113 monitoring TCP/IP 114 support des facets projet 111 HTML, CSS et JavaScript 112 Web Services 113 WTP (Web Tools Platform) 10, 103 WTP 2.0 114
X XDoclet 104, 105, 121, 217 XDoclet 1.2.3 122 XMI (XML Metadata Interchange) 305 Y Yahoo! Mail 21 Yoxos 215
Eclipse Europa
K. Djaafar
Karim Djaafar est consultant expert en technologies Java/JEE aprs plus dune dizaine dannes dexprience dans le domaine du dveloppement logiciel et du conseil au sein de SSII. Aujourdhui directeur technique de la SSII Jasmine Conseil, il assure des missions de conseil sur des projets Java/JEE mettant en uvre des frameworks Open Source tels que Hibernate, Spring ou Seam. Il intervient aussi bien sur les phases de conception des architectures applicatives, que sur les problmatiques de test, de dploiement sur les principaux serveurs dapplications JEE et doptimisation des performances.
Rsolument pratique, cet ouvrage montre comment utiliser de manire cohrente et efficace les diffrents outils de la suite Eclipse Europa, combins des frameworks tels que JBoss Seam, pour couvrir lensemble du cycle de dveloppement dune application Java EE 5 et tirer parti des innovations de la spcification EJB 3. Louvrage met laccent sur la conception du modle de donnes avec Data Tools, le dveloppement JSF avec Web Tools et Seam, le nouveau standard EJB 3.0, le mapping objet-relationnel avec Java Persistence API et le framework Dali, lapproche de dveloppement pilot par le modle avec EclipseUML et AndroMDA, les fonctionnalits avances du framework Seam et le dploiement sur le serveur JBoss. Cette approche est illustre au travers de ltude de cas WebStock, application e-commerce construite au fil de louvrage et dont le code source est disponible sur www.editions-eyrolles.com. Le lecteur acquerra ainsi une parfaite matrise des outils et une solide mthodologie de dveloppement reposant sur un ensemble de best practices en matire de conception dapplications EJB 3.
Au sommaire
Nouveauts dEclipse 3.3 (Europa) Support du client riche avec Eclipse RPC Dveloppement collaboratif et gestion de configuration avec CVS et Subversion sous Eclipse Profiling de code avec TPTP Web Tools et ses sous-projets Conception du modle de donnes avec Data Tools Dveloppement JSP avec Web Tools et les design patterns JSF et le framework Seam Dveloppement EJB 3 avec Web Tools et JBoss Gestion de la persistance avec JPA Mapping JPA avec Dali Mise en uvre de ltude de cas WebStock : modlisation MDA et gnration de code avec EclipseUML, dploiement sur JBoss Configuration EJB 3 avance avec Seam Annexes : procdures dinstallation (Eclipse Europa, JBoss), annotations Seam, profil EJB 3 pour AndroMDA.
9 7 8 2 2 1 2 1 2 06 1 5
Sur le site www.editions-eyrolles.com Dialoguez avec lauteur Tlchargez le code source de ltude de cas WebStock Dcouvrez les mises jour et complments