Jboss Seam & Seam Hotel Booking. Turning Client Vision into Results 2 Sommaire Jboss Seam...
-
Upload
jolie-quere -
Category
Documents
-
view
113 -
download
3
Transcript of Jboss Seam & Seam Hotel Booking. Turning Client Vision into Results 2 Sommaire Jboss Seam...
Jboss Seam &
Seam Hotel Booking
Turning Client Vision into Results2
Sommaire
• Jboss Seam– 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
• Seam Hotel Booking– Présentation de l’application
– Authentification
– Recherche
– Conversation
– Sécurité
– Navigation
Turning Client Vision into Results3
Jboss Seam
Turning Client Vision into Results4
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
Turning Client Vision into Results5
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
Turning Client Vision into Results6
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
– …
Turning Client Vision into Results7
Présentation générale
Turning Client Vision into Results8
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)
Turning Client Vision into Results9
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-bean-name> 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
Turning Client Vision into Results10
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
Turning Client Vision into Results11
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
Turning Client Vision into Results12
Les composants Seam
@Scope(ScopeType.SESSION)@Name("MyDatabaseUtils")Public class MyDatabaseUtils{
@Createpublic void initDatabase(){}
@Destroypublic void closeDbResources(){}
}
Turning Client Vision into Results13
Un modèle de programmation contextuelle
• Seam introduit de nouveaux contextes :– 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
Ord
re d
e p
rio
rité
de
rech
erch
e
Turning Client Vision into Results14
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
Turning Client Vision into Results15
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
Turning Client Vision into Results16
Un modèle de programmation contextuelle : La conversation
Implicite Explicite
Par défaut
JSFPage
pages.xmlJava
@Begin / @End
f:param conversationPropagationou@propagation in seam:link-Element
Turning Client Vision into Results17
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
Turning Client Vision into Results18
Un modèle de programmation contextuelle
Session
Session
Request Request Request
Request Request Request
Application
Conversation Conversation
ConversationConversation
Process
Turning Client Vision into Results19
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)
Turning Client Vision into Results20
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)
Turning Client Vision into Results21
Bijection@In et @Out
@Stateful@Name("hotelBooking")public class HotelBookingAction implements HotelBooking{ @In private User user; @In @Out private Hotel hotel;…}
Turning Client Vision into Results22
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 »
• 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 Results23
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
<s:link value="View Hotel" action="#{hotelBooking.selectHotel(hot)}" />
Objet courant
Turning Client Vision into Results24
DataModel
• Utilisation des annotations @DataModel, @DataModelSelection et @Factory
@DataModel private List <Person> fans;
@DataModelSelection private Person selectedFan;
@Factory("fans")public void findFans () { fans = em.createQuery("from Person").getResultList();}
public void delete () { em.remove(selectedFan);}
Variable exposée dans le contexte
La variable « fans » sera initialisée lors du 1er appel de la page
Utilisation de l’objet courant
Turning Client Vision into Results25
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
Turning Client Vision into Results26
Intégration JSF/EJB3
@Stateful@Name("register")public class RegisterAction implements Register{
@In private User user;@PersistenceContext private EntityManager em;
public void register(){em.persist(user);
}}
<h:commandButton value="Register" action="#{register.register}"/>
Turning Client Vision into Results27
Intégration JSF/EJB3
Page JSF Managed Bean
EJB3 Session Bean
EJB3 EntityBean
JSF et EJB3 : Approche « classique »
Page JSF
EJB3 Session Bean
EJB3 EntityBean
JSF et EJB3 avec Jboss Seam
Turning Client Vision into Results28
Intégration JSF/EJB3
JSF Page
JSF Page
JSF Page
JSF Page
POJO Facad
e
POJO Facad
e
Session EJB
Entity EJB
Session EJB
Entity EJB
Managed Bean
Turning Client Vision into Results29
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)
Turning Client Vision into Results30
Validation des formulaires
Annotation 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 e-mail
@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 Results31
Validation des formulaires
@Entity@Name("hotel")public class Hotel {
private String name;
@Length(max=50) @NotNullpublic String getName() { return name; }}
<f:form>
<s:validateAll>
<h:inputText value="#{hotel.name}" />
</s:validateAll>
</f:form>
Permet de valider les champs du formulaire en utilisant
Hibernate Validator
Turning Client Vision into Results32
Validation des formulairesLes 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" />
Turning Client Vision into Results33
Validation des formulairesLes 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>
Turning Client Vision into Results34
NavigationModè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
Turning Client Vision into Results35
Navigation stateless navigation model
• Renvoi d’une chaine de caractères (correspondant au nom de la page) avec possibilité de passage de paramètres
• 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)
public String search() { return "/results.jsp?pattern=#{searchAction.searchPattern}";}
Turning Client Vision into Results36
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
<page view-id="/editDocument.xhtml"> <navigation from-action="#{documentEditor.update}"> <rule if="…"> <end-conversation/> <redirect view-id="/viewDocument.xhtml"> <param name="id" value="#{documentEditor.documentId}"/> </redirect> </rule> </navigation></page>
Document source
Document destination
Fin de la conversation
Eventuelle condition
Passage de paramètres
Turning Client Vision into Results37
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
Turning Client Vision into Results38
Navigation stateful navigation model
<input type="submit" jsfc="h:commandButton" value="Confirm" action="confirm" /><input type="submit" jsfc="h:commandButton" value="Cancel" action="cancel" />
<pageflow-definition>
<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>…<page name="confirm checkout" view-id=".xhtml"> <transition name="confirm" to="confirmed"> <action expression="#{beanManager.method()}"/> </transition><transition name="cancel" to="enter ISBN"/></page>…</pageflow-definition>0
Méthode retournant un booléen
Termine une conversation
Méthode associée à une transition
Turning Client Vision into Results39
Le cycle de vie
Turning Client Vision into Results40
Seam Hotel Booking
Turning Client Vision into Results41
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)
Turning Client Vision into Results42
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()
Turning Client Vision into Results43
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 :
• La méthode authenticate() renvoie un booléen :– True si le couple login/password (requête SQL)– False sinon
<security:identity authenticate-method="#{authenticator.authenticate}"/>
Turning Client Vision into Results44
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)
• 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)
Attribut searchString
Attribut pageSize
Méthode find()
Turning Client Vision into Results45
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();
}
Turning Client Vision into Results46
Recherche
• Utilisation du composant JSF « dataTable » pour afficher la variable « hotels » (liste des hôtels trouvés suite à la recherche)
<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}
</h:column></h:dataTable>
</a:outputPanel>
Panel rafraîchi lors de l’action « onkeyup »
Valeur de l’objet courant
Condition de rendu
Liste à afficher
Entête de colonneValeur de la colonne
Turning Client Vision into Results47
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
Turning Client Vision into Results48
ConversationPhase 1
@Stateful@Name("hotelBooking")
public class HotelBookingAction implements HotelBooking{
@PersistenceContext(type=EXTENDED)private EntityManager em;
@In(required=false) @Outprivate Hotel hotel;
@Beginpublic void selectHotel(Hotel selectedHotel){ hotel = em.merge(selectedHotel); }}
Permet de débuter une conversation
longue
Permet d’injecter unEntityManager
Déclaration du composant
« hotelBooking »
<s:link value="View Hotel" action="#{hotelBooking.selectHotel(hot)}" />
Gestion du mécanismede bijection
Turning Client Vision into Results49
ConversationPhase 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
Turning Client Vision into Results50
ConversationPhase 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
Turning Client Vision into Results51
ConversationPhase 5
@Stateful@Name("hotelBooking")
public class HotelBookingAction implements HotelBooking{
@PersistenceContext(type=EXTENDED)private EntityManager em;
@In(required=false)
private Booking booking;
@Endpublic void confirm(){ em.persist(booking); }}
Permet de terminer une conversation
longue
Gestion du mécanismede bijection
<h:commandButton value="Confirm" action="#{hotelBooking.confirm}" />
Turning Client Vision into Results52
ConversationWorkspace
• 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 « lastDatetime »
Attribut « description »
Méthode select()
Turning Client Vision into Results53
Sécurité
• @Restrict : Cette annotation permet d’appliquer une règle de sécurité à un composant Seam.
• Utilisation de la balise <exception class> définie dans le fichier de configuration « pages.xml » : Permet une redirection en fonction d’une exception
@Restrict("#{identity.loggedIn}")
Le composant n’est accessible qu’aux utilisateurs loggués
Turning Client Vision into Results54
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>