I. Introduction▲
Avoir de belles URL lorsqu'on programme un site Web en Java JEE, surtout avec JSF, n'est pas une chose aisée. Il faut prendre en compte de nombreux aspects et peu de développeurs aiment s'y confronter. Heureusement, la bibliothèque Pretty Faces simplifie la tâche. C'est ce que nous allons découvrir dans la suite.
I-A. À propos▲
Découvrir une technologie n'est pas chose facile. En aborder plusieurs d'un coup l'est encore moins. Partant de ce constat, cet article a été écrit pour aller à l'essentiel. Les points importants sont présentés dans le corps de l'article et les éléments secondaires sont expliqués en annexes.
I-B. Avant de commencer▲
Pour écrire ce tutoriel, j'ai utilisé les éléments suivants :
- Java JDK 1.6.0_24-b07 ;
- Eclipse Indigo 3.7 JEE 64b ;
- Maven 3.0.3 ;
- Tomcat 6.0.29 64b ;
- Pretty Faces 3.3.2.
II. Découverte du projet d'exemple▲
II-A. Télécharger, installer et importer le projet d'exemple▲
Pour commencer, je vous propose de télécharger le fichier Zip « fibowebapp1.zip », contenant un projet Java-Maven d'exemple (une mini webapp) qui va nous servir de support visuel pour les fonctionnalités présentées dans la suite de cet article.
Compilez le projet d'exemple et importez-le dans Eclipse (comme expliqué dans le tutoriel « Importer un projet Maven dans Eclipse en 5 minutes ») ou dans l'IDE de votre choix.
Installez ensuite la webapp dans le serveur d'application de votre choix, par exemple Tomcat 6, ce que vous pouvez faire directement depuis Eclipse.
Pour suivre ce tutoriel, vous pouvez vous contenter de lire les codes proposés ci-dessous (codes complets en annexes) et de faire confiance aux captures d'écran.
II-B. Ce que fait déjà le projet d'exemple▲
Le projet d'exemple est une petite webapp permettant de calculer plusieurs fonctions mathématiques célèbres. Cette application Web n'a rien de très complexe. Elle utilise le framework Web JSF, incluse dans Java. Les fonctionnalités (calcul de la suite de Fibonacci et du factoriel) servent uniquement d'illustration.
À partir du menu, on peut aller sur la page qui nous intéresse, permettant de calculer la suite de Fibonacci. Cette page est située dans le sous-dossier « math » de l'application. Le code source du menu doit donc bien spécifier ce chemin.
<?xml version="1.0" encoding="UTF-8"?>
<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:c="http://java.sun.com/jsp/jstl/core">
<div id="menus">
<h:link value="Fibonacci" outcome="/math/fibonacci.jsf" /> <br/>
<h:link value="Factoriel" outcome="/math/factoriel.jsf" /> <br/>
</div>
</ui:composition>L'URL (adresse « http://…/fibowebapp/math/fibonacci.jsf ») de la page fait donc apparaitre le nom du sous-dossier (« math »). Ce n'est ni très joli, ni très pratique, ni très sécurisé, ni très performant du point de vue de l'indexation dans les moteurs de recherche, etc. Et c'est sans parler de l'extension « .jsf » qui est inutile du point de vue de l'utilisateur et donne des informations confidentielles.
À la place de l'URL « http://…/fibowebapp/math/fibonacci.jsf »), on préfèrerait avoir une adresse comme « http://…/fibowebapp/fibonacci », par exemple, non polluée par des détails techniques qui n'intéressent pas l'utilisateur.
Quand on clique sur le bouton « Calculer », après avoir choisi un rang, on reste sur la même page. L'URL ne change pas, mais le contenu de la page est rafraichi.
L'application utilise un bean standard JSF pour stocker les valeurs et lancer les actions.
@ManagedBean(name = "fiboBean")
public class FiboBean {
private Integer rang;
private Long valeur;
// Service singleton qui realise le calcul.
private final FiboService fiboService = FiboService.getInstance();
public void calculer() {
valeur = fiboService.calculerFibonacci(rang);
...
}
// + getters/setters
...Quant à la page, elle est également très simple.
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html" xmlns:c="http://java.sun.com/jsp/jstl/core"
template="/template.xhtml">
<ui:define name="mainContent">
<div id="content">
<h1>Fibonacci</h1>
<h:form>
Rang :
<h:selectOneMenu id="fiboselect" value="#{fiboBean.rang}">
<c:forEach var="entry" begin="1" end="90">
<f:selectItem itemLabel="#{entry}" itemValue="#{entry}"/>
</c:forEach>
</h:selectOneMenu>
<h:commandButton id="fibobutton" value="Calculer" action="#{fiboBean.calculer}" />
<c:if test="#{fiboBean.valeur ne null}">
La valeur de la suite de Fibonacci pour le rang <b>#{fiboBean.rang}</b> est <b>#{fiboBean.valeur}</b>.
</c:if>
...
</h:form>
</div>
</ui:define>
</ui:composition>III. Action▲
III-A. Maven▲
Durée estimée : 1 minute.
Pour utiliser Pretty Faces, il faut ajouter une dépendance dans le fichier « pom.xml ».
<dependency>
<groupId>com.ocpsoft</groupId>
<artifactId>prettyfaces-jsf2</artifactId>
<version>3.3.2</version>
</dependency>Puis relancer une installation Maven.
mvn clean install eclipse:eclipseEn fonction des éléments déjà présents sur le disque dur, le résultat de l'installation Maven devrait ressembler à la trace suivante.
C:\...\fibowebapp>mvn clean install eclipse:eclipse
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building fibowebapp 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 11.025s
[INFO] Finished at: Thu Apr 05 20:59:22 CEST 2012
[INFO] Final Memory: 10M/53M
[INFO] ------------------------------------------------------------------------On doit ensuite faire un refresh (touche F5) dans Eclipse pour faire apparaitre Pretty Faces dans la liste des bibliothèques référencées.
III-B. Configuration▲
Durée estimée : 2 minutes.
La bibliothèque Pretty Faces est livrée avec un filtre qu'on doit référencer dans la webapp. Pour cela, il faut modifier le fichier « web.xml ».
<filter>
<filter-name>Pretty Filter</filter-name>
<filter-class>com.ocpsoft.pretty.PrettyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Pretty Filter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>La balise « filter-mapping » indique, ici, que toutes les requêtes doivent passer par le filtre de Pretty Faces.
Il faut ensuite créer un fichier nommé « pretty-config.xml » dans le dossier « WEB-INF », juste à côté du fichier « web.wml ». Dans un premier temps, on va se contenter de créer un fichier « vide ».
<?xml version="1.0" encoding="UTF-8"?>
<pretty-config xmlns="http://ocpsoft.com/prettyfaces/3.3.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ocpsoft.com/prettyfaces/3.3.2
http://ocpsoft.com/xml/ns/prettyfaces/ocpsoft-pretty-faces-3.3.2.xsd">
</pretty-config>À ce stade, quand on relance la webapp, on ne doit constater aucun changement de comportement.
III-C. Adresses simplifiées▲
Durée estimée : 1 minute.
Les URL utilisées sont relativement laides, mais nous allons y remédier immédiatement. Pour cela, nous allons configurer le fichier « pretty-config.xml », en ajoutant des entrées pour chaque page.
<?xml version="1.0" encoding="UTF-8"?>
<pretty-config xmlns="http://ocpsoft.com/prettyfaces/3.3.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ocpsoft.com/prettyfaces/3.3.2
http://ocpsoft.com/xml/ns/prettyfaces/ocpsoft-pretty-faces-3.3.2.xsd">
<url-mapping id="home">
<pattern value="/home" />
<view-id value="/home.jsf" />
</url-mapping>
<url-mapping id="fibonacci">
<pattern value="/fibo" />
<view-id value="/math/fibonacci.jsf" />
</url-mapping>
<url-mapping id="factoriel">
<pattern value="/fact" />
<view-id value="/math/factoriel.jsf" />
</url-mapping>
</pretty-config>Il faut relancer le serveur pour que cette modification soit prise en compte.
On peut maintenant accéder à la page de calcul des éléments de la suite de Fibonacci à l'aide de l'URL simplifiée « http://…/fibowebapp/fibo », alors qu'il fallait utiliser l'adresse (moche) « http://…/fibowebapp/math/fibonacci.jsf » avant. On remarque en particulier la disparition de l'extension « .jsf » et de la mention du sous-dossier « math ».
Pretty Faces accepte des « regex » complexes dans ses mappings.
III-D. Adapter les menus▲
Durée estimée : 1 minute.
On constate que les menus continuent de fonctionner alors qu'on ne les a pas encore modifiés et qu'ils conduisent vers les jolies URL et non vers les anciennes versions. Cela vient du fait qu'on utilisait les balises JSF. Ça n'aurait pas été le cas si on avait utilisé les balises HTML classiques.
On va maintenant utiliser la « taglib » (ensemble de balises) de Pretty Faces pour adapter les menus. Ça nous permettra, plus tard, de passer des paramètres. Pour cela, il faut déclarer un nouveau « xmlns » et employer le tag « pretty:link ».
<?xml version="1.0" encoding="UTF-8"?>
<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:c="http://java.sun.com/jsp/jstl/core"
xmlns:pretty="http://ocpsoft.com/prettyfaces">
<div id="menus">
<!--
<h:link value="Fibonacci" outcome="/math/fibonacci.jsf" />
<h:link value="Factoriel" outcome="/math/factoriel.jsf" />
-->
<pretty:link mappingId="fibonacci">
Fibonacci
</pretty:link>
<pretty:link mappingId="factoriel">
Factoriel
</pretty:link>
</div>
</ui:composition>L'attribut « mappingId » de la balise « pretty:link » (dans le menu) fait référence à la valeur de l'attribut « id »de la balise « url-mapping » (dans la config).
III-E. Passer des paramètres▲
Durée estimée : 2 minutes.
Pour l'instant, on est obligé de passer par le menu et de choisir un rang dans la liste déroulante, puis de cliquer sur le bouton « Calculer » pour avoir la valeur d'un membre de la suite de Fibonacci. On voudrait avoir ce résultat directement, en passant un paramètre dans l'URL. Cela se fait classiquement à l'aide d'une adresse comme « http://…/fibowebapp/fibo?r=12 ». Il faut bien entendu programmer la gestion des paramètres et les injecter dans les beans. Avec Pretty Faces, cela ne prend que quelques secondes.
<?xml version="1.0" encoding="UTF-8"?>
<pretty-config xmlns="http://ocpsoft.com/prettyfaces/3.3.2" ...>
...
<url-mapping id="fibonacci">
<pattern value="/fibo" />
<view-id value="/math/fibonacci.jsf" />
<query-param name="r">#{fiboBean.rang}</query-param>
</url-mapping>
...
</pretty-config>Lorsqu'on demande l'adresse « http://…/fibowebapp/fibo?r=12 », on constate que le rang est déjà sélectionné à « 12 ».
Toutefois, on voudrait aussi que le calcul soit déjà réalisé lors de l'affichage de la page. Pretty Faces permet de lancer directement une méthode lors d'un appel.
<?xml version="1.0" encoding="UTF-8"?>
<pretty-config xmlns="http://ocpsoft.com/prettyfaces/3.3.2" ...>
...
<url-mapping id="fibonacci">
<pattern value="/fibo" />
<view-id value="/math/fibonacci.jsf" />
<query-param name="r">#{fiboBean.rang}</query-param>
<action>#{fiboBean.calculer}</action>
</url-mapping>
...
</pretty-config>Maintenant, quand on demande « http://…/fibowebapp/fibo?r=9 », on a bien la valeur déjà calculée.
Bien entendu, si le paramètre « r » n'est pas spécifié dans l'URL, ça va tout de même vers la bonne page, mais sans spécifier de valeur pour le rang. Dans notre cas, il faudra bien penser à donner une valeur par défaut au rang dans le bean ou vérifier que le rang n'est pas « null » pour éviter une « NullPointerException ».
public class FiboBean {
...
public void calculer() {
if(rang == null) {
return;
}
...III-F. Des URL jolies malgré les paramètres▲
Durée estimée : 1 minute.
On a déjà un résultat très sympa, mais pas encore assez à mon goût ; ce n'est pas très agréable d'avoir des signes « ? » ou « = » dans les URL. À la place d'une adresse comme « http://…/fibowebapp/fibo?r=14 », on voudrait une URL ressemblant à « http://…/fibowebapp/fibo/14 », comme si la valeur « 14 » était une sous-rubrique de la section « fibo » du site.
Pour avoir de telles adresses, on va ajouter un nouveau mapping dans la configuration de Pretty Faces.
<?xml version="1.0" encoding="UTF-8"?>
<pretty-config xmlns="http://ocpsoft.com/prettyfaces/3.3.2" ...>
...
<!-- Avec des ? -->
<url-mapping id="fibonacci">
<pattern value="/fibo" />
<view-id value="/math/fibonacci.jsf" />
<query-param name="r">#{fiboBean.rang}</query-param>
<action>#{fiboBean.calculer}</action>
</url-mapping>
<!-- Sans les ? -->
<url-mapping id="fibonacci2">
<pattern value="/fibo/#{fiboBean.rang}" />
<view-id value="/math/fibonacci.jsf" />
<action>#{fiboBean.calculer}</action>
</url-mapping>
...
</pretty-config>On peut donc demander l'adresse « http://…/fibowebapp/fibo/14 », qui est beaucoup plus jolie et beaucoup plus efficace dans le cadre du référencement sur les moteurs de recherche.
La bibliothèque Pretty Faces ne limite pas le nombre de paramètres (avec « ?= ») et/ou sous-section à un seul. On peut en utiliser autant qu'on le souhaite (qu'on en a besoin) et on peut mélanger l'utilisation des paramètres et des sous-sections. On peut tout à fait avoir des URL comme « http://…/fibowebapp/fibo/14/fr/blue/15?method=recursif&limit=10 ».
III-G. Réécriture d'URL▲
Un peu dans le même ordre d'idée, on peut utiliser Pretty Faces avec des jolies URL sur une application qui nécessite des URL avec des paramètres. Par exemple, si l'application est conçue pour fonctionner avec l'adresse laide « http://…/fibowebapp/math/factoriel?number=5 », on peut utiliser Pretty Faces pour employer une l'adresse « http://…/fibowebapp/fact/5 » à la place. C'est tout de même plus sympa, n'est-ce pas ? Cela se fait simplement comme les autres mappings.
<?xml version="1.0" encoding="UTF-8"?>
<pretty-config xmlns="http://ocpsoft.com/prettyfaces/3.3.2" ...>
...
<url-mapping>
<pattern value="/fact/#{number}" />
<view-id>/math/factoriel.jsf</view-id>
</url-mapping>
...
</pretty-config>La bibliothèque va, ici, comprendre qu'il faut mapper la sous-section identifiée par « #{number} » sur le paramètre « number ». Cela fonctionne comme une simple redirection, sans affecter des variables de bean, contrairement aux exemples des chapitres précédents.
III-H. Liens avec des paramètres▲
Durée estimée : 1 minute.
L'étape d'après consiste à construire des liens, utilisant la configuration de Pretty Faces, tout en passant des paramètres, mais sans se soucier de les organiser.
À titre d'illustration, nous allons ajouter un nouveau menu.
<?xml version="1.0" encoding="UTF-8"?>
<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:c="http://java.sun.com/jsp/jstl/core"
xmlns:pretty="http://ocpsoft.com/prettyfaces">
<div id="menus">
<pretty:link mappingId="fibonacci">
Fibonacci
</pretty:link>
<pretty:link mappingId="fibonacci2">
<f:param value="10" />
Fibonacci de 10
</pretty:link>
<pretty:link mappingId="factoriel">
Factoriel
</pretty:link>
</div>
</ui:composition>Après avoir relancé le serveur, on constate que ce nouveau menu conduit bien vers l'adresse « http://…/fibowebapp/fibo/10 » et que le calcul est déjà réalisé lorsqu'on arrive sur la page.
Bien entendu, ce paramètre peut être dynamique. À titre d'illustration, disons qu'on souhaite utiliser une valeur par défaut (par exemple à 7), définie dans le bean.
public class FiboBean {
private static final Integer DEFAULT_RANG = 7;
public Integer getDefaultRang() {
return DEFAULT_RANG;
}
...Il ne reste plus qu'à utiliser cette valeur (qui n'est pas forcément une constante) dans le menu.
<?xml version="1.0" encoding="UTF-8"?>
<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:c="http://java.sun.com/jsp/jstl/core"
xmlns:pretty="http://ocpsoft.com/prettyfaces">
<div id="menus">
<pretty:link mappingId="fibonacci2">
<f:param value="#{fiboBean.defaultRang}" />
Fibonacci au rang DEFAULT_RANG
</pretty:link>
...
</div>
</ui:composition>Sans surprise, le lien fonctionne…
Et voilà…
IV. Conclusions▲
C'est magique : Pretty Faces permet une navigation plus intelligente et bien plus sexy. Ce petit article n'aborde que les points fondamentaux de la bibliothèque, mais j'ai le sentiment qu'ils couvrent les besoins les plus courants.
Pour en savoir plus, je recommande la lecture de la documentation de Pretty Faces car cette bibliothèque regorge de fonctionnalités. Elle mérite d'être connue et utilisée. Je vous invite également à regarder les autres produits de la société OCPSoft, et en particulier Pretty Time à propos duquel j'écrirai prochainement un article.
Le code final de ce tutoriel est disponible dans le fichier ZIP fibowebapp2.zip.code final
Retrouvez mes autres tutoriels rapides sur developpez.com à l'adresse https://thierry-leriche-dessirier.developpez.com/#page_articlesTutoriels
Vos retours nous aident à améliorer nos publications. N'hésitez donc pas à commenter cet article sur le forum : 6 commentaires ![]()
V. Remerciements▲
Je tiens à remercier, en tant qu'auteur de tutoriel, toutes les personnes qui m'ont aidé et soutenu. Je pense tout d'abord à mes collègues qui subissent mes questions au quotidien, mais aussi à mes contacts et amis du Web, dans le domaine de l'informatique ou non, qui m'ont fait part de leurs remarques et critiques. Bien entendu, je n'oublie pas l'équipe de developpez.com qui m'a guidé dans la rédaction de cet article et m'a aidé à le corriger et le faire évoluer, principalement sur le forum.
Plus particulièrement j'adresse mes remerciements à keulkeul et Claude Leloup.

VI. Annexes▲
VI-A. Précisions sur la page de calcul▲
En plus de calculer la valeur du membre de la suite de Fibonacci pour le rang choisi, la page calcule tous les éléments de rang inférieur. Le programme utilise deux méthodes de calcul. La première méthode fonctionne à l'aide d'un algorithme récursif. Elle est un peu lente, mais donne des valeurs exactes. La seconde méthode emploie une formule mathématique ayant l'avantage d'être rapide, mais dont la justesse dépend de la précision des constantes utilisées.
La seconde méthode de calcul utilise le nombre d'or et la racine de 5.
public class FiboService {
private final static double NOMBRE_OR = 1.61803398874989;
private final static double RACINE_5 = 2.236067977499;La valeur renvoyée par la méthode de calcul direct dépend de la précision des constantes utilisées. Ici, on constate un écart dès le rang 62, ce qu'on met en avant dans la dernière colonne.
Ces deux méthodes de calcul ont été présentées dans le tutoriel « 3T en pratique, application au calcul de la suite de Fibonnaci, en 5 minutes », disponible sur Developpez.com.
VI-B. Liens▲
Le site Web de Pretty Faces est disponible à l'adresse http://ocpsoft.org/prettyfaces

Retrouvez mes autres tutoriels sur developpez.com à l'adresse https://thierry-leriche-dessirier.developpez.com/#page_articlesTutoriels

Ajoutez-moi à vos contacts à l'aide du QR Code suivant :

VI-C. Les fichiers importants en entier▲
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dvp</groupId>
<artifactId>fibowebapp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>fibowebapp</name>
<description>fibowebapp</description>
<licenses>
<license>
<name>Copyright ©1995-2012 thierryler.com et Copyright ©2012 Developpez.com</name>
<comments>Les sources présentées sur cette page sont libres de droits, et vous pouvez [..] </comments>
</license>
</licenses>
<developers>
<!-- Thierry -->
<developer>
<name>Thierry Leriche-Dessirier</name>
<roles>
<role>Developper</role>
</roles>
<organization>ICAUDA</organization>
</developer>
</developers>
<properties>
<!-- Build -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.6</java.version>
<wtp.version>2.0</wtp.version>
<!-- Test -->
<junit.version>4.10</junit.version>
<!-- Servlet et pages -->
<mojarra.version>2.1.4</mojarra.version>
<jboss-el.version>2.0.1.GA</jboss-el.version>
<jstl.version>1.2</jstl.version>
<servlet-api.version>2.5</servlet-api.version>
<!-- Plugins -->
<maven-compiler-plugin.version>2.3.2</maven-compiler-plugin.version>
<maven-eclipse-plugin.version>2.8</maven-eclipse-plugin.version>
<tomcat-maven-plugin.version>1.1</tomcat-maven-plugin.version>
<!-- Pretty faces -->
<prettyfaces-jsf2.version>3.3.2</prettyfaces-jsf2.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- JSF -->
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>${mojarra.version}</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>${mojarra.version}</version>
<scope>compile</scope>
</dependency>
<!-- JSTL -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<!-- Servlet 2.5 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servlet-api.version}</version>
<scope>provided</scope>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- pretty faces -->
<dependency>
<groupId>com.ocpsoft</groupId>
<artifactId>prettyfaces-jsf2</artifactId>
<version>${prettyfaces-jsf2.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- servlet -->
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<scope>compile</scope>
</dependency>
<!-- JSTL -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- pretty faces -->
<dependency>
<groupId>com.ocpsoft</groupId>
<artifactId>prettyfaces-jsf2</artifactId>
</dependency>
</dependencies>
<build>
<finalName>fibowebapp</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>${maven-eclipse-plugin.version}</version>
<configuration>
<wtpversion>${wtp.version}</wtpversion>
<source>${java.version}</source>
<target>${java.version}</target>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<!-- Tomcat plugin for embedded tomcat -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>tomcat-maven-plugin</artifactId>
<version>${tomcat-maven-plugin.version}</version>
<configuration>
<path>/${project.build.finalName}</path>
</configuration>
</plugin>
</plugins>
</build>
</project><?xml version="1.0" encoding="UTF-8"?>
<pretty-config xmlns="http://ocpsoft.com/prettyfaces/3.3.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ocpsoft.com/prettyfaces/3.3.2
http://ocpsoft.com/xml/ns/prettyfaces/ocpsoft-pretty-faces-3.3.2.xsd">
<url-mapping id="home">
<pattern value="/home" />
<view-id value="/home.jsf" />
</url-mapping>
<url-mapping id="fibonacci">
<pattern value="/fibo" />
<view-id value="/math/fibonacci.jsf" />
<query-param name="r">#{fiboBean.rang}</query-param>
<action>#{fiboBean.calculer}</action>
</url-mapping>
<url-mapping id="fibonacci2">
<pattern value="/fibo/#{fiboBean.rang}" />
<view-id value="/math/fibonacci.jsf" />
<action>#{fiboBean.calculer}</action>
</url-mapping>
<url-mapping id="factoriel">
<pattern value="/fact" />
<view-id value="/math/factoriel.jsf" />
</url-mapping>
</pretty-config><?xml version="1.0" encoding="UTF-8"?>
<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:c="http://java.sun.com/jsp/jstl/core"
xmlns:pretty="http://ocpsoft.com/prettyfaces">
<div id="menus">
<!--
<h:link value="Fibonacci" outcome="/math/fibonacci.jsf" /> <br/>
<h:link value="Factoriel" outcome="/math/factoriel.jsf" /> <br/>
-->
<pretty:link mappingId="fibonacci">
Fibonacci
</pretty:link><br/>
<pretty:link mappingId="fibonacci2">
<f:param value="10" />
Fibonacci de 10
</pretty:link><br/>
<pretty:link mappingId="fibonacci2">
<f:param value="#{fiboBean.defaultRang}" />
Fibonacci au rang DEFAULT_RANG
</pretty:link><br/>
<pretty:link mappingId="factoriel">
Factoriel
</pretty:link><br/>
</div>
</ui:composition>VI-D. PrettyFaces et Spring Security▲
Quand on travaille sur une application Web importante, on a (en général) une page connexion (login) au système. Si celle-ci utilise Spring et plus particulièrement le module Spring-Security, il faut faire attention à deux choses : l'ordre des filtres dans le fichier « web.xml » et la configuration des accès.
Contrairement à ce qu'on pourrait (à tort) croire, il faut que le filtre de Spring-Security soit positionné avant celui de Pretty Faces.
<?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"
version="2.5">
...
<!-- Spring security -->
<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>
</filter-mapping>
<!-- Pretty faces -->
<filter>
<filter-name>Pretty Filter</filter-name>
<filter-class>com.ocpsoft.pretty.PrettyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Pretty Filter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
...Pour la page de connexion, il faut bien entendu ajouter un bon mapping. En général, la configuration de Spring Security ressemble à la suivante :
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="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-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
...
<http use-expressions="true">
<!-- login / logout -->
<intercept-url pattern="/login" access="permitAll" />
<intercept-url pattern="/login/**" access="permitAll" />
<intercept-url pattern="/accessdenied" access="permitAll" />
<intercept-url pattern="/logout_success" access="permitAll" />
...
<!-- Les autres pages sont refusees -->
<intercept-url pattern="/**" access="denyAll" />
...
<!-- login -->
<form-login login-processing-url="/login_check" login-page="/login"
default-target-url="/home/" authentication-failure-url="/login?login_error=1"
authentication-success-handler-ref="myHandler" />
<access-denied-handler error-page="/accessdenied" />
<!-- logout -->
<logout invalidate-session="true" logout-success-url="/logout_success"
logout-url="/logout" delete-cookies="JSESSIONID" />
...Il faut donc avoir une configuration de Pretty faces qui réponde aux URL de connexion.
<?xml version="1.0" encoding="UTF-8"?>
<pretty-config xmlns="http://ocpsoft.com/prettyfaces/3.3.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ocpsoft.com/prettyfaces/3.3.2
http://ocpsoft.com/xml/ns/prettyfaces/ocpsoft-pretty-faces-3.3.2.xsd">
...
<!-- Login -->
<url-mapping id="login">
<pattern value="/login" />
<view-id value="/login.jsf" />
</url-mapping>
<!-- Access denied -->
<url-mapping id="accessdenied">
<pattern value="/accessdenied" />
<view-id value="/accessdenied.jsf" />
</url-mapping>
<!-- Logout -->
<url-mapping id="logout">
<pattern value="/logout" />
<view-id value="/j_spring_security_logout" />
</url-mapping>
<!-- Logout successed -->
<url-mapping id="logout_success">
<pattern value="/logout_success" />
<view-id value="/logout_success.jsf" />
</url-mapping>
...
















