Turning Client Vision into Results
Download
Report
Transcript Turning Client Vision into Results
Jboss Seam &
Seam Hotel Booking
Sommaire
•
Jboss Seam
–
–
–
–
–
–
–
–
–
•
Seam Hotel Booking
–
–
–
–
–
–
2
Présentation générale
Les composants Seam
Un modèle de programmation contextuelle
Bijection
dataModel
Intégration JSF/EJB3
Validation des formulaires
Navigation
Le cycle de vie
Présentation de l’application
Authentification
Recherche
Conversation
Sécurité
Navigation
Turning Client Vision into Results
Jboss Seam
3
Turning Client Vision into Results
Présentation générale
• Framework Open Source développé par Jboss et initié
par Gavin King, le père d’Hibernate
• Conteneur léger J2EE
• Seam est l’un des premiers Framework à supporter
les architectures avec état grâce à la notion de
conversation
• Il utilise un modèle de programmation POJO
4
Turning Client Vision into Results
Présentation générale
• Seam intègre de nombreuses technologies :
– Le standard JSF ainsi que les composants graphiques
RichFaces, IceFaces (composants graphiques riches), et
Ajax4JSF (extension Ajax des composants JSF de base)
– Seam Remoting : API JavaScript permettant d'accéder depuis
le navigateur à un composant Seam coté serveur
– Le standard EJB stateless et stateful d’EJB3 (pour les
composants conversationnels)
– Le standard JPA et les entités d'EJB 3 pour la persistance
– JBoss Drools : sécurité déclarative par règles
5
Turning Client Vision into Results
Présentation générale
– JBoss jBPM : processus fonctionnels et workflows
– Support de GWT (Google Web Toolkit)
– Les web services (possibilité d’utiliser un composant Seam en
tant que web service)
– Hibernate Search
– Itext : génération de PDF
– TestNG : framework pour faciliter la création de tests unitaires
– …
6
Turning Client Vision into Results
Présentation générale
7
Turning Client Vision into Results
Les composants Seam
• Les composants prennent en charge les
fonctionnalités et la logique métier de l’application
web
• Ils permettent également de gérer des événements de
la couche « vue » ou d’intéragir avec la base de
données
• Ce sont des objets POJOs
• Les composants sont définis par 3 éléments : Le nom,
la portée et le rôle (gérés par des annotations)
8
Turning Client Vision into Results
Les composants Seam
• Les composants Seam sont associés à des variables
du contexte grâce à l’annotation @Name. Cette
déclaration correspond à la balise <managed-beanname> issue du fichier « faces-config.xml ». Le nom
du composant doit être unique dans le système
• Un composant Seam est obligatoirement déclaré dans
un contexte :
– Soit de manière implicite (en fonction du type de composant)
– Soit de manière explicite en précisant le scope à l’aide de
l’annotation @Scope
9
Turning Client Vision into Results
Les composants Seam
• Un composant peut être rattaché à plusieurs variables de
contexte. Le couple d’annotations @Name/@Scope permet
de définir un « rôle » par défaut. Il est possible de l’enrichir
en ajoutant de nouveaux « rôles » grâce à @Role(name=,
scope=) ou @Roles({@Role(), @Role()})
• Seam admet 5 types de composants :
– Stateless session bean (scope par défaut : STATELESS)
– Stateful session bean (scope par défaut : CONVERSATION)
– Entity bean (scope par défaut : CONVERSATION)
– JavaBean (scope par défaut : EVENT)
– Message-driven beans
10
Turning Client Vision into Results
Les composants Seam
• Le cycle de vie d’un composant peut être géré par les
annotations @Create et @Destroy (redéfinition des
annotations @PostConstruct et @Predestroy):
– @Create : Une méthode annotée de @create sera appelée
immédiatement après la création du composant
– @Destroy : Une méthode annotée de @destroy sera appelée
avant la destruction du contexte
11
Turning Client Vision into Results
Les composants Seam
@Scope(ScopeType.SESSION)
@Name("MyDatabaseUtils")
Public class MyDatabaseUtils{
@Create
public void initDatabase(){
}
@Destroy
public void closeDbResources(){
}
}
12
Turning Client Vision into Results
Un modèle de programmation
contextuelle
Ordre de priorité de recherche
• Seam introduit de nouveaux contextes :
13
– Event : C’est le plus « petit » contexte de Seam. Un composant
associé à un contexte « Event » est détruit à la fin de la
requête
– Page : Un composant associé à un contexte « Page » est lié à
une page spécifique. L’état est stocké sur le client
– Conversation
– Session : Le composant est géré comme un objet en session
HTTP
– Process
– Application : Le composant associé au contexte
« Application » est disponible du début à la fin de l’application.
Ce contexte peut s’avérer utile pour le maintien d’informations
statiques utiles à plusieurs composants
Turning Client Vision into Results
Un modèle de programmation
contextuelle : La conversation
• La Conversation :
– Une conversation représente généralement une multitude de
requêtes qui proviennent du même client
– Permet de simplifier la gestion de la Session HTTP. Le
contexte de conversation permet de résoudre les problèmes
suivants :
• Le client ne termine pas la transaction
• Le navigateur du client n'accepte pas les cookies
• Le client ouvre un autre navigateur et lance une autre
action (achat par exemple)
• Le client clique sur le bouton Back de son navigateur
– Permet de contrôler la durée de vie d’un composant
14
Turning Client Vision into Results
Un modèle de programmation
contextuelle : La conversation
• Une conversation est attachée à UN onglet ou à UNE
fenêtre d’un navigateur Un utilisateur peut « gérer »
plusieurs conversations (donc plusieurs espaces de travail)
en même temps sans que celles-ci ne rentrent en
« collision »
• Il existe 2 types de conversations :
– La conversation implicite (ou conversation temporaire) :
• Créée par défaut pour chaque requête
• Elle démarre à la soumission de la requête et se termine au rendu
de la réponse
– La conversation explicite (ou conversation longue) :
• Créée de manière déclarative (utilisation des annotations @Begin
et @End) au niveau de l’application
• Permet d’étendre une conversion temporaire en une conversion
longue
• Non détruite une fois la page de réponse rendue
15
Turning Client Vision into Results
Un modèle de programmation
contextuelle : La conversation
Implicite
Explicite
Par défaut
Java
pages.xml
@Begin / @End
JSF
Page
16
f:param conversationPropagation
ou
@propagation in seam:link-Element
Turning Client Vision into Results
Un modèle de programmation
contextuelle : Process
• Le contexte « Process » :
– Permet l'intégration de la gestion des processus métiers
dans une application.
– Il est géré par un moteur BPM (Business Process
Management, ici, JBPM).
– Il est multi-utilisateur
– Il peut subir de nombreuses interactions
17
Turning Client Vision into Results
Un modèle de programmation
contextuelle
Application
Process
Session
Request
Request
Conversation
Request
Conversation
Session
Request
Request
Conversation
18
Request
Conversation
Turning Client Vision into Results
Bijection
@In et @Out
• Seam propose un mécanisme d'injection des
dépendances dynamique et bijective cela permet
une interaction entre composant
• Mécanisme à base d’annotation (pas de fichier XML)
• Un composant peut être injecté automatiquement
dans un autre composant (@In)
• Un composant peut également créer et projeter un
autre composant dans le contexte (@Out)
19
Turning Client Vision into Results
Bijection
@In et @Out
• Il est possible de forcer la création d’un composant
au moment de l’injection (@In(create=true))
• Il est possible de projeter un composant en
redéfinissant son scope
(@Out(scope=ScopeType.SESSION))
• Seam crée le composant si il n’existe pas et gère son
cycle de vie "Inversion of Control" (IoC)
20
Turning Client Vision into Results
Bijection
@In et @Out
@Stateful
@Name("hotelBooking")
public class HotelBookingAction implements
HotelBooking
{
@In
private User user;
@In @Out
private Hotel hotel;
…
}
21
Turning Client Vision into Results
Bijection
@Factory
•
@Factory (factory data provider): permet d’initialiser une variable d’un
composant Seam à la 1ère demande. En effet, @Factory vérifie que celle-ci est
bien initialisée lorsque la couche de présentation demande l’objet mais ne la
réinitialise pas si une donnée a été changée
•
L’annotation @Factory peut être utilisée de 2 manières :
–
Sur une méthode renvoyant void
–
Sur une méthode ne renvoyant pas void. Dans ce cas, il faut être attentif au
scope :
• Si le scope n’a pas été défini de manière explicite, la variable obtient le
scope du composant
• Si le scope du composant est défini à « Staless » et que le scope n’a pas été
défini de manière explicite, le scope par défaut est « Event »
•
22
Dans les 2 cas :
–
La variable sera initialisée si celle-ci ne contient pas de valeur
–
Elle sera exposée dans le contexte avec le nom défini en paramètre de
l’annotation @Factory
Turning Client Vision into Results
DataModel
•
@DataModel et @DataModelSelection sont directement liés à
l’utilisation du composant JSF « dataTable »
•
@DataModel : Projette un attribut du type List, Map, Set ou
Object[] et le convertit en une instance de DataModel (permet de
récupérer l’élément actif à partir de la méthode getRowData())
•
@DataModelSelection : Permet de conserver l’objet de la ligne
courante d’une « dataTable ». Il est également possible de passer
celui-ci directement dans une expression EL
Objet courant
<s:link value="View Hotel" action="#{hotelBooking.selectHotel(hot)}" />
23
Turning Client Vision into Results
DataModel
• Utilisation des annotations @DataModel,
@DataModelSelection et @Factory
@DataModel private List <Person> fans;
@DataModelSelection private Person selectedFan;
Variable exposée dans le contexte
@Factory("fans")
public void findFans () {
fans = em.createQuery("from Person").getResultList();
}
La variable « fans » sera initialisée
lors du 1er appel de la page
public void delete () {
em.remove(selectedFan);
}
24
Utilisation de l’objet courant
Turning Client Vision into Results
Intégration JSF/EJB3
• Jboss Seam implémente la JSR-299 (Web Beans) :
Principe qui consiste à standardiser l’unification de 2
modèles de composants (JSF et EJB3). Permet de
simplifier le modèle de programmation des
applications Web
• Disparition du Managed Bean et du fichier de
configuration « faces-config.xml »
• Composant métier invoqué directement depuis la
page JSF via L'Expression Language
25
Turning Client Vision into Results
Intégration JSF/EJB3
<h:commandButton value="Register" action="#{register.register}"/>
@Stateful
@Name("register")
public class RegisterAction implements Register{
@In private User user;
@PersistenceContext private EntityManager em;
public void register(){
em.persist(user);
}}
26
Turning Client Vision into Results
Intégration JSF/EJB3
EJB3 Session
Bean
Page JSF
Managed
Bean
Page JSF
EJB3 Entity
Bean
JSF et EJB3 : Approche « classique »
27
EJB3 Session
Bean
EJB3 Entity
Bean
JSF et EJB3 avec Jboss Seam
Turning Client Vision into Results
Intégration JSF/EJB3
JSF
Page
JSF
Page
POJO
Facade
Session
EJB
POJO
Facade
Entity
EJB
Managed Bean
JSF
Page
JSF
Page
28
Session
EJB
Entity
EJB
Turning Client Vision into Results
Validation des formulaires
• Seam utilise le Framework « Hibernate Validator »
pour effectuer la validation des contraintes à un seul
endroit : le modèle de données
• Evite la duplication des règles de validation sur les
différentes couches (présentation, persistance, base
de données, …)
• Une vingtaine de contraintes prédéfinies avec la
possibilité d’en créer d’autres (par implémentation de
la classe Validator)
29
Turning Client Vision into Results
Validation des formulaires
Annotation
30
Vérification à l'exécution
@Length(min=, max=)
vérifie si la longueur de la chaîne de
caractères est comprise dans l'intervalle
@NotNull
vérifie si la valeur n'est pas nulle
@Pattern(regex="regexp",
flag=)
vérifie si la propriété correspond à
l'expression rationnelle donnée
@Email
vérifie si la chaîne de caractères est
conforme à la spécification d'une adresse email
@Past
vérifie si la date est dans le passé
@Future
vérifie si la date est dans le futur
@CreditCardNumber
Vérifie si la chaine de caractère correspond
à un numéro de carte bancaire
Turning Client Vision into Results
Validation des formulaires
@Entity
@Name("hotel")
public class Hotel {
<f:form>
<s:validateAll>
private String name;
@Length(max=50) @NotNull
public String getName() {
return name;
}
}
<h:inputText
value="#{hotel.name}"
/>
</s:validateAll>
</f:form>
Permet de valider les champs
du formulaire en utilisant
Hibernate Validator
31
Turning Client Vision into Results
Validation des formulaires
Les messages d’erreurs
• 2 façons de gérer les messages d’erreurs :
– En utilisant les standards JSF (la balise <h:message>. Cette balise ne
rend qu’UN message. Possibilité d’afficher l’ensemble des messages
en utilisant <h:messages>)
– En utilisant l’approche Seam et sa balise <s:decorate> (plus complexe
mais permet une meilleur gestion de l’affichage)
• Il est possible de gérer un message d’erreur pour chaque
champ. Pour cela, il est nécessaire de préciser l’identifiant
du champ dans la balise « for »
<h:inputText id="name" value="#{person.name}"/>
<h:message for="name" />
32
Turning Client Vision into Results
Validation des formulaires
Les messages d’erreurs
• Dans le cas de l’utilisation des annotations du
Framework Hibernate Validator :
– En cas de violations de contrainte, l'exception
« InvalidStateException » est levée création d’un tableau
« d’InvalidValues » décrivant chaque échec
– (Hypothèse) Le tableau retourné ne contient que les erreurs du
champ concerné (via la méthode getInvalidValues()), les
messages sont ajoutés au contexte (via la méthode
addMessage()) et ceux-ci sont affichés au niveau de la couche
présentation par la balise <h:message>
33
Turning Client Vision into Results
Navigation
Modèles de navigation
• Il existe 2 modèles de navigation :
– Le modèle de navigation sans état (stateless navigation
model)
• Règles standards de navigation de JSF
• Règles de navigation de Seam
– Le modèle de navigation avec état (stateful navigation model) :
• jPDL
34
Turning Client Vision into Results
Navigation
stateless navigation model
• Renvoi d’une chaine de caractères (correspondant au
nom de la page) avec possibilité de passage de
paramètres
public String search() {
return "/results.jsp?pattern=#{searchAction.searchPattern}";}
• Utilisation des règles standards de navigation de JSF
(fichier de configuration « faces-config.xml »). Cette
méthode présente quelques limitations :
– Impossible de définir des paramètres lors d’une redirection
– Impossible de démarrer ou de finir une conversation
– Impossible d’évaluer une EL expression (seulement la valeur
de retour d’une méthode)
35
Turning Client Vision into Results
Navigation
stateless navigation model
• Utilisation des règles de navigation de Seam (définies dans
le fichier « pages.xml »). Ce mécanisme permet :
– D’utiliser des EL expression
– De commencer ou terminer une conversation
– De passer des paramètres
Document source
<page view-id="/editDocument.xhtml">
<navigation from-action="#{documentEditor.update}">
Eventuelle condition
<rule if="…">
Fin de la conversation
<end-conversation/>
<redirect view-id="/viewDocument.xhtml">
Document destination
<param name="id" value="#{documentEditor.documentId}"/>
</redirect>
</rule>
Passage de paramètres
</navigation>
</page>
36
Turning Client Vision into Results
Navigation
stateful navigation model
• Utilisation du langage de définition jPDL qui permet de
décrire les différentes étapes par lesquelles doit passer un
utilisateur pour réaliser une tâche
• Le pageflow est composé d’états et de transitions
• Il existe 2 sortes d’état :
– Les décisions : permettent d'aiguiller la navigation en fonction de
l'état du système. Chaque décision est associée à l'évaluation d'une
expression (booléenne ou non)
– Les pages : permettent d'aiguiller la navigation en fonction des
actions de l'utilisateur
• Les transitions permettent de passer d'un état à l'autre
37
Turning Client Vision into Results
Navigation
stateful navigation model
<pageflow-definition> Méthode retournant un booléen
<decision name="has book?" expression="#{}">
<transition name="true" to="rejected" />
<transition name=« false" to=« enter ISBN" />
</decision>
<page name="rejected" view-id=".xhtml">
<end-conversation />
</page>
Termine une conversation
…
<page name="confirm checkout" view-id=".xhtml">
<transition name="confirm" to="confirmed">
<action expression="#{beanManager.method()}"/>
</transition>
<transition name="cancel" to="enter ISBN"/>
</page>
Méthode associée
…
à une transition
</pageflow-definition>0
<input type="submit" jsfc="h:commandButton" value="Confirm" action="confirm" />
<input type="submit" jsfc="h:commandButton" value="Cancel" action="cancel" />
38
Turning Client Vision into Results
Le cycle de vie
39
Turning Client Vision into Results
Seam Hotel
Booking
40
Turning Client Vision into Results
Présentation de l’application
• Seam Hotel Booking est une application web de
démonstration qui utilise les principaux concepts
du Framework Jboss Seam (contexte
conversationnel, intégration JSF/EJB3, …)
• Elle permet :
– De s’identifier
– D’enregistrer un nouvel utilisateur
– De rechercher un hôtel et d’en visualiser les détails
– De réserver un hôtel (en précisant la date d’arrivée et de départ)
– D’annuler une réservation
– De visualiser les derniers hôtels sélectionnés (contexte de
conversation)
41
Turning Client Vision into Results
Authentification
•
Basé sur JAAS (Java Authentication and Authorization Service) :
Framework de sécurité robuste et hautement configurable pour la
gestion d’authentification utilisateur. Assuré par la classe
org.jboss.seam.security.Identity
•
Le champ login est « bindé » avec « identity.username »,
password avec « identity.password » (2 attributs de la classe
Identity) tandis que le bouton appelle la méthode « identity.login »
(vérifie si l’utilisateur est déjà connecté)
Attribut username
Attribut password
Méthode login()
42
Turning Client Vision into Results
Authentification
• L’application Seam Hotel Booking utilise sa propre
méthode d’authentification. Elle permet simplement de
vérifier que le couple login/password est bien présent dans
la base de données
• Cette méthode d’authentification doit être déclarée dans le
fichier de configuration « components.xml » sous la forme
suivante :
<security:identity authenticatemethod="#{authenticator.authenticate}"/>
• La méthode authenticate() renvoie un booléen :
– True si le couple login/password (requête SQL)
– False sinon
43
Turning Client Vision into Results
Recherche
• La recherche d’un hôtel est paramétrée par un motif
(attributs de l’entity bean « Hotel » : nom, adresse,
ville ou code postal de l’hôtel) et par le nombre de
réponses retournées (5, 10, ou 20)
Attribut searchString
Méthode find()
Attribut pageSize
• Utilisation de la balise <a:support> pour le support
AJAX Permet de rafraîchir une zone (le résultat de
la recherche) de la page à chaque événement
JavaScript « onkeyup » (relâchement de la touche)
44
Turning Client Vision into Results
Recherche
• Utilisation de la balise @DataModel afin d’exposer, au
contexte, une liste d’hôtels (résultat d’une requête
SQL)
@PersistenceContext private EntityManager em;
@DataModel private List<Hotel> hotels;
public void find(){
hotels = em.createQuery("select h from Hotel h where …
").getResultList();
}
45
Turning Client Vision into Results
Recherche
• Utilisation du composant JSF « dataTable » pour
afficher la variable « hotels » (liste des hôtels trouvés
suite à la recherche)
Panel rafraîchi lors
de l’action « onkeyup »
Liste à afficher
Valeur de l’objet
courant
<a:outputPanel id="searchResults">
<h:dataTable id="hotels" value="#{hotels}" var="hot"
rendered="#{hotels.rowCount>0}">
<h:column><f:facet name="header">Name</f:facet>
#{hot.name}
Condition de rendu
</h:column>
</h:dataTable>
</a:outputPanel>
46
Valeur de
la colonne
Entête de colonne
Turning Client Vision into Results
Conversation
• Dans le cadre d’une réservation d’hôtel, l’achat DOIT
se dérouler en 5 phases :
– Phase 1 : l'utilisateur doit effectuer une recherche afin de
sélectionner un hôtel. La conversation commence seulement
au moment où l’utilisateur clique sur l’action « View Hotel »,
action rattachée à une méthode annotée par @Begin
Résultat d’une recherche
47
Turning Client Vision into Results
Conversation
Phase 1
<s:link value="View Hotel" action="#{hotelBooking.selectHotel(hot)}" />
Déclaration du
composant
« hotelBooking »
@Stateful
@Name("hotelBooking")
public class HotelBookingAction
implements HotelBooking{
Permet d’injecter un
EntityManager
@PersistenceContext(type=EXTENDED)
private EntityManager em;
Gestion du
mécanisme
de bijection
@In(required=false) @Out
private Hotel hotel;
@Begin
public void selectHotel(Hotel selectedHotel){
hotel = em.merge(selectedHotel);
}}
48
Permet de débuter
une conversation
longue
Turning Client Vision into Results
Conversation
Phase 2
– Phase 2 : L’utilisateur accède au détail de l’hôtel qu’ il vient de
sélectionner. Cette page lui permet de continuer sa réservation
ou de revenir à sa recherche initiale
– Phase 3 : Demande d’informations pour la prise en compte de
la réservation (date de début et de fin, nombre de lits, …)
– Phase 4 : Récapitulatif de la réservation
49
Turning Client Vision into Results
Conversation
Phase 5
– Phase 5 : Confirmation de la réservation. Cette action fait
appel à une méthode annotée par @End : Le contexte passe
du statut de conversation longue à conversation temporaire.
De plus, il y a enregistrement de la réservation dans la base de
données
50
Turning Client Vision into Results
Conversation
Phase 5
<h:commandButton value="Confirm" action="#{hotelBooking.confirm}" />
@Stateful
@Name("hotelBooking")
public class HotelBookingAction
implements HotelBooking{
@PersistenceContext(type=EXTENDED)
private EntityManager em;
Gestion du mécanisme
de bijection
@In(required=false)
private Booking booking;
@End
public void confirm(){
em.persist(booking);
}
}
51
Permet de terminer
une conversation
longue
Turning Client Vision into Results
Conversation
Workspace
• Le workspace permet à un utilisateur de basculer entre
plusieurs conversations. Il n’y a pas de code Java,
seulement du code JSF
• Utilisation de la variable « conversationList » (liste de
« ConversationEntry »)
Attribut « startDatetime »
Attribut « description »
Méthode select()
52
Attribut « lastDatetime »
Turning Client Vision into Results
Sécurité
• @Restrict : Cette annotation permet d’appliquer une
règle de sécurité à un composant Seam.
@Restrict("#{identity.loggedIn}")
Le composant n’est accessible
qu’aux utilisateurs loggués
• Utilisation de la balise <exception class> définie dans
le fichier de configuration « pages.xml » : Permet une
redirection en fonction d’une exception
53
Turning Client Vision into Results
Navigation
• La navigation du site est assurée par le fichier de
configuration « pages.xml »
<page view-id="/main.xhtml" login-required="true">
<navigation from-action="#{hotelBooking.selectHotel(hot)}">
<redirect view-id="/hotel.xhtml"/>
</navigation>
</page>
54
Turning Client Vision into Results