Vous êtes sur la page 1sur 28

Mise en place dune

application application JSF, Spring et Hibernate

Last update: 06/ 08/2010 Version: 1.1 Status:


In progress Being checked Validated

WRITTEN BY Name : Yosr Chari Department : TS/SE Date : 06/08/2010 Stamp :

1- Introduction gnrale
Le but de ce tutorial est de sinitier au dveloppement dapplications MVC bases sur JSF, Spring et Hibernate.

2- Base de donnes
Notre base de donnes consiste en deux tables : contacts et contrats. Les commandes SQL pour la cration de la base et des tables sont les suivantes :
--- Structure de la table `contacts` -CREATE TABLE IF NOT EXISTS `contacts` ( `CIN` varchar(20) NOT NULL, `firstName` varchar(15) NOT NULL, `lastName` varchar(15) NOT NULL, `email` varchar(20) NOT NULL, PRIMARY KEY (`CIN`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; --- Contenu de la table `contacts` -INSERT INTO `contacts` (`CIN`, `firstName`, `lastName`, `email`) VALUES ('08765645', 'Ali', 'Ben Salah', 'alis@gmail.com'), ('05456783', 'Mohamed', 'Ben Abdallah', 'med_benA@gmail.com'); -- ---------------------------------------------------------- Structure de la table `contrats` -CREATE TABLE IF NOT EXISTS `contrats` ( `id` int(11) NOT NULL AUTO_INCREMENT, `ref` varchar(11) NOT NULL, `idclient` varchar(20) NOT NULL, `datec` date NOT NULL, `duree` int(11) NOT NULL, PRIMARY KEY (`id`), FOREIGN KEY (idclient) references contacts(CIN) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ; --- Contenu de la table `contrats` -INSERT INTO `contrats` (`id`, `ref`, `idclient`, `datec`, `duree`) VALUES (1, '33', '08765645', '2010-05-18', 7), (2, '2', '08765645', '2010-05-18', 9);

3- Cration dun nouveau projet


La premire chose faire est de crer un projet web dynamique. Pour cela, accder au menu File -> New -> Other et choisir Dynamic Web Project sous loption Web .

Figure 1 : Cration d'un projet web dynamique

Nommer le projet GestionContrats et configurer par la suite le serveur dapplication. Pour cela, cliquer sur le bouton New . Choisir de la liste des serveurs celui que nous allons utiliser (Apache Tomcat v6.0 dans notre cas) et cliquez sur le bouton Next . Une fentre apparat, (il est ncessaire davoir install le serveur) :

Figure 2: Configuration du serveur

Cliquer sur Finish , le reste des lments de la fentre de cration du projet sont remplies. Cliquer sur Finish . Une fois le projet cr, il faudra ajouter les jars ncessaires sous le dossier lib :

Figure 3: Librairies du projet

4- Installation dHibernate tools


Hibernate tools est un plugin qui permet de gnrer automatiquement les classes du mapping partir de la base de donnes. Pour linstaller, il suffit daccder loption Software Updates du menu Help ; onglet Available Software et ajouter le site http://download.jboss.org/jbosstools/updates/stable/ en cliquant sur le bouton Add Site . Redmarrer Eclipse. Il faut maintenant configurer la connexion la base de donnes. Crer un nouveau rpertoire de type source folder nomm config. Cliquer dessus avec le bouton droit et choisir New -> Other .

Figure 4: Cration du fichier de configuration Hibernate

Cliquer sur Next et remplir la fentre avec les informations locales :

Figure 5: Configuration pour la cration du fichier de config.

Par la mme occasion, configurer la console Hibernate tools pour disposer dun outil de gnration de mapping. Pour configurer les paramtres de connexion la base, cliquez sur New :

Figure 6: Configuration des paramtres de la base de donnes

Il ne faut pas oublier de slectionner le jar correspondant notre driver. Cliquer sur Finish . Le fichier de configuration hibernate.cfg.xml a t cr comme suit :
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/commerciale</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> </session-factory> </hibernate-configuration>

Ouvrir la vue Hibernate Configuration et vrifier la conformit de laffichage la base. On est prt lancer la gnration de code. Pour cela, il suffit de choisir loption Hibernate Code Generation Configurations dans licne de Hibernate Tools .

Figure 7: Lancement de la gnration de code

Il faudra par la suite prciser les dtails de la gnration dans la fentre affiche :

Figure 8: Prcision des dtails de la gnration

Et dans longlet Exporters :

Figure 9: Onglet Exporters

Cliquer sur Run ; nous pouvons voir les classes (entits) gnres dans le package explorer . Comme vous pouvez le remarquer, les entits sont gnres avec lensemble des annotations ncessaires au mapping Hibernate . Par contre, nous remarquons que les annotations relatives la cl trangre ne sont pas gnres. On modifie donc la classe Contrats.java comme suit :
package com.oxia.formation; import static javax.persistence.GenerationType.IDENTITY; import java.util.Date; import import import import import import import import import import javax.persistence.Column; javax.persistence.Entity; javax.persistence.FetchType; javax.persistence.GeneratedValue; javax.persistence.Id; javax.persistence.JoinColumn; javax.persistence.ManyToOne; javax.persistence.Table; javax.persistence.Temporal; javax.persistence.TemporalType;

@Entity @Table(name = "contrats", catalog = "commerciale") public class Contrats implements java.io.Serializable { private private private private private Integer id; String ref; Contacts client; Date datec; int duree;

public Contrats() { } public Contrats(String ref, Contacts client, Date datec, int duree) { this.ref = ref; this.client = client; this.datec = datec; this.duree = duree; } @Id @GeneratedValue(strategy = IDENTITY) @Column(name = "id", unique = true, nullable = false) public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } @Column(name = "ref", nullable = false, length = 11) public String getRef() { return this.ref; } public void setRef(String ref) { this.ref = ref; } @ManyToOne(optional = false, fetch = FetchType.EAGER) @JoinColumn(name = "idClient", referencedColumnName = "CIN", nullable = false) public Contacts getClient() { return this.client; } public void setClient(Contacts client) { this.client = client; } @Temporal(TemporalType.DATE) @Column(name = "datec", nullable = false, length = 10) public Date getDatec() { return this.datec; } public void setDatec(Date datec) { this.datec = datec; } @Column(name = "duree", nullable = false) public int getDuree() { return this.duree; } public void setDuree(int duree) { this.duree = duree; } }

5- Couche daccs aux donnes (DAO)


Pour chaque entit, crer linterface dans le package DAO (ContactsDao et ContratsDao).

Crer ensuite les implmentations des interfaces dans le package ipml (ContactsDaoImpl et ContratsDaoImpl). Normalement, pour bnficier des fonctionnalits et des API Spring, chaque implmentation devrait tendre la classe HibernateDAOSupport . Mais pour des raisons de bonnes pratiques, nous allons faire autrement. En effet, les oprations de base pour la persistance des donnes sont toutes identiques et ne diffrent que par le type dobjet manipuler (cration, consultation, mise jour et suppression). Ces mthodes vont alors tre rptes et redfinies dans chaque DAO. Cependant, avec les types gnriques, cette redondance pourra tre vite en crant une interface gnrique UtilDao dfinissant ces mthodes.

5.1- DAOs gnriques


package com.oxia.formation.dao; import java.io.Serializable; import java.util.List; public interface UtilDao<T, ID extends Serializable> { void create(T entity); T findById(ID id); T findById(ID id, Class<? extends T> clazz); List<T> findAll(); void update(T entity); void delete(T entity); }

Crer par la suite limplmentation de cette interface UtilDaoImpl de laquelle vont hriter toutes les DAOs de nos entits :
package com.oxia.formation.dao.impl; import java.io.Serializable; import java.util.List; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import com.oxia.formation.dao.UtilDao; public class UtilDaoImpl<T, ID extends Serializable> extends HibernateDaoSupport implements UtilDao<T, ID> { final transient protected Log log = LogFactory.getLog(this.getClass()); private Class<T> clazz; public UtilDaoImpl(Class<T> clazz) { this.clazz = clazz; } public void create(T entity) { getHibernateTemplate().save(entity); if(log.isDebugEnabled()){

log.debug("Entity created"); } } public void delete(T entity) { getHibernateTemplate().delete(entity); if(log.isDebugEnabled()){ log.debug("Entity deleted"); } } @SuppressWarnings("unchecked") public List<T> findAll() { return getHibernateTemplate().loadAll(clazz); } @SuppressWarnings("unchecked") public T findById(Class<T> clazz, ID id) { return (T) getHibernateTemplate().get(clazz, id); } @SuppressWarnings("unchecked") public T findById(ID id) { return (T) getHibernateTemplate().load(clazz, id); } public void update(T entity) { getHibernateTemplate().update(entity); if(log.isDebugEnabled()){ log.debug("Entity updated"); } } }

3.2- DAOs spcifiques


Interface spcifique pour lentit Contrats
package com.oxia.formation.dao; import com.oxia.formation.Contrats; public interface ContratsDao extends UtilDao<Contrats, Integer> { }

Implmentation
package com.oxia.formation.dao.impl; import com.oxia.formation.Contrats; import com.oxia.formation.dao.ContratsDao; public class ContratsDaoImpl extends UtilDaoImpl<Contrats, Integer> implements ContratsDao { public ContratsDaoImpl() { super(Contrats.class); } public List<Contrats> findContratsByContact(String idclient) { return getHibernateTemplate().findByNamedParam( "FROM Contrats c WHERE c.client.CIN = :idclient", "idclient",idclient); } }

Interface spcifique pour lentit Contacts


package com.oxia.formation.dao; import java.util.List; import com.oxia.formation.Contacts; public interface ContactsDao extends UtilDao<Contacts, String> { List<Contacts> getContacts(); }

Implmentation
package com.oxia.formation.dao.impl; import java.util.List; import com.oxia.formation.Contacts; import com.oxia.formation.dao.ContactsDao; public class ContactsDaoImpl extends UtilDaoImpl<Contacts, String> implements ContactsDao { public ContactsDaoImpl() { super(Contacts.class); } @SuppressWarnings("unchecked") public List<Contacts> getContacts() { return getHibernateTemplate().loadAll(Contacts.class); } }

De cette manire, le DAO pourra appeler les mthodes du DAO gnrique ainsi que celles qui lui sont propres.

6- Fichiers de configuration Spring


Nous passons maintenant la cration des fichiers de configuration de Spring : Nous allons commencer par un fichier ApplicationContext-ressources.xml qui contient les paramtres de la connexion la base de donnes :
<?xml version="1.0" encoding="UTF-8"?> <!-- DATASOURCE DEFINITON--> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" destroy-method="close" lazy-init="true"> <property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/commerciale" />

<property name="username" value="root" /> <property name="password" value="" /> </bean> </beans>

Ainsi, le fichier hibernate.cfg.xml peut tre limin puisque toutes les informations quil contient sont prsentes dans ce fichier.

Ensuite, nous crons le fichier ApplicationContext.xml sous le dossier WEB-INF . Ce fichier contient tous les beans grs par Spring. On va commencer par les paramtres de gnrateur de session session factory . Cette configuration consiste spcifier les paramtres dHibernate, les classes annotes ainsi que la classe responsable de la gestion de la session.
<?xml version="1.0" encoding="UTF-8"?> <!-- DATASOURCE DEFINITON--> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<!-- HIBERNATE CONFIGURATION --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactory Bean"> <property name="dataSource" ref="dataSource" /> <property name="annotatedClasses"> <list> <value>com.oxia.formation.Contacts</value> <value>com.oxia.formation.Contrats</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.use_outer_join">true</prop> <prop key="hibernate.max_fetch_depth">1</prop> <prop key="hibernate.jdbc.batch_size">0</prop> <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop> <prop key="hibernate.cache.use_query_cache">true</prop> </props> </property> </bean> </beans>

Le fichier suivant est ApplicationContext-Dao.xml ; il permet de spcifier les Daos de lapplication.


<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <!-- Application context DAO layer --> <!-- General --> <bean id="abstractHibernateDAO" class="org.springframework.orm.hibernate3.support.HibernateDaoSupport" abstract="true"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <bean id="contactsDao" class="com.oxia.formation.dao.impl.ContactsDaoImpl" parent="abstractHibernateDAO"> </bean> <bean id="contratsDao" class="com.oxia.formation.dao.impl.ContratsDaoImpl" parent="abstractHibernateDAO"> </bean> </beans>

Nous crons par la suite un autre fichier xml ( ApplicationContext-transaction.xml ) pour la gestion des transactions.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <!--Transaction management --> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager" /> <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED" /> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!-- the transactional semantics... --> <tx:attributes> <!-- all methods starting with 'get' are read-only --> <tx:method name="get*" read-only="true" /> <tx:method name="find*" read-only="true" /> <!-- other methods use the default transaction settings (see below) --> <tx:method name="*" propagation="REQUIRED" /> </tx:attributes> </tx:advice> <!-Ensure that the above transactional advice runs for any execution of an operation defined by the userManagementService interface --> <aop:config> <aop:pointcut id="managementServiceOperation" expression="execution(* com.oxia.formation.*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcutref="managementServiceOperation" /> </aop:config> </beans>

Une fois ces fichiers crs, il faut dire notre application de lancer le framework Spring en utilisant cette configuration. Pour cela, il faudrait les ajouter dans le fichier web.xml .
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/ApplicationContext*.xml </param-value> </context-param>

7- Couche prsentation
Nous allons maintenant passer la couche prsentation. Le but est davoir un menu Contact qui nous permet de consulter la liste de contacts et dditer un contact donn. Nous commenons par la page template.xhtml qui dfinit la structure des pages de lapplication.
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:rich="http://richfaces.org/rich" xmlns:a4j="http://richfaces.org/a4j" xmlns:c="http://java.sun.com/jstl/core" xmlns:fn="http://java.sun.com/jsp/jstl/functions"> <head> <title>Insert title here</title> <link rel="stylesheet" type="text/css" href="./css/main.css"/> </head> <body> <div id="header"> <ui:insert name="header"> <ui:include src="/facelets/Header.xhtml"/> </ui:insert> </div> <div id="center"> <ui:insert name="center"> <br /> <span class="titleText"></span> <hr /> </ui:insert> </div> <div id="left"> </div> </body> </html>

Cette page fait appel la page header.xhtml qui dfinit lentte des pages de lapplication, qui consiste au menu dans notre application.
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich"> <h:form> <rich:toolBar> <rich:dropDownMenu> <f:facet name="label"> <h:panelGrid cellpadding="0" cellspacing="0" columns="2" style="vertical-align:middle"> <h:outputText value="Contacts" /> </h:panelGrid> </f:facet> <rich:menuItem submitMode="none"> <h:outputLink value="RechercheContact.jsf">

<h:outputText value="Recherche Contact"></h:outputText> </h:outputLink> </rich:menuItem> <rich:menuItem submitMode="none"> <h:outputLink value="ListContact.jsf"> <h:outputText value="Liste Contacts"></h:outputText> </h:outputLink> </rich:menuItem> <rich:menuItem submitMode="none"> <h:commandLink id="link" action="#{contactCtr.create}"> <h:outputText value="Nouveau Contact"></h:outputText> </h:commandLink> </rich:menuItem> </rich:dropDownMenu> </rich:toolBar> </h:form> </ui:composition>

Nous allons maintenant mettre en place les pages RechercheContact.xhtml , ListContact.xhtml et onecontact.xhtml. ListContact.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <ui:composition template="template.xhtml"> <ui:define name="center"> <ui:include src="contacts.xhtml" /> </ui:define> </ui:composition> </html>

contacts.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:rich="http://richfaces.org/rich" xmlns:a4j="http://richfaces.org/a4j"> <head> <title>RichFaces</title> </head> <body> <f:view> <h:form> <rich:dataTable value="#{contactCtr.features}" var="contact"> <f:facet name="header"> <rich:columnGroup> <h:column>

<h:outputText value="" /> </h:column> <h:column> <h:outputText value="" /> </h:column> <h:column> <h:outputText value="CIN" /> </h:column> <h:column> <h:outputText value="FirstName" /> </h:column> <h:column> <h:outputText value="LastName" /> </h:column> <h:column> <h:outputText value="Email" /> </h:column> </rich:columnGroup> </f:facet> <h:column> <h:commandLink id="editContact" value="Edit" action="#{contactCtr.editContact}"> </h:commandLink> </h:column> <h:column> <h:commandLink id="deleteContact" value="Delete" action="#{contactCtr.deleteContact}" /> </h:column> <h:column> <h:outputText value="#{contact.CIN}" /> </h:column> <h:column> <h:outputText value="#{contact.firstName}" /> </h:column> <h:column> <h:outputText value="#{contact.lastName}" /> </h:column> <h:column> <h:outputText value="#{contact.email}" /> </h:column> </rich:dataTable> </h:form> </f:view> </body> </html>

onecontact.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:rich="http://richfaces.org/rich" xmlns:a4j="http://richfaces.org/a4j"> <ui:composition template="template.xhtml"> <ui:define name="center"> <h:form> <a4j:outputPanel ajaxRendered="true"> <h:messages /> </a4j:outputPanel> <table> <tr>

<td><h:outputLabel for="CINInput" value="CIN:" /></td> <td><h:inputText id="CINInput" value="#{contactCtr.selectedContact.CIN}" required="true" disabled="#{contactCtr.creation == false}" /></td> </tr> <tr> <td><h:outputLabel for="firstNameInput" value="Prenom:" /></td> <td><h:inputText id="firstNameInput" value="#{contactCtr.selectedContact.firstName}" required="true" /> </td> </tr> <tr> <td><h:outputLabel for="lastNameInput" value="Nom:" /></td> <td><h:inputText id="lastNameInput" value="#{contactCtr.selectedContact.lastName}" required="true" /></td> </tr> <tr> <td><h:outputLabel for="emailInput" value="Email:" /></td> <td><h:inputText id="emailInput" value="#{contactCtr.selectedContact.email}" required="true" /></td> </tr> </table> <h:commandButton id="save" value="Enregistrer" rendered="#{contactCtr.creation == true}" action="#{contactCtr.saveContact}" /> <h:commandButton id="update" value="Enregistrer" rendered="#{contactCtr.creation == false}" action="#{contactCtr.updateContact}" /> </h:form> </ui:define> </ui:composition> </html>

Cette page permet la cration dun nouveau contact ou la mise jour dun contact existant (accs partir du lien edit de la page liste). Tous les champs sont obligatoires ; un message derreur est affich si tel nest pas le cas.

Figure 10: Erreur si les champs ne sont pas renseigns

Aussi, un message derreur est affich si lutilisateur essaye dintroduire un contact dj existant (CIN existante).

Figure 11: Tentative d'insertion d'un id existant

RechercheContact.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:rich="http://richfaces.org/rich" xmlns:a4j="http://richfaces.org/a4j"> <ui:composition template="template.xhtml"> <ui:define name="center"> <h:form> <table align="center"> <tr> <td><h:outputLabel for="CINInput" value="Entrez le Num. de la CIN:" /></td> <td><h:inputText id="CINInput" value="#{contactCtr.selectedContact.CIN}" /></td> </tr> <tr> <td><h:commandButton id="search" value="Rechercher" action="#{contactCtr.getContactById}" /></td> </tr> </table> </h:form> </ui:define> </ui:composition> </html>

Cette page nous mne la page qui affiche les dtails du contact recherch (CIN, nom et prnom, mail et les dtails de ses contrats). DetailContact.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:rich="http://richfaces.org/rich"

xmlns:a4j="http://richfaces.org/a4j"> <ui:composition template="template.xhtml"> <ui:define name="center"> <h:form> <a4j:outputPanel ajaxRendered="true"> <h:messages /> </a4j:outputPanel> <h:panelGrid id="userinfo"> <h:outputLabel value="CIN: #{contactCtr.selectedContact.CIN}" /> <h:outputLabel value="Prenom: #{contactCtr.selectedContact.firstName}" /> <h:outputLabel value="Nom: #{contactCtr.selectedContact.lastName}" /> <h:outputLabel value="Mail: #{contactCtr.selectedContact.email}" /> <br /> <br /> <h:outputLabel value="Liste des contrats" style="fontweight:bold" /> <br /> <h:dataTable value="#{contactCtr.listeContrats}" var="item"> <h:column> <f:facet name="header"> <h:outputText value="Ref." /> </f:facet> <h:inputText value="#{item.ref}" readOnly="true" /> </h:column> <h:column> <f:facet name="header"> <h:outputText value="Date Contrat" /> </f:facet> <h:inputText value="#{item.datec}" readOnly="true" /> </h:column> <h:column> <f:facet name="header"> <h:outputText value="Duree" /> </f:facet> <h:inputText value="#{item.duree}" readOnly="true" /> </h:column> </h:dataTable> </h:panelGrid> </h:form> </ui:define> </ui:composition> </html>

Figure 12: Dtail d'un contact donn

Nous passons maintenant au contrleur ContactCtr.java


package com.oxia.formation.ctr; import java.io.Serializable; import java.util.List; import import import import import javax.annotation.PostConstruct; javax.faces.application.FacesMessage; javax.faces.context.FacesContext; javax.faces.model.DataModel; javax.faces.model.ListDataModel;

import org.springframework.dao.DataIntegrityViolationException; import import import import com.oxia.formation.Contacts; com.oxia.formation.Contrats; com.oxia.formation.dao.ContactsDao; com.oxia.formation.dao.ContratsDao;

public class ContactCtr implements Serializable { private static final long serialVersionUID = 1L; private ContratsDao contratsDao; private ContactsDao contactsDao; private DataModel features; private Contacts selectedContact = new Contacts(); private Contacts contact; private List<Contacts> contacts; private List<Contrats> listeContrats; private boolean creation; @PostConstruct public void init() { contacts = contactsDao.getContacts(); features = new ListDataModel(contacts); } public DataModel getFeatures() { contacts = contactsDao.getContacts(); features = new ListDataModel(contacts); return features; } public List<Contacts> getContacts() {

contacts = contactsDao.getContacts(); features = new ListDataModel(contacts); return contacts; } public String editContact() { setSelectedContact(contacts.get(features.getRowIndex())); setCreation(false); return "success"; } public String create() { selectedContact = new Contacts(); setCreation(true); return "success"; } public String saveContact() { contact = new Contacts(); contact.setCIN(selectedContact.getCIN()); contact.setFirstName(selectedContact.getFirstName()); contact.setLastName(selectedContact.getLastName()); contact.setEmail(selectedContact.getEmail()); try { contactsDao.create(selectedContact); } catch (DataIntegrityViolationException e) { FacesContext.getCurrentInstance().addMessage( "Exist", new FacesMessage( "L'identifiant saisi existe dj dans la base")); return "echec"; } return "success"; } public String updateContact() { setCreation(false); contactsDao.update(selectedContact); return "success"; } public String deleteContact() { setCreation(false); contactsDao.delete(contacts.get(features.getRowIndex())); return "success"; } public String getContactById() { setCreation(false); setSelectedContact(contactsDao.findById(selectedContact.getCIN())); listeContrats = contratsDao.findContratsByContact(selectedContact .getCIN()); return "success"; } public ContactsDao getContactDao() { return contactsDao; } public void setContactsDao(ContactsDao contactsDao) { this.contactsDao = contactsDao; } public Contacts getSelectedContact() { return selectedContact; }

public void setSelectedContact(Contacts selectedContact) { this.selectedContact = selectedContact; } public boolean isCreation() { return creation; } public void setCreation(boolean creation) { this.creation = creation; } public ContratsDao getContratsDao() { return contratsDao; } public void setContratsDao(ContratsDao contratsDao) { this.contratsDao = contratsDao; } public List<Contrats> getListeContrats() { return listeContrats; } public void setListeContrats(List<Contrats> listeContrats) { this.listeContrats = listeContrats; } }

Il ne nous reste plus que le fichier de configuration faces-config.xml


<?xml version="1.0" encoding="UTF-8"?> <faces-config xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd" version="1.2"> <application> <!-- spring 2.5.x --> <elresolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver> </application> <navigation-rule> <from-view-id>/index.xhtml</from-view-id> <navigation-case> <from-action>#{contactCtr.create}</from-action> <from-outcome>success</from-outcome> <to-view-id>/onecontact.xhtml</to-view-id> </navigation-case> </navigation-rule> <navigation-rule> <from-view-id>/ListContact.xhtml</from-view-id> <navigation-case> <from-action>#{contactCtr.editContact}</from-action> <from-outcome>success</from-outcome> <to-view-id>/onecontact.xhtml</to-view-id> </navigation-case> <navigation-case> <from-action>#{contactCtr.create}</from-action> <from-outcome>success</from-outcome> <to-view-id>/onecontact.xhtml</to-view-id> </navigation-case> </navigation-rule> <navigation-rule> <from-view-id>/onecontact.xhtml</from-view-id> <navigation-case> <from-action>#{contactCtr.saveContact}</from-action>

<from-outcome>success</from-outcome> <to-view-id>/ListContact.xhtml</to-view-id> </navigation-case> <navigation-case> <from-action>#{contactCtr.updateContact}</from-action> <from-outcome>success</from-outcome> <to-view-id>/ListContact.xhtml</to-view-id> </navigation-case> <navigation-case> <from-action>#{contactCtr.deleteContact}</from-action> <from-outcome>success</from-outcome> <to-view-id>/ListContact.xhtml</to-view-id> </navigation-case> </navigation-rule> <navigation-rule> <from-view-id>/RechercheContact.xhtml</from-view-id> <navigation-case> <from-action>#{contactCtr.getContactById}</from-action> <from-outcome>success</from-outcome> <to-view-id>/detailContact.xhtml</to-view-id> </navigation-case> <navigation-case> <from-action>#{contactCtr.create}</from-action> <from-outcome>success</from-outcome> <to-view-id>/onecontact.xhtml</to-view-id> </navigation-case> </navigation-rule> <navigation-rule> <from-view-id>/detailContact.xhtml</from-view-id> <navigation-case> <from-action>#{contactCtr.create}</from-action> <from-outcome>success</from-outcome> <to-view-id>/onecontact.xhtml</to-view-id> </navigation-case> </navigation-rule> <managed-bean> <managed-bean-name>contactCtr</managed-bean-name> <managed-bean-class>com.oxia.formation.ctr.ContactCtr</managed-beanclass> <managed-bean-scope>session</managed-bean-scope> <managed-property> <property-name>contactsDao</property-name> <value>#{contactsDao}</value> </managed-property> <managed-property> <property-name>contratsDao</property-name> <value>#{contratsDao}</value> </managed-property> </managed-bean> </faces-config>

Nous pouvons prsent lancer lapplication. Pour cela, choisir loption Run As -> Run on Server .

Figure 13: Ecran Liste des contacts

Et voici la version complte du fichier web.xml


<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>jsfexemple</display-name> <!-- Faces Servlet --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/ApplicationContext*.xml </param-value> </context-param> <context-param> <param-name>javax.faces.CONFIG_FILES </param-name> <param-value> /WEB-INF/faces-config.xml</param-value> </context-param> <context-param> <param-name>javax.faces.DEFAULT_SUFFIX </param-name> <param-value>.xhtml</param-value> </context-param> <context-param> <param-name>org.ajax4jsf.VIEW_HANDLERS </param-name> <param-value>com.sun.facelets.FaceletViewHandler </param-value> </context-param> <listener> <listener-class>com.sun.faces.config.ConfigureListener</listenerclass> </listener> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <filter> <display-name>RichFaces Filter</display-name> <filter-name>richfaces</filter-name> <filter-class>org.ajax4jsf.Filter</filter-class> </filter> <filter-mapping> <filter-name>richfaces</filter-name> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> </filter-mapping> <filter> <filter-name>springSecurityFilterChain </filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy </filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain </filter-name> <url-pattern>/*</url-pattern> <dispatcher>FORWARD</dispatcher> <dispatcher>REQUEST</dispatcher> </filter-mapping> <servlet> <servlet-name>Faces Servlet</servlet-name>

<servlet-class>javax.faces.webapp.FacesServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- Faces Servlet Mapping --> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app>

8- Scurit avec Spring


Nous allons maintenant scuriser lapplication en demandant lutilisateur de se connecter avant de pouvoir accder lapplication. Pour cela, il suffit de modifier le fichier web.xml en ajoutant les balises suivantes :
<filter> <filter-name>springSecurityFilterChain </filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy </filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain </filter-name> <url-pattern>/*</url-pattern> <dispatcher>FORWARD</dispatcher> <dispatcher>REQUEST</dispatcher> </filter-mapping>

Nous allons ensuite crer le fichier ApplicationContext-security.xml


<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd"> <security:authentication-provider> <security:user-service> <security:user name="user" password="password" authorities="ROLE_USER" /> </security:user-service> </security:authentication-provider> <security:http> <security:intercept-url pattern="/login.jsf" filters="none" /> <security:intercept-url pattern="/loginFailure.jsf" filters="none" /> <security:intercept-url pattern="/**" access="ROLE_USER"/> <security:form-login login-page="/login.jsf" authentication-failure-url="/loginFailure.jsf" /> <security:anonymous /> <security:logout logout-success-url="/logout.jsf" logout-url="/logout" />

</security:http> </beans>

Le login et le mot de passe ainsi que les rles des utilisateurs sont configurs en dur dans le fichier (login : user, mot de passe : password). On dfinit aussi les rgles daccs aux pages de lapplication laide de llment intercept-url . Il s'agit simplement d'associer un pattern d'URL un ou plusieurs rles (sparation avec une virgule). A noter que les patterns d'URL sont traits dans l'ordre de dclaration : si /** tait dclar en premier, les autres patterns ne seraient pas vrifis. La page de login personnalise est spcifie laide de lattribut login-page . A noter que pour cette page, nous avons une rgle dinterception avec filters= none pour que la page de login ne soit pas filtre par Spring Security. Sans cette rgle, l'application tombe dans une boucle infinie qui tente d'afficher la page login.jsf , mais qui ncessiterait aussi d'tre authentifie (suivant la dernire rgle avec le pattern /**). Nous dfinissons ensuite la page login.xhtml ainsi que la page loginFailure.xhtml . La page de login doit respecter certaines rgles :

action => j_spring_security_check nom input identifiant => j_username nom input mot de passe => j_password

login.xhtml
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich" xmlns:c="http://java.sun.com/jstl/core" xmlns:sf="http://www.springframework.org/tags/faces" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:security="http://www.springframework.org/security/tags"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="pragma" content="no-cache" /> <meta http-equiv="cache-control" content="no-cache" /> <meta http-equiv="expires" content="0" /> <title>Authentification</title> </head> <body> <div class="form-login"> <div class="login1"></div> </div> <table align="center"> <tr> <td> <img src="images/connexion.png"/> </td> </tr> </table> <br/><br/><br/>

<form method="post" action="j_spring_security_check"> <table align="center"> <tr> <td>Identifiant :</td> <td><input name="j_username" value="" type="text" /></td> </tr> <tr> <td>Mot de passe :</td> <td><input name="j_password" type="password" /></td> </tr> </table> <table align="center"> <tr> <td> <input value="Valider" type="submit" /> </td> </tr> </table> </form> </body> </html>

Il suffit de lancer notre serveur pour avoir la page dauthentification.

Figure 14: Authentification

loginFailure.xhtml
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich" xmlns:c="http://java.sun.com/jstl/core" xmlns:sf="http://www.springframework.org/tags/faces" xmlns:jsp="http://java.sun.com/JSP/Page"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="pragma" content="no-cache" /> <meta http-equiv="cache-control" content="no-cache" /> <meta http-equiv="expires" content="0" /> <title>Authentification Failure</title> </head> <body> <br/><br/><br/> <table align="center"> <tr><td>L'identifiant ou le mot de passe saisi est incorrect</td></tr> </table> </body> </html>