Développement d`un réseau social modulaire - CRIL

Transcription

Développement d`un réseau social modulaire - CRIL
Développement d’un réseau social modulaire
Stage - Master I
Matthieu Proucelle
Université d’Artois
29 mai 2009
Table des matières
1 JEE
1.1 Java . . . . . . . . . . . . .
1.2 Plate-forme . . . . . . . . .
1.3 Spécifications . . . . . . . .
1.3.1 JSR . . . . . . . . .
1.3.2 JCP . . . . . . . . .
1.3.3 JEE 5 . . . . . . . .
1.4 Modèle n-tier . . . . . . . .
1.5 Modèle en couche de JEE .
1.5.1 EJB . . . . . . . . .
1.5.2 JPA . . . . . . . . .
1.5.3 JSF . . . . . . . . .
1.6 Serveurs . . . . . . . . . . .
1.7 Sécurité - Authentification 1.7.1 Sécurité . . . . . . .
1.7.2 Authentification . .
1.7.3 Autorisations . . . .
1.8 Au delà des spécifications .
1.9 Logiciel Libre . . . . . . . .
1.9.1 Aspect Humain . . .
1.9.2 Aspect Économique
1.9.3 JEE et open source .
1.10 JEE6 . . . . . . . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
Autorisations
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
2 L’application
2.1 Présentation . . . . . . . . . . . .
2.2 Analyse . . . . . . . . . . . . . .
2.2.1 Fonctionnement . . . . . .
2.2.2 Rôles . . . . . . . . . . .
2.2.3 Cas d’utilisation . . . . .
2.3 Technologies choisies . . . . . . .
2.3.1 API et Frameworks . . . .
2.3.2 Environnement de travail
2.3.3 Serveur d’application . . .
2.4 Architecture . . . . . . . . . . . .
2.4.1 Persistance . . . . . . . .
2.4.2 Business-tier . . . . . . .
2.4.3 Web-tier . . . . . . . . . .
2.5 Modularité . . . . . . . . . . . .
2.5.1 Première approche . . . .
2.5.2 Portlets . . . . . . . . . .
2.6 Difficultés rencontrées . . . . . .
2.6.1 Bugs . . . . . . . . . . . .
2.6.2 Navigation . . . . . . . .
2.6.3 Création de composants .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4
4
4
4
5
5
5
6
6
7
8
9
10
10
10
10
11
11
11
12
12
12
12
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13
13
13
13
13
14
17
17
17
17
17
17
20
20
22
22
22
23
23
23
24
1
Remerciements
Je remercie tout particulièrement Mr Stéphane Cardon, mon tuteur, pour son engagement et son support
tout au long de ce stage. Je tenais aussi à remercier Mathieu Boniface avec qui j’ai partagé des discussions
des plus constructives et encourageantes.
2
Introduction
L’université d’Artois fournit à travers le Master Informatique de la faculté Jean Perrin une formation
avancée sur les technologies liées à internet. Le stage à effectuer en première année permet aux étudiants
d’apprécier pendant 8 semaines le travail en entreprise ou dans un laboratoire de recherche.
La première moitié de mon travail consistait à étudier et apprécier la technologie Java Entreprise Edition.
Cette technologie est un ensemble de spécifications qui permettent de développer des applications d’entreprises de grande envergure. Le premier chapitre dévoile les dessous de cette vaste technologie en détaillant
les points principaux et en élaguant les moins importants.
Lors de la deuxième partie de mon stage, j’ai développé une application permettant de mettre en ligne
un réseau social.
Un réseau social est un ensemble d’entités sociales, telles que des individus ou des organisations sociales,
reliées entre elles par des liens créés lors des interactions sociales.
Une application de réseau social est donc un moyen informatique de faire vivre un tel réseau. Elle doit
permettre à des personnes de créer des liens, d’interagir et de se regrouper.
Je présente les différentes parties du développement de ce logiciel, depuis le choix des technologies utilisées
jusqu’à l’analyse des conséquences de ces choix dans la seconde partie de ce document.
3
Chapitre 1
JEE
Certains acronymes sont récurrents dans ce document, c’est pourquoi il est nécessaire d’en faire une petite
présentation avant de se lancer dans le vif du sujet.
Un API pour Application Program Interface, est un ensemble de classes utilitaires permettant le développement
d’applications.
Un Framework est a l’instar d’un API, un ensemble de classes. Cependant il impose une architecture
logicielle que le développeur doit respecter.
JSE pour Java Standard Edition, la plateforme Java de base incluant les bibliothèques et les outils nécessaires
à l’exécution des programmes Java.
JDK pour Java Développement Kit, la plate-forme de développement de Java, regroupant les API et les
outils nécessaires au développement et à la compilation des programmes Java.
JEE pour Java Entreprise Edition.
1.1
Java
Java est un langage orienté objet, créé en 1995 par une équipe de développeurs Sun. Le but de ce
projet était de proposer un langage de programmation reprenant les forces du C++ mais en le simplifiant
énormément. Aujourd’hui Java a 14 ans, et est utilisé dans de nombreux domaines, depuis des petits logiciels
de bureau jusqu’aux énormes applications d’entreprise.
Ce langage est un langage interprété, c’est à dire qu’il n’est pas exécuté directement sur la machine, mais
sur une ”machine virtuelle” (un logiciel) installée sur l’ordinateur. Cette machine virtuelle, appelée JRE
pour Java Runtime Environnement, prend un fichier java précompilé en entrée et exécute le programme sur
l’hote. De ce fait, Java est portable. Le code source n’etant pas compilé pour une architecture en particulier,
les machines virtuelles de tous les systèmes répondent et exécutent de la même façon un programme Java,
sans que l’auteur ne se soucie de la portabilité de son code source.
Grâce à sa simplicité et à sa portabilité, Java est un langage qui permet une productivité accrue.
1.2
Plate-forme
JEE (Java Entreprise Edition) peut être considéré comme une extension de JSE (Java Standard Edition)
spécialisée dans les applications pour entreprises et internet. C’est un ensemble de spécifications, de services
et de protocoles qui permettent le développement d’applications réseaux robustes. La plate-forme distribuée
par Sun est un groupe de logiciels, composé d’un serveur d’applications, d’un SGBD, et de différents outils
utilitaires.
1.3
Spécifications
Une spécification est un ensemble de documents qui sont écrits avant le développement d’une technologie
et qui décrivent précisément le fonctionnement des différents composants de cette dernière.
4
1.3.1
JSR
Le langage Java et les plate-formes JSE et JEE sont spécifiés. Chaque changement ou nouveauté dans
le langage est proposé, étudié, spécifié et implémenté. Toutes ces spécifications sont issues des JSR (Java
Specification Request). A la sortie du composant, les JSR finales fournissent le code source du composant
et une série de tests qui vont être utilisés par des éditeurs tiers pour attester de la compatibilité de leurs
applications.
1.3.2
JCP
Les JSR sont émises par un organisme nommée JCP (Java Community Process). Cette organisation qui
regroupe des entreprises, organisations et développeurs Java, est responsable des évolutions du langage et
coordonne leurs sorties.
1.3.3
JEE 5
Voici une liste des principales spécifications de JEE :
• Java API for Web Services (JAX-WS) 2.0,
• Java API for XML-Based RPC (JAX-RPC) 1.1
• Java Architecture for XML Binding (JAXB) 2.0
• SOAP with Attachments API for Java (SAAJ)
• Streaming API for XML (StAX)
• Web Service Metadata for the Java Platform
• Enterprise JavaBeans (EJB) 3.0
• J2EE Connector Architecture (JCA) 1.5
• Java Servlet 2.5
• JavaServer Faces (JSF) 1.2
• JavaServer Pages (JSP) 2.1
• JavaServer Pages Standard Tag Library (JSTL)
• J2EE Management
• J2EE Application Deployment
• Java Authorization Contract for Containers
• Common Annotations for the Java Platform
• Java Message Service (JMS) API
• Java Persistence API
• Java Transaction API (JTA)
• JavaBeans Activation Framework (JAF) 1.1
• JavaMail
Malgrè la taille impressionnante de cette liste, on peut facilement regrouper les spécifications les plus
intéressantes en 4 groupes :
• Logique métier
– Enterprise JavaBeans (EJB) 3.0 :
Stateful, stateless, message-driven, les EJB sont le cœur de la couche logique de l’application.
– JavaMail :
Envoi et réception des mail.
• Persistance
– Java Persistence API : API de persistance qui permet d’enregistrer les états des instances de nos
classes en charge de stocker les données.
• Partie Web
– Java Servlet 2.5 : Un servlet est une classe qui permet de produire dynamiquement des données
suite à une requête HTTP. Ici les servlets sont souvent utilisés avec les pages JSP ou comme proxy
entre les EJB et une application client.
– JavaServer Faces (JSF) 1.2 : Java Server Faces est un framework de présentation respectant le
paradigme MVC.
– JavaServer Pages (JSP) 2.1 : Les JSP sont des pages html qui contiennent du code qui sera interprété
par le serveur avant l’envoi de la réponse au client. Elles sont souvent couplées à un servlet.
– JavaServer Pages Standard Tag Library (JSTL) : La JSTL est l’ensemble des tags pouvant être
utilisés dans une page jsp, qui sert de standard pour les serveurs compatibles JEE.
5
• Les web services
– Java API for Web Services (JAX-WS) 2.0
– Java API for XML-Based RPC (JAX-RPC) 1.1
– Java Architecture for XML Binding (JAXB) 2.0
– SOAP with Attachments API for Java (SAAJ)
– Streaming API for XML (StAX)
– Web Service Metadata for the Java Platform
Ces quatre groupes représentent les 4 parties majeures d’une application d’entreprise. En faisant abstraction des web services, les ensembles Logique métier Persistance et Partie Web s’apparentent à ce que l’on
appelle tier ou couche. Ces tiers sont la base d’un paradigme de développement appelé modèle n-tier.
1.4
Modèle n-tier
Le développement n-tier (ou multi-tier) propose un modèle d’architecture en couche qui permet de séparer
les différentes parties d’une application. Une couche ne dépend que des couches de niveau supérieur. La
communication se fait entre deux couches adjacentes.
Le modèle n-tier le plus répandu est le modèle 3-tiers. Il définit 3 couches : une couche de présentation,
une seconde couche de logique métier, et une dernière couche de données.
Figure 1.1 – Le modèle 3-tiers
Le tier de présentation affiche les données au client. Il peut y avoir plusieurs tiers de présentation, chacun
indépendant des autres. Lorsque le client demande une ressource, le tier présentation envoie une requête au
tier logique métier. Ce dernier effectue le traitement logique de l’application en communicant avec le dernier
tier qui lui fournit les données nécessaires.
1.5
Modèle en couche de JEE
Java Entreprise Edition offre aux développeurs la possibilité de créer leurs applications sur une base
n-tier.
Voici les couches que l’on retrouve dans une application JEE :
• Tier Client : Le tier client peut être une application swing, un applet, une page web etc... C’est la
couche qui affiche les données à l’utilisateur.
• Tier Web : Le tier web est représenté ici par le couple JSP/Servlets et le framework JSF. C’est la
partie de l’application qui produit la présentation et qui l’envoie au navigateur client. Elle reçoit les
requêtes du client et fait la liaison avec les EJB si nécessaire.
• Tier Métier : Les EJB et entités, qui représentent la partie métier de l’application.
• Tier EIS (Enterprise Information System) : Ce tier est constitué d’une ou plusieurs bases de
données qui peuvent être réparties sur plusieurs machines. C’est ici que toutes les données persistantes
sont stockées.
6
Figure 1.2 – Le modèle n-tier
Cela étant dit, chacun est libre d’utiliser l’architecture qu’il désire. Par exemple un simple site web
dynamique, qui peut tenir dans un Web Container, n’aura pas besoin du tier Métier EJB. Effectivement, la
logique métier peut être implémentée directement dans le tier Web à l’aide de classes Pojo (Plain Old Java
Object).
Les EJB sont donc surtout utilisés pour les applications de grande envergure utilisant des webservices ou
des clients de différentes sortes (Web, Swing, WS, etc...).
1.5.1
EJB
Les EJB (Entreprises JavaBeans) sont des composants serveurs qui respectent la JSR 220.
Dans une application d’entreprise, ils représentent la logique métier, proposent une interface avec les
entités, et font office de Façade (au sens design pattern) au système.
Généralités
Un EJB est une classe java à laquelle on ajoute une ou plusieurs annotations qui vont définir son type.
Un système d’interface permet de définir les méthodes qui peuvent être appelées en local (à l’intérieur
de la JVM du serveur) ou à distance.
Exemple :
Listing 1.1 – Interfaces d’un EJB
@Local
public i n t e r f a c e MyBeanLocal {
public void doJob ( ) ;
public void doJobOnlyLocal ( ) ;
}
@Remote
public i n t e r f a c e MyBeanRemote {
public void doJob ( ) ;
}
Le bean qui implémentera l’interface MyBeanLocal proposera 2 méthodes qui pourront être appelées à partir
du serveur. S’l implémente aussi l’interface MyBeanRemote, la méthode doJob, sans aucun changement dans
le code, pourra aussi être invoquée d’un client distant.
7
EJB Stateless
Les EJB Stateless sont des composants qui fonctionnent de façon éphémère. Le client demande et reçoit
des données, et l’interaction se termine là. Ils n’ont pas d’état, l’utilisation des attributs de classe est donc à
proscrire car la durée de vie théorique d’un EJB Stateless est la même que le temps nécessaire pour traiter
la méthode.
On utilise l’annotation @Stateless pour définir un Stateless EJB :
Listing 1.2 – Stateless EJB
@Stateless
public c l a s s AdditionBean {
public int add ( int a , int b ) {
return a+b ;
}
}
EJB Stateful
Contrairement au composant sans état, les Stateful Session Beans associent les requêtes à un unique
client. Il peut donc conserver des données propres aux actions du client dans des attributs.
On utilise l’annotation @Stateful pour définir un Stateful Session Bean :
Listing 1.3 – Stateful EJB
@Stateful
public c l a s s A d d i t i o n S e s s i o n B e a n {
private int somme ;
public int add ( int a ) {
somme += a ;
return somme ;
}
}
MDB
Les MDB, ou Message Driven Beans, sont des EJB qui offrent un fonctionnement asynchrone à l’aide de
la technologie JMS (Java Messaging Service). En effet, pour les deux types de beans précédents, le client
envoyait une requête à l’EJB, puis se bloquait pour attendre la réponse. Ici la requête est placé dans une file
à l’aide de JMS, puis le client continue son traitement jusqu’à ce que le MDB retourne un résultat, encore
une fois par JMS. Un événement est à ce moment levé chez le client, qui peut dès lors traiter le résultat.
On utilise l’annotation @MessageDriven pour définir un MDB :
Listing 1.4 – MDB
@MessageDriven
public c l a s s BigCalculMDB implements M e s s a g e L i s t e n e r {
public void onMessage ( Message message ) {
/∗ E f f e c t u e un l o n g c a l c u l e t r e n v o i l e message par JMS ∗/
}
}
1.5.2
JPA
JPA (Java Persistence API) est un API permettant un mapping objet-relationnel au cœur de Java qui va
permettre d’enregistrer des objets Java dans une base de données relationnelle de façon transparente pour
le développeur. JPA est comme nous l’avons vu une spécification. Il existe différentes implémentations de
cette dernière dont TopLink, EclipseLink et Hibernate. Le code écrit avec l’API JPA sera donc compatible
avec n’importe laquelle de ces implémentations. JPA fait aussi abstraction du SGBD utilisé pour stocker
les données. En effet, la modification d’une simple ligne dans le fichier de configuration de JPA permet de
changer le SGBD utilisé.
8
Pour qu’une classe Java puisse être traitée et enregistrée par JPA dans une base, elle doit comporter
certaines annotations :
• Entity : L’annotation @Entity transforme une classe Java standard en une Entité. Les entités sont
les objets de base de JPA, et doivent comporter un id unique. Dans la plupart des cas, une entité
correspond à une table dans la base relationnelle.
• Embbeded et Embbedable : Dans un modèle objet, certaines classes n’ont pas à être des Entités.
Les annotation @Embbedable et @Embbedded permettent de mapper un objet à l’interieur d’un autre.
Au niveau relationnel, une seule table sera utilisée, dans laquelle on retrouvera les attributs des deux
objets.
• Relations : Tout comme dans un modèle relationnel, il est possible de définir des relations entre les
classes. Les relations 1-n utilisent les annotations @OneToMany et @ManyToOne, les relations n-n
l’annotation @ManyToMany et les relations 1-1 l’annotation @OneToOne.
• Annotations de mapping : A ces annotations principales s’ajoutent des annotations qui permettent
de gérer le mapping de façon précise. Il est ainsi possible de définir le nom des tables ou des colonnes
dans la base de données, le nom des clefs externes ou les mécanismes utilisés lors de mapping particuliers
(pour l’héritage par exemple), ou le type de chargement des relations 1-n et 0-n.
La configuration de JPA se fait dans un fichier persistence.xml, qui va définir le moteur JPA à utiliser et
le type et la configuration de la base de données. JPA propose aussi un langage de requêtes, dans la lignée
de SQL, qui permet de récupérer des éléments dans la base de données en utilisant des conditions : JPQL
(Java Persistence Query Language)
1.5.3
JSF
Java Server Faces est un framework JEE permettant de développer un site web en utilisant le design
pattern MVC. Il est indépendant de la technologie sous-jacente de présentation. Plus précisément, un site
codé en JSF peut être rendu avec JSP, mais aussi avec d’autres technologies comme XUL, ou Facelets.
Les règles de navigation se font à l’aide du fichier faces-config.xml, dans lequel on définit pour chaque
action de l’utilisateur la page à visiter. Cela instaure une certaine rigueur au niveau de la programmation
de la navigation dans les sites.
Dans une application utilisant JSF, on retrouve 2 composants importants : les vues (Faces) et les
contrôleurs (ManagedBeans).
– La présentation de l’application est effectuée par les Faces, qui sont des pages codées avec un langage
de balise.
Listing 1.5 – Exemple de balise JSF
<h : commandLink action=”#{ p r o f i l . doSearch }” >
<h : outputText value=” P r o f i l ” />
<f : param name=” p r o f i l M a i l ” value=”#{ j e e z e r . e m a i l } ” />
</h : commandLink>
– Les contrôleurs de l’application se trouvent dans des classes Java que l’on appelle Managed Bean. Les
ManagedBeans vont traiter les actions effectuées par l’utilisateur, et lancer des requêtes sur la partie
Métier de l’application, que sont les EJB, si nécessaire. Les vues vont ensuite récupérer les données au
niveau des ManagedBeans pour les afficher.
Comme nous l’avons vu sur la figure 1.2, le conteneur web et le conteneur EJB sont séparés dans le
serveur d’applications. Cependant le conteneur web a besoin d’appeler des méthodes sur les EJB. A la
base, un mécanisme lourd est utilisé pour récupérer une référence sur un EJB. Mais l’accés aux EJB à
travers les ManagedBean est simplifié grâce au système d’injection qui va permettre au conteneur web
d’injecter directement cette référence dans un attribut.
Le code suivant décrit ce fonctionnement :
Listing 1.6 – Injection
public c l a s s JEEzerControl {
@EJB
MemberLocal memberBean ;
public JEEzer g e t E n t i t y ( ) {
return memberBean . getMember ( u s e r . getName ( ) ) ;
}
9
Lors de l’instanciation de la classe JEEzerControl, une référence vers un EJB MemberLocal est injecté
par le serveur d’application dans l’attribut memberBean. L’appel de méthodes se déroule ensuite comme
avec n’importe quel objet.
1.6
Serveurs
Un serveur d’applications JEE doit implémenter les spécifications précédentes. Plus précisément, il doit
être capable de passer les tests fournis avec chaque spécification, donc implémenter les API de façon standard.
Il existe une multitude de serveurs JEE, chacun ayant une implémentation interne différente des API mais
exécutant les programmes de la même façon.
Lorsqu’un serveur passe tous les tests, il est reconnu par Sun comme Java EE 5 Compatible.
Un serveur d’application va coordonner les communications entre les composants, gérer le cycle de vie
des beans, les sessions HTTP, le nommage des beans et des webservices etc...
Les deux composantes importantes du serveur d’application sont les Conteneur WEB et les Conteneur
EJB. Le conteneur web est en charge du Web-tier tandis que le conteneur EJB a la responsabilité des EJB,
qui représentent le Business-tier.
Il existe des serveurs à part entière qui implémentent seulement la partie conteneur WEB. C’est le
cas de Tomcat, un serveur Servlet/JSP, appartenant au projet Apache. Même s’il est possible d’ajouter
quelques fonctionnalités à l’aide de plugins, je ne m’attarderai pas sur ces derniers dont les fonctions sont
trop restreintes pour des applications d’entreprises.
Les serveurs qui suivent sont donc des serveurs d’applications complets ”Java EE 5 Compatibles” :
– Apache Geronimo 2.1.2
– WebLogic Server 10.0
– IBM WASCE 2
– IBM WebSphere Application Server 7
– JBoss 5.0.0
– JBossAS 5.0.0
– Apusic Application Server 5
– Oracle Application Server 11
– OW2 JOnAS 5.1
– SAP NetWeaver 7.1
– Sun GlassFish Enterprise Server 9.1
– TmaxSoft JEUS 6
– GlassFish Application Server v2
– NEC WebOTX 8.1
Parmi ceux-ci, 4 retiennent notre attention par rapport à leur licence libre :
Serveur
Licence
Entreprise
Glassfish
GNU GPL 2
Sun
Geronimo
Apache 2.0
IBM
JBossAS
GNU LGPL
RedHat
JOnAS
GNU LGPL
OW2
Il faut bien comprendre que, exception faite des différences au niveau de l’installation, de la configuration
et des performances, ces serveurs fournissent une implémentation standard de JEE.
1.7
1.7.1
Sécurité - Authentification - Autorisations
Sécurité
Le serveur d’application fournit des services de haut niveau comme les EJB, ou la sécurité est appliquée
directement par le conteneur EJB. Nul besoin donc de passer des heures à vérifier si telle méthode ne pose
pas de problème de sécurité liée à un défaut de conception.
1.7.2
Authentification
Plusieurs solutions d’authentification existent comme JAAS, JGuard ou OpenSSO, mais les spécifications
de JEE définissent un protocole d’authentification et d’autorisation au niveau des EJB.
10
Dans ce système, le serveur utilise un REALM. Un realm est un ensemble d’identifiants, de mots de
passe, et de rôles qui identifient des utilisateurs valides.
Il existe plusieurs realms , qui utilisent chacun des méthodes d’authentification différentes. Celui qui
nous intéresse ici est JDBC-Realm qui utilise une base de données relationnelle pour stocker ces valeurs. Le
serveur d’application pourra donc récupérer les informations sur les membres directement dans nos entités.
Dans une application web, l’utilisateur non connecté sera envoyé vers une page de connections. La page
JSF va envoyer ses données d’identification à un servlet appelé j security check. Ce servlet va ensuite vérifier
ces données et renvoyer l’utilisateur sur la page demandée si elles sont valides.
Dans une application Swing, une fenêtre de connexion apparait et demande ces informations à l’utilisateur
lorsqu’une méthode protégée est appelée sur un EJB.
1.7.3
Autorisations
Par défaut, une méthode EJB est accessible par n’importe quel utilisateur, même anonyme. La restriction
de l’accès aux méthodes métier EJB se fera simplement à l’aide d’annotations comme dans l’exemple suivant :
Listing 1.7 – Restriction des droits
@Stateless
@ D e c l a r e R o l e s ( { ” a d m i n i s t r a t e u r ” , ” moderateur ” } )
public c l a s s HelloEJB implements H e l l o {
@PermitAll
public S t r i n g h e l l o W o r l d ( S t r i n g msg ) {
return ” Everybody : H e l l o , ” + msg ;
}
@RolesAllowed ( ” a d m i n i s t r a t e u r ” )
public S t r i n g helloAdmin ( S t r i n g msg ) {
return ”Admin : H e l l o , ” + msg ;
}
@RolesAllowed ( ” moderateur ” )
public S t r i n g helloModo ( S t r i n g msg ) {
return ”modo : H e l l o , ” + msg ;
}
}
1.8
Au delà des spécifications
Il existe bien d’autres technologies autour de JEE que celles qui proviennent des JSF.
– Des frameworks MVC, comme Struts, sont basés sur des technologies JEE et proposent une alternative
à JSF et JSP.
– Spring est un conteneur léger. Il a un structure similaire à un serveur JEE et permet au développeur
d’utiliser la programmation par aspect.
– Hibernate est un framework de persistance. Même s’il implémente aujourd’hui JPA, il propose de
nombreuses fonctionnalités supplémentaires.
– Il existe un grand nombre de frameworks Ajax pour JSF. La plupart proposent des composants qui
s’integrent facilement à JSF et permettent des traitements asynchrones. Les deux les plus utilisés sont
RichFaces et IceFaces.
– Et pour finir, il y a GWT (Google Web Toolkit). Développé par Google, il permet de créer des pages
web en code Java, qui est par la suite compilé en JavaScript.
1.9
Logiciel Libre
Le logiciel libre (souvent appelé open-source) ne cesse de faire parler de lui et de plus en plus d’entreprises
viennent à l’utiliser. Loin de moi l’idée de développer ici de façon exhaustive les différents atouts économiques
du modèle libre. Cependant, je souhaite présenter ma vision des choses quand à l’adoption de logiciels libres
dans une entreprise.
11
Une licence libre au sens FSF (Free Software Foundation) donne le droit d’utiliser, d’étudier, de modifier,
de dupliquer et de diffuser (donner et vendre) le dit logiciel.
1.9.1
Aspect Humain
Le Logiciel libre est avant tout un modèle de partage et de droits dans le monde informatique. Le modèle
économique mis en place impose des logiciels propriétaires et payants, que ce soit aux entreprises ou aux particuliers. Pourtant les logiciels libres apportent une alternative gratuite à la plupart des logiciels propriétaires.
Gratuite mais aussi respectant la vie privée et les droits de chacun. En effet, de par sa nature, le logiciel
libre permet, au-delà des 5 droits fondamentaux cités ci-dessus, d’assurer qu’aucun procédé d’identification,
de suivi, de restriction d’utilisation, ou d’espionnage ne soit intégré dans le-dit logiciel.
1.9.2
Aspect Économique
Le choix d’un solution logicielle libre permet aux entreprises de se défaire du lien fort avec l’éditeur
de logiciel auquel elles sont obligatoirement soumises en choisissant de payer une licence. Ce lien oblige
l’entreprise à payer les mises à jour du logiciel, parfois même les corrections de bug. Un logiciel libre, est
dans la plupart des cas gratuit. Ses mises à jour sont aussi gratuites.
Ce lien entre l’entreprise et l’éditeur de logiciel propriétaire place l’entreprise dans une position de
dépendance, a tel point que si l’éditeur vient à disparaı̂tre ou cesser le support du logiciel, la solution
logicielle de l’entreprise est bonne à jeter à la poubelle. Avec les logiciels libres, ce problème n’existe pas.
Lors de l’acquisition du logiciel, l’entreprise acquiert aussi le code source, et le droit de le modifier et de le
redistribuer. Si l’éditeur du logiciel libre cesse de le l’éditer, le support peut donc être fait par des ingénieurs
de l’entreprise et par la communauté.
Car la communauté a aussi une grande importance dans le maintien mais surtout dans le contrôle qualité
du logiciel libre. Effectivement, le code source étant ouvert, les ”hackeurs” du monde entier peuvent vérifier
et corriger les erreurs. C’est pour cela que le terme logiciel libre est aujourd’hui associé à une idée de qualité
et de sécurité.
Comme la plupart des logiciels libres sont gratuits, les éditeurs se basent sur un modèle économique qui
propose aux entreprises de payer non pas une licence, mais des services comme l’installation, le support ou
l’ajout de fonctionnalités.
Lorsqu’une nouvelle fonctionnalité est créée, son code source est souvent libéré et intégré au logiciel, ce
qui permet à l’éditeur d’améliorer son logiciel et au client d’assurer la pérennité, la qualité et l’évolution de
sa commande.
1.9.3
JEE et open source
JEE étant basé sur des spécifications ouvertes, des implémentations libres sont disponibles, comme nous
l’avons vu dans la partie serveur. Une application d’entreprise en JEE donc peut être développée sans
engendrer aucun cout lié à l’achat de licence. Mais le maitre d’ouvrage profitera aussi de toutes les qualités
inhérentes au logiciel libre citées ci-dessus. C’est un des points forts de cette technologie, qui convainc de
plus en plus d’entreprises d’adopter JEE.
1.10
JEE6
JEE6, qui sort en Septembre 2009, apporte son lot de nouveautés. Dans la lignée de Java 5, les annotations viennent remplacer les fichiers de configuration web.xml et faces-config.xml. Facelets (un framework
complémentant JSF) sera intégré par défaut dans les serveurs et permettra un développement de composants
JSF personnalisés bien plus simple. Les profils, qui représentent des sous-ensembles de JEE, font aussi partie
des nouveautés. Le profil Web par exemple, intégrera uniquement les outils nécessaires au développement
d’applications Web. Cela permettra de déployer des serveurs plus légers, implémentant tel ou tel profil en
fonction des besoins de l’entreprise. Et bien sur les nouvelles versions des spécifications comme les EJB
3.1, JPA 2.0 et JSF 2.0 apportent des modifications importantes, mais surtout une simplicité quant à la
configuration des applications.
12
Chapitre 2
L’application
2.1
Présentation
La deuxième partie de mon travail était de créer un moteur d’application de réseau sociale extensible
et modulaire, qui pourrait être utilisé dans différents contextes. L’application permettrait aux membres de
pouvoir créer une liste de connaissances, de s’échanger des messages instantanés ou différés, de créer des
groupes, des espaces de travail collaboratif etc... La grande difficulté de cette partie venait de l’utilisation
des technologies avec lesquelles je n’avais pas encore travaillé. En effet, à chaque nouvelle fonctionnalité, à
chaque nouvelle page, le temps de développement était incroyablement augmenté, au debut à cause de la
recherche des composants nécessaires au codage de l’application, et ensuite à cause de bugs récalcitrants
dont je vous parlerai par la suite.
2.2
Analyse
Même si toutes les fonctionnalités décrites par la suite ne sont pas implémentées, j’ai choisi de vous
présenter la totalité de l’analyse que j’ai réalisée avant le développement.
2.2.1
Fonctionnement
L’application propose un système d’inscription, de connexion, de gestion des droits et des groupes,
d’échange de messages et d’ajout de connaissances. Chaque partie du site est représentée par une entrée
dans le menu sur laquelle le membre doit cliquer pour y accéder. Un champ de recherche se trouve aussi en
haut à droite de la page. Il permet de rechercher des membres à l’aide de mots clés. Lors de la connexion
d’un membre, sa page d’accueil lui fait part des derniers événements comme la réception d’un message, une
”demande d’ami” par un autre membre, etc... Si le membre clique sur l’un de ces événements, il est redirigé
vers la page correspondante. L’événement est ensuite marqué comme lu. L’utilisateur peut accéder à son
profil par l’intermédiaire de la page profil. Les informations disponibles dans le profil sont le nom, le prénom,
et l’email. Si un membre le désire, il peut indiquer d’autres informations comme son adresse, ses activités ou
les choses auxquelles il s’intéresse. La page Amis liste les amis du membre et permet à ce dernier d’afficher
leur page personnelle. Sur cette page, il est possible d’accéder au profil du membre et de lui envoyer un
message. La boite de réception du membre lui permet de gérer ses messages. Il peut les lire, y répondre, ou
les archiver. Chaque membre a une page personnelle sur laquelle ses amis peuvent accéder à son profil ou lui
envoyer un message. Finalement, le membre peut se déconnecter à tout moment en cliquant sur Déconnexion.
2.2.2
Rôles
Trois rôles on étés définis dans l’application.
JEEzer est un simple membre du réseau social. Il a le droit de gérer ses propres mails, ses amis, ses groupes.
Moderator est un membre qui a le droit de modérer des messages et autres interactions.
Administrator est l’administrateur du réseau social.
13
2.2.3
Cas d’utilisation
Figure 2.1 – Cas d’utilisation généraux
Le diagramme 2.1 représente les cas d’utilisation généraux que peuvent réaliser le membre et l’adminitrateur. Ces cas d’utilisation sont détaillés ci-après.
14
Figure 2.2 – Gestion des messages
Un membre peut consulter, envoyer ou archiver ses messages.
Figure 2.3 – Gestion du profil
Le membre peut modifier ses informations personnelles, ajouter une photo pour son profil, ou régler des
préférences.
15
Figure 2.4 – Gestion du workspace
Un membre inscrit à un Workspace peut y ajouter, modifier ou archiver un fichier et inviter un autre
membre. Il est possible pour chaque inscrit de créer des workspaces.
Figure 2.5 – Administration
L’administrateur a des droits supplémentaires. Il peut inscrire ou désinscrire un membre et effectuer des
opérations de modération sur les interactions entre les membres.
16
2.3
2.3.1
Technologies choisies
API et Frameworks
Bien qu’il existe des nombreux frameworks et API qui viennent se greffer à JEE, j’ai décidé au tout début
de l’application d’utiliser en priorité des technologies issues des JSR. Le Business-tier est donc constitué
d’EJB 3.0, alors que le framework de présentation web utilisé est JSF. Cependant, JSF n’intégrant pas
l’Ajax avant sa version 2 qui sortira avec JEE6, il m’a paru important d’intégrer un framework qui proposait
des composants Ajax. Parmi tous les frameworks existants, j’ai choisi RichFaces. GWT était intéressant mais
ne s’intégrait pas assez facilement à JEE pour que je décide de l’utiliser.
2.3.2
Environnement de travail
Il était aussi nécessaire pour mon travail d’utiliser des logiciels gratuits mais également libres. Cela
permettant d’une part de développer l’application sans effectuer l’achat d’aucune licence, mais d’autre part
de montrer qu’il est possible et simple pour une organisation, une université ou une entreprise d’utiliser des
logiciels libres sur toute la plateforme de développement et de déploiement.
Pour l’environnement de développement, j’ai utilisé un système d’exploitation GNU/Linux et l’IDE Netbeans, tous deux sous licence GPL.
2.3.3
Serveur d’application
Le choix du serveur aurait pu se montrer plus difficile, mais comme je l’ai expliqué dans la première
partie, l’implémentation des spécifications est la même pour chacun d’entre eux. J’ai donc choisi Glassfish,
qui est une version open-source du serveur d’application payant de Sun et qui est facilement configurable
et clusterisable. Une autre raison qui m’a poussé à choisir ce dernier est que Sun l’utilise pour développer
JEE6, il sera donc le premier serveur d’application ”JEE6 Compatible” (une version prélude de Glassfish 3
est déjà disponible).
2.4
Architecture
Les cas d’utilisation m’ont permis de développer la partie statique de la modélisation. Les diagrammes
de classes qui suivent sont issus de longues réflexions sur les services que propose l’application, et réutilisent
des idées de l’analyse réalisée au premier semestre en Génie Logiciel sur l’application FSNet.
2.4.1
Persistance
La partie persistance de l’application contient les objets pouvant être enregistrés dans la base de données.
Une Entité doit avoir un id unique, aucune Entité ne peut donc être stockée sous forme d’interface, même
si elles peuvent en implémenter. Dans une application standard, des interfaces auraient été utilisées pour
remplacer des classes abstraites comme News.
Entités Sociales
La figure 2.6 montre les classes qui constituent la gestion des membres et des groupes. Dans l’application,
la classe SocialEntity représente une entité sociale du réseau. Cette entité possède un email unique en id et
une liste de rôles. La classe JEEzer, qui spécialise SocialEntity, est un membre de l’application représentant
une personne ”physique”. La classe possède donc des attributs propres à un humain, ainsi qu’une liste d’amis.
SocialGroup regroupe un ensemble de SocialEntity. Cette classe est utilisée pour la création de groupes et
de sous groupes. On peut reconnaitre une forme de design pattern composite, avec l’utilisation d’une classe
à la place de l’interface.
Membre
Dans la figure 2.7 sont présentés la classe JEEzer et ses relations avec la classe Profil qui va lui permettre
d’ajouter des informations personnelles, et aussi avec la classe PicturesAlbum, qui reprèsente un album photo
appartenant au membre. Ces albums pourront être créés par l’utilisateur qui pourra y ajouter des photos.
17
Figure 2.6 – Entités sociales
Figure 2.7 – Membre
Messages
La figure 2.8 inclut la partie messagerie de l’application. J’ai décidé d’utiliser une certaine redondance
au niveau des relations entre SocialEntity et Mail, qui permettra d’éviter d’inclure des requêtes couteuses
en temps, lors de la recherche des relations entre ces derniers. Comme on peut le voir sur le schéma, un mail
est envoyé par une personne à une instance de SocialEntity (donc un membre ou un groupe). Si le mail a
plusieurs destinataires, il sera dupliqué et envoyé à chacun. Un mail peut être aussi de type AskFriendMail,
qui représente en fait une ”demande d’ami”. Chaque message a un état, il peut être non lu, lu ou archivé.
News
Le système de news est exposé sur la figure 2.9. Une instance de SocialEntity possède une liste de News
qui elle-même possède un état lu, non lu ou archivé. Tous les types de news héritent de la classe abstraite
18
Figure 2.8 – Messages
Figure 2.9 – News
News et possèdent leurs propres attributs en fonction de leur type.
19
2.4.2
Business-tier
EJB
Figure 2.10 – EJB
Les 3 EJB utilisés dans l’application sont présentés dans la figure 2.10. Il a été difficile de choisir la façon
dont certaines actions seraient effectuées. En effet, les Entités se déplacent entre les couches de l’application, il
est donc possible de faire des traitements dans les EJB ou dans les ManagedBeans. J’ai décidé d’implémenter
dans les EJB des fonctions simples qui permettent de réaliser des opérations basiques sur les Entités comme
la création, la recherche, la mise à jour, ou l’effacement. D’autres actions sont directement effectuées dans
les ManagedBean.
Par exemple lorsque le membre lit un mail, le ManagedBean InboxControl qui représente le contrôleur de
la boite de réception va lui même marquer le mail comme lu et appeler la méthode updateMail() sur l’EJB.
Dans une autre application, la méthode permettant de marquer un mail comme lu aurait pu être placée sur
l’EJB responsable des messages :
public void setMailReaded(mail Mail, état State) ;
2.4.3
Web-tier
La partie web est composée de pages JSF et de contrôleurs. La figure 2.11 montre l’organisation des
pages JSF de l’application. Les pages à la racine permettent la connexion et l’inscription d’un membre.
Le répertoire secure contient les pages sécurisées, auxquelles seul un membre connecté peut accéder. On y
retrouve les différentes parties du site comme la page affichant le profil, ou celle affichant les résultats des
recherches de l’utilisateur. Les fichiers header et footer sont dupliqués car ils sont totalement différents pour
un visiteur non connecté et un membre connecté. La feuille CSS est aussi dupliquée, et cela est dû à un bug
que je détaille dans la section 2.6.2.
A chaque page présentant des informations venant d’entités, correspond un contrôleur. Chaque contrôleur
permet d’effectuer les échanges avec les EJB. Le code du contrôleur SearchControl est disponible dans les
annexes.
20
Figure 2.11 – Les pages JSF
Figure 2.12 – Contrôleurs
21
Figure 2.13 – Diagramme de séquence
Le diagramme de séquence de la figure 2.13 montre la propagation d’une demande de page par le membre,
depuis le clic de souris jusqu’à l’affichage de la nouvelle page. Lors du clic de l’utilisateur sur le bouton de
recherche, la méthode doSearch est appelée sur le ManagedBean SearchControl qui va à son tour invoquer
la méthode findMember() sur l’EJB MemberBean. La méthode findMember utilise une requête JPQL pour
rechercher des membres correspondant aux critères de recherche entrés par l’utilisateur. Une liste est créée
et retournée au contrôleur. La page JSF va ensuite parcourir cette liste et en afficher les éléments dans un
tableau.
2.5
Modularité
La partie du stage qui consistait à réaliser d’un système de modules pour l’application fut très fastidieuse.
Le développement du système de module n’a pas été finalisé. Le temps passé à analyser cette partie n’a
malheureusement pas son équivalent au niveau développement.
2.5.1
Première approche
Dans ma première approche, j’utilisais un index dynamique qui affichait les pages en fonction de la
variable ”page” passé en paramètre. Chaque partie du site (inbox, messagerie, etc...) était considérée comme
un module. Pour chacune de ces parties, une classe implémentant une interface Module, définissait les
différentes propriétés du module comme son titre et sa page d’accueil. Une classe ModuleLoader permettait
de charger dynamiquement ces modules et d’en récupérer les propriétés. Cependant, je n’ai pas eu le temps de
finir cette implémentation qui présente des inconvénients surtout au niveau du déploiement et du packaging
des modules. En effet lors du déploiement, la classe du module doit se situer dans un répertoire différent de
celui ou se trouvent les pages web, par sécurité. Les entités doivent aussi se trouver dans un jar séparé. Un
déploiement d’un module aurait été une tâche longue et fastidieuse.
2.5.2
Portlets
Cependant, il existe un système de modules appelé Portlets qui permet de créer des sites sous forme de
portail, chaque élément du menu représentant un portlet (ou module). Ce système permet donc de développer
22
de façon indépendante et standardisée des composants du site. Cependant les technologies associées à ce
système ne font pas partie du serveur d’application choisi, et le couplage des portlets avec JSF ajoute
une complexité non négligeable. Lorsque je me suis aperçu que le système de module personel n’etait pas
réalisable, il ne me restait plus assez de temps pour intégrer Portlet à l’application, aucun système de module
n’a donc pu etre developpé.
2.6
2.6.1
Difficultés rencontrées
Bugs
Tout au long de mon stage j’ai pu être confronté a une multitude de bugs. L’un des plus récalcitrants
était l’incapacité de Toplink (l’implémentation JPA) à charger mes classes @Embeddable dans des entités.
Voici le genre d’erreur que j’ai pu rencontrer :
Déploiement de l’application dans le domaine a échoué ; Exception [TOPLINK-28018] (Oracle TopLink
Essentials - 2.1 (Build b60e-fcs (12/23/2008))):
oracle.toplink.essentials.exceptions.EntityManagerSetupException
Exception Description: predeploy for PersistenceUnit [JEEz-ejbPU] failed.
Internal Exception: Exception [TOPLINK-30007] (Oracle TopLink Essentials - 2.1 (Build b60e-fcs
(12/23/2008))): oracle.toplink.essentials.exceptions.PersistenceUnitLoadingException
Exception Description: An exception was thrown while loading class: org.jeez.news.AcceptedFriendNew
to check whether it implements @Entity, @Embeddable, or @MappedSuperclass.
Internal Exception: java.lang.ClassNotFoundException: org.jeez.news.AcceptedFriendNew
Cette erreur survenant alors que l’annotation @Embbedeable se trouvait sur une toute autre classe.
Ne comprenant pas pourquoi cet exception était lancée, j’ai donc changé d’implémentation JPA et intégré
Hibernate à mon serveur. Hibernate chargeait la classe sans problème, cependant il ne réagissait pas de
la même façon que Toplink lors du chargement des associations dans le conteneur web. En effet, alors que
Toplink permet sans aucun problème le chargement dynamique d’une liste en LazyLoading directement dans
JSF lors de la création de la page de présentation, Hibernate ferme la session avant que ce chargement n’ait
lieu. Il m’a fallu me tourner vers OpenJPA, lequel me levait une exception au niveau de ma classe annoté
avec @Embbedable. J’ai donc transformé certaines classes en Entités et je suis repassé sous TopLink qui
n’avait plus aucun problème à démarrer.
J’ai donc pu tester 3 implémentations de JPA, qui est censé être un standard, et constater 3 comportements différents.
RichFaces m’a aussi posé quelques problèmes. Un bug non reproductible apparaissait parfois lors de
l’exécution d’une page contenant des composants RichFaces. Ce bug créait une récursivité infinie à l’interieur
de l’api RichFaces. Une méthode appelait une seconde méthode, qui rappelait la première, ainsi de suite.
2.6.2
Navigation
JSF a une façon particulière de gérer la navigation. En effet lorsque l’utilisateur navigue de page en
page, la barre d’adresse du navigateur affiche toujours l’adresse de la page précédente. Cela pose plusieurs
problèmes.
Le premier est lié bien sûr à l’échange de lien et à la sauvegarde d’un favori. En effet, la page enregistrée
ne sera pas celle qui est affichée sur le navigateur.
Le deuxième problème vient du ciblage des fichiers lors du changement de page. Si la nouvelle page est
dans un autre répertoire que la première, elle va naturellement cibler les images et autres ressources de façon
relative. Cependant JSF n’aura pas encore changé de répertoire. Il affichera la page avec des liens morts.
Le dernier problème rencontré à cause de cette navigation particulière dépend directement du problème
précédent et est liée au système d’authentification. En effet, les pages du répertoire secure ne sont normalement accessibles que lorsque l’utilisateur est connecté. Cependant, un simple lien sur la page d’accueil vers
une de ces pages permet de contourner ce mécanisme. Comme l’adresse n’est pas mise à jour, le filtre de
sécurité n’empêche pas l’accès à la page sécurisée, même si l’utilisateur n’est pas connecté.
Le seul moyen de corriger ce problème est d’introduire une balise <redirect/> dans les règles de navigation
de chaque page, qui va utiliser une redirection HTTP, mais qui apporte des requêtes réseau supplémentaires.
23
2.6.3
Création de composants
La création de composants en JSF est très difficile sans l’ajout de certains frameworks comme Facelets. Il
y a dans mon code quelques parties qui se ressemblent et qui auraient pu être factorisées dans des composants.
JEE 6 integrera Facelet par défaut pour palier à ce problème.
24
Conclusion
Âpres 8 semaines passées à travailler sur JEE et sur l’application, j’ai la possibilité de prendre un peu de
recul et de constater les conséquences de mes choix.
J’ai depuis le début de mon travail essayé d’utiliser un maximum de technologies et d’orienter l’architecture de mon application comme une application d’entreprise. Même si seul le site web a été développé,
le modèle en couche de l’application permet d’ajouter facilement des WebServices, ou des clients différents
du navigateur internet (clients swing, ou pour téléphone portable). De ce fait, j’ai pu utiliser non pas seulement la partie web de JEE mais toute la partie application, ce que me permet d’avoir aujourd’hui une vue
d’ensemble de la technologie.
JEE est une technologie que j’ai eu grand plaisir à découvrir. Cependant, certaines spécifications comme
JSF et JPA, sont jeunes et doivent encore mûrir (cf. 2.6.1 page 23). Les versions 2.0 de JSF et JPA vont
apporter de nombreux changements, que je suis impatient de tester. Le choix d’une telle technologie pour
un stage de Master I était osée. Intégrer tous ces concepts pour les appliquer lors du développement de
l’application, en si peu de temps, a été difficile.
La découverte d’un framework ou d’un API apporte son lot de bonnes choses mais aussi ses difficultés.
Le couplage JSF-EJB laisse une grande liberté au développeur quant à la méthode à utiliser au niveau de
l’utilisation des Entités. Est-il plus intéressant de laisser la responsabilité du traitement et du chargement de
certaines données à JSF, ou vaut-il mieux multiplier les méthodes au niveau EJB ? Cette question ne trouve
de réponse que dans l’expérience. A partir de projets open-source, de tutoriels et d’exemples de code, j’ai
réussi à extraire un modèle sur lequel je me suis basé pour développer mon projet. Mais aujourd’hui encore,
des questions restent en suspend.
Le choix du sujet de mon stage a été immediat etant donnée qu’il portait sur les technologies sur
lesquelles repose la formation du Master ILI. Technologies dans lesquelles je souhaite me spécialiser. La
découverte de JEE a été une bonne expérience, même si certaines parties assez rébarbatives m’ont ralenti dans le développement de l’application. Cependant les 8 semaines de recherche, d’apprentissage, de
développement, et parfois de galère m’ont permis d’intégrer une technologie d’une envergure telle qu’elle
peut parfois désorienter les néophytes. L’avancement du projet n’est pas à la hauteur de mes ambitions et
de la motivation que je montrais au commencement de cette aventure. Mais la formation et l’expérience que
j’ai pu acquérir me permettent de regarder en arrière sans regret aucun et de jouir d’une connaissance qu’il
m’aurait été difficile d’obtenir avec un stage dans un langage comme PHP, même en entreprise.
25
Bibliographie
[1] Antonio Goncalves. Java EE 5. Eyrolles, 2007.
[2] David Flanagan. Java en concentré. O’Reilly, 2006.
[3] Eric Jendrock Jennifer Ball Debbie Carson Ian Evans Scott Fordin Kim Haase. The java ee5
tutorial. http ://java.sun.com/javaee/5/docs/tutorial/doc/, Octobre 2008.
[4] Michael Sikora. Ejb 3 security. http ://www.packtpub.com/article/ejb-3-security, Septembre 2008.
[5] Shing Wai Chan. Jdbc realm in glassfish. http ://blogs.sun.com/swchan/entry/jdbcrealm in glassfish,
Juin 2006.
[6] Shing Wai Chan. Security annotations and authorization in glassfish and the java ee 5 sdk. http ://java.sun.com/developer/technicalArticles/J2EE/security annotation/, Juillet 2006.
26
Annexes
Listing 2.1 – Code de searchResult.jsp
<%@page contentType=” t e x t / html ”%>
<%@page pageEncoding=”UTF−8”%>
<%@ t a g l i b u r i=” h t t p : / / r i c h f a c e s . o r g / a 4 j ” p r e f i x=” a 4 j ”%>
<%@ t a g l i b u r i=” h t t p : / / r i c h f a c e s . o r g / r i c h ” p r e f i x=” r i c h ”%>
<%@ t a g l i b p r e f i x=” f ” u r i=” h t t p : / / j a v a . sun . com/ j s f / c o r e ”%>
<%@ t a g l i b p r e f i x=”h” u r i=” h t t p : / / j a v a . sun . com/ j s f / html ”%>
< !DOCTYPE HTML PUBLIC ”−//W3C//DTD HTML 4 . 0 1 T r a n s i t i o n a l //EN”
” h t t p : / /www. w3 . o r g /TR/ html4 / l o o s e . dtd ”>
<f : view>
<html>
<head>
<meta http−e q u i v=” Content−Type” content=” t e x t / html ; c h a r s e t=UTF−8”
/>
<l i n k r e l=” s t y l e s h e e t ” type=” t e x t / c s s ” href=” . / s t y l e . c s s ” />
<t i t l e></ t i t l e>
</head>
<body>
<%@ i n c l u d e f i l e =” h e a d e r . j s p ” %>
<div id =” c o n t e n t ”>
<r i c h : p a n e l>
<f : f a c e t name=” h e a d e r ”>
<h : outputText value=” R e s u l t a t s ” />
</ f : f a c e t>
<h : form id=” r e s u l t s ”>
<r i c h : d a t a L i s t value=”#{s e a r c h . f o u n d F r i e n d s } ” var=”
f o u n d J e e z e r ”>
<h : commandLink action=”#{j e e z e r P a g e . doPrepare } ” >
<f : param name=” e m a i l ” value=”#{f o u n d J e e z e r .
e m a i l } ” />
<h : outputText value=”#{f o u n d J e e z e r . f i r s t N a m e }
#{f o u n d J e e z e r . lastName } ” />
</h : commandLink>
</ r i c h : d a t a L i s t>
<r i c h : d a t a L i s t value=”#{s e a r c h . foundAsked } ” var=”
f o u n d J e e z e r ”>
<h : outputText value=”#{f o u n d J e e z e r . f i r s t N a m e } #{
f o u n d J e e z e r . lastName }” />
<h : outputText value=” En a t t e n t e d ’ une r e p o n s e ” />
27
</ r i c h : d a t a L i s t>
<r i c h : d a t a L i s t value=”#{s e a r c h . f o u n d N o t F r i e n d s } ” var=”
f o u n d J e e z e r ”>
<% // TODO modal p a n e l avec message %>
<h : outputText value=”#{f o u n d J e e z e r . f i r s t N a m e } #{
f o u n d J e e z e r . lastName }” />
<a 4 j : commandLink action=”#{s e a r c h . doAskFriend } ”
reRender=” r e s u l t s ”>
<f : param name=” e m a i l ” value=”#{f o u n d J e e z e r .
e m a i l } ” />
<h : outputText value=” A j o u t e r comme ami” />
</ a 4 j : commandLink>
</ r i c h : d a t a L i s t>
</h : form>
</ r i c h : p a n e l>
</ div>
<%@ i n c l u d e f i l e =” f o o t e r . j s p ” %>
</body>
</html>
</ f : view>
\ label { annexcontroleur }
28
Listing 2.2 – Code de SearchControl.java
/∗
∗ SearchControl . java
∗
∗ C o p y r i g h t ( c ) 2009 M a t t h i e u P r o u c e l l e . A l l r i g h t s r e s e r v e d .
∗
∗ This f i l e i s p a r t o f JEEz .
∗
∗ JEEz i s f r e e s o f t w a r e : you can r e d i s t r i b u t e i t and/ or modify
∗ i t under t h e terms o f t h e GNU General P u b l i c L i c e n s e as p u b l i s h e d by
∗ t h e Free S o f t w a r e Foundation , e i t h e r v e r s i o n 3 o f t h e L i c e n s e , or
∗ ( a t your o p t i o n ) any l a t e r v e r s i o n .
∗
∗ JEEz i s d i s t r i b u t e d i n t h e hope t h a t i t w i l l be u s e f u l ,
∗ b u t WITHOUT ANY WARRANTY; w i t h o u t even t h e i m p l i e d warranty o f
∗ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See t h e
∗ GNU General P u b l i c L i c e n s e f o r more d e t a i l s .
∗
∗ You s h o u l d have r e c e i v e d a copy o f t h e GNU General P u b l i c L i c e n s e
∗ a l o n g w i t h JEEz .
I f not , s e e <h t t p : / /www. gnu . o r g / l i c e n s e s />.
∗/
package o r g . j e e z . c o n t r o l s ;
import
import
import
import
import
import
import
import
java . io . S e r i a l i z a b l e ;
java . u t i l . ArrayList ;
java . u t i l . List ;
j a v a x . e j b . EJB ;
o r g . j e e z . e n t i t i e s . s o c i a l s . JEEzer ;
o r g . j e e z . s t a t e l e s s . MemberLocal ;
o r g . j e e z . s t a t e l e s s . MessageLocal ;
o r g . j e e z . u t i l s . ParamManager ;
/∗ ∗
∗
∗ @author M a t t h i e u P r o u c e l l e
∗/
public c l a s s S e a r c h C o n t r o l implements S e r i a l i z a b l e {
@EJB
private
@EJB
private
private
private
private
private
MemberLocal memberBean ;
MessageLocal messageBean ;
S t r i n g s e a r c h S t r i n g = ” Recherche ” ;
L i s t <JEEzer> f o u n d F r i e n d s ;
L i s t <JEEzer> f o u n d N o t F r i e n d s ;
L i s t <JEEzer> foundAsked ;
/∗ ∗
∗ Get t h e v a l u e o f foundAsked
∗
∗ @return t h e v a l u e o f foundAsked
∗/
public L i s t <JEEzer> getFoundAsked ( ) {
return foundAsked ;
}
/∗ ∗
∗ S e t t h e v a l u e o f foundAsked
29
∗
∗ @param foundAsked new v a l u e o f foundAsked
∗/
public void setFoundAsked ( L i s t <JEEzer> foundAsked ) {
t h i s . foundAsked = foundAsked ;
}
/∗ ∗
∗ Get t h e v a l u e o f f o u n d N o t F r i e n d s
∗
∗ @return t h e v a l u e o f f o u n d N o t F r i e n d s
∗/
public L i s t <JEEzer> getFoundNotFriends ( ) {
return f o u n d N o t F r i e n d s ;
}
/∗ ∗
∗ Set the value of foundNotFriends
∗
∗ @param f o u n d N o t F r i e n d s new v a l u e o f f o u n d N o t F r i e n d s
∗/
public void setFoundNotFriends ( L i s t <JEEzer> f o u n d N o t F r i e n d s ) {
this . foundNotFriends = foundNotFriends ;
}
/∗ ∗
∗ Get t h e v a l u e o f f o u n d F r i e n d s
∗
∗ @return t h e v a l u e o f f o u n d F r i e n d s
∗/
public L i s t <JEEzer> getFoundFriends ( ) {
return f o u n d F r i e n d s ;
}
/∗ ∗
∗ Set the value of foundFriends
∗
∗ @param f o u n d F r i e n d s new v a l u e o f f o u n d F r i e n d s
∗/
public void s e t F o u n d F r i e n d s ( L i s t <JEEzer> f o u n d F r i e n d s ) {
this . foundFriends = foundFriends ;
}
/∗ ∗
∗ Get t h e v a l u e o f s e a r c h S t r i n g
∗
∗ @return t h e v a l u e o f s e a r c h S t r i n g
∗/
public S t r i n g g e t S e a r c h S t r i n g ( ) {
return s e a r c h S t r i n g ;
}
/∗ ∗
∗ Set the value of searchString
∗
∗ @param s e a r c h S t r i n g new v a l u e o f s e a r c h S t r i n g
∗/
public void s e t S e a r c h S t r i n g ( S t r i n g s e a r c h S t r i n g ) {
30
this . searchString = searchString ;
}
/∗ ∗
∗ Get t h e v a l u e o f found
∗
∗ @return t h e v a l u e o f found
∗/
public L i s t <JEEzer> getFound ( ) {
return f o u n d N o t F r i e n d s ;
}
/∗ ∗
∗ S e t t h e v a l u e o f found
∗
∗ @param found new v a l u e o f found
∗/
public void setFound ( L i s t <JEEzer> found ) {
t h i s . f o u n d N o t F r i e n d s = found ;
}
public S t r i n g doSearch ( ) {
JEEzer j e e z e r = JEEzerControl . g e t S e s s i o n I n s t a n c e ( ) . g e t E n t i t y ( ) ;
f o u n d N o t F r i e n d s = new A r r a y L i s t <JEEzer >() ;
f o u n d F r i e n d s = new A r r a y L i s t <JEEzer >() ;
foundAsked = new A r r a y L i s t <JEEzer >() ;
i f ( s e a r c h S t r i n g != null && ! s e a r c h S t r i n g . e q u a l s ( ” Recherche ” ) ) {
L i s t <JEEzer> found = memberBean . findMembers ( s e a r c h S t r i n g ) ;
System . out . p r i n t l n ( j e e z e r . g e t A s k e d F o r f r i e n d s ( ) ) ;
f o r ( JEEzer j : found ) {
i f ( j . isAFriendOf ( j e e z e r ) ) {
f o u n d F r i e n d s . add ( j ) ;
} else i f ( j e e z e r . getAskedForfriends () . contains ( j ) ) {
foundAsked . add ( j ) ;
} else {
f o u n d N o t F r i e n d s . add ( j ) ;
}
}
}
s e a r c h S t r i n g = ” Recherche ” ;
return ” s e a r c h ” ;
}
public void doAskFriend ( ) {
S t r i n g f r i e n d E m a i l = ParamManager . getParam ( ” e m a i l ” ) ;
S t r i n g body = ParamManager . getParam ( ” body ” ) ;
messageBean . a s k F o r F r i e n d ( f r i e n d E m a i l , body ) ;
JEEzer t a r g e t = memberBean . getMember ( f r i e n d E m a i l ) ;
f o u n d N o t F r i e n d s . remove ( t a r g e t ) ;
foundAsked . add ( t a r g e t ) ;
}
public boolean f r i e n d ( ) {
return f a l s e ;
}
}
31
Listing 2.3 – Code de MemberBean
/∗
∗ MemberBeanBean . j a v a
∗
∗ C o p y r i g h t ( c ) 2009 M a t t h i e u P r o u c e l l e . A l l r i g h t s r e s e r v e d .
∗
∗ This f i l e i s p a r t o f JEEz .
∗
∗ JEEz i s f r e e s o f t w a r e : you can r e d i s t r i b u t e i t and/ or modify
∗ i t under t h e terms o f t h e GNU General P u b l i c L i c e n s e as p u b l i s h e d by
∗ t h e Free S o f t w a r e Foundation , e i t h e r v e r s i o n 3 o f t h e L i c e n s e , or
∗ ( a t your o p t i o n ) any l a t e r v e r s i o n .
∗
∗ JEEz i s d i s t r i b u t e d i n t h e hope t h a t i t w i l l be u s e f u l ,
∗ b u t WITHOUT ANY WARRANTY; w i t h o u t even t h e i m p l i e d warranty o f
∗ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See t h e
∗ GNU General P u b l i c L i c e n s e f o r more d e t a i l s .
∗
∗ You s h o u l d have r e c e i v e d a copy o f t h e GNU General P u b l i c L i c e n s e
∗ a l o n g w i t h JEEz .
I f not , s e e <h t t p : / /www. gnu . o r g / l i c e n s e s />.
∗/
package o r g . j e e z . s t a t e l e s s ;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
java . s e c u r i t y . Principal ;
java . u t i l . ArrayList ;
j a v a . u t i l . Date ;
java . u t i l . List ;
j a v a x . a n n o t a t i o n . Resource ;
javax . annotation . s e c u r i t y . DeclareRoles ;
javax . annotation . s e c u r i t y . PermitAll ;
javax . annotation . s e c u r i t y . RolesAllowed ;
j a v a x . e j b . EJB ;
javax . ejb . SessionContext ;
javax . ejb . S t a t e l e s s ;
j a v a x . p e r s i s t e n c e . EntityManager ;
javax . p e r s i s t e n c e . PersistenceContext ;
j a v a x . p e r s i s t e n c e . Query ;
o r g . j e e z . e n t i t i e s . s o c i a l s . JEEzer ;
org . j e e z . e n t i t i e s . s o c i a l s . P r o f i l ;
o r g . j e e z . news . AcceptedFriendNew ;
/∗ ∗
∗
∗ @author M a t t h i e u P r o u c e l l e
∗/
@ S t a t e l e s s ( name = ” beans /MemberBean” )
public c l a s s MemberBean implements MemberLocal {
@ P e r s i s t e n c e C o n t e x t ( unitName = ”JEEz−ejbPU” )
private EntityManager em ;
@Resource
SessionContext ctx ;
@EJB
private MessageLocal messageBean ;
@PermitAll
public JEEzer getMember ( f i n a l S t r i n g m a i l ) {
Query query = em . c r e a t e Q u e r y ( ”SELECT j FROM JEEzer j WHERE j . e m a i l =:
32
email ” ) ;
query . s e t P a r a m e t e r ( ” e m a i l ” , m a i l ) ;
JEEzer j e e z e r = ( ( JEEzer ) query . g e t S i n g l e R e s u l t ( ) ) ;
return j e e z e r ;
}
public JEEzer getCurrentMember ( ) {
P r i n c i p a l cp = c t x . g e t C a l l e r P r i n c i p a l ( ) ;
return getMember ( cp . getName ( ) ) ;
}
@RolesAllowed ( ” A d m i n i s t r a t o r ” )
public void c r e a t e E n v i r o n n e m e n t ( ) { . . . }
@PermitAll
public void createMember ( JEEzer member ) {
em . p e r s i s t ( member ) ;
}
@PermitAll
public L i s t <JEEzer> findMembers ( S t r i n g s e a r c h ) {
A r r a y L i s t <JEEzer> l i s t e = new A r r a y L i s t <JEEzer >() ;
String [ ] st = search . s p l i t (” ”) ;
for ( S t r i n g s : s t ) {
Query query = em . c r e a t e Q u e r y ( ”SELECT j FROM JEEzer j WHERE UPPER( j
. e m a i l ) LIKE : token ” +
”OR UPPER( j . f i r s t N a m e ) LIKE : token ” +
”OR UPPER( j . lastName ) LIKE : token ” ) ;
query . s e t P a r a m e t e r ( ” token ” , s . toUpperCase ( ) ) ;
L i s t <JEEzer> j e e z e r s = ( ( L i s t <JEEzer >) query . g e t R e s u l t L i s t ( ) ) ;
l i s t e . addAll ( j e e z e r s ) ;
}
System . out . p r i n t l n ( ”EJB : found = ” + l i s t e ) ;
return l i s t e ;
}
@PermitAll
public void updateMember ( JEEzer j e e z e r ) {
em . merge ( j e e z e r ) ;
}
@PermitAll
public void v a l i d a t e F r i e n d ( S t r i n g f r i e n d E m a i l ) {
JEEzer member = getCurrentMember ( ) ;
JEEzer newFriend = getMember ( f r i e n d E m a i l ) ;
member . addFriend ( newFriend ) ;
newFriend . addFriend ( member ) ;
AcceptedFriendNew theNew = new AcceptedFriendNew ( member ) ;
em . merge ( theNew ) ;
newFriend . addNew ( theNew ) ;
em . merge ( member ) ;
em . merge ( newFriend ) ;
}
33
@RolesAllowed ( ” A d m i n i s t r a t o r ” )
public void deleteMember ( JEEzer j e e z e r ) {
em . merge ( j e e z e r ) ;
em . remove ( j e e z e r ) ;
}
}
34