Plutôt que faire un énième article présentant les nouveautés de JSF 2. J’ai décidé d’attaquer le problème sous un autre angle.
En effet, lorsque j’ai voulu tester ce que propose JSF 2 et le mettre en application, je suis parti de l’application Personne du blog qui est une application JSF 1.2 (avec Richfaces 3.3.3) pour la migrer vers JSF 2 et Richfaces 4.
Il est possible d’utiliser Richfaces 3.3.x avec JSF 2 mais tout n’est pas compatible, alors autant tout migrer en même temps
Je vais donc vous présenter dans cet article un cas concret de migration d’une application JSF 1.2 vers JSF 2.
Pour appuyer mon propos, je me base sur la version 1.2.1 du projet Personne pour la partie JSF 1.2 et la version 1.3.0 pour la partie JSF 2.
Le projet utilise également Spring, mais aucune modification n’est à effectuer de ce coté pour la migration. Ceci est vrai pour la configuration à proprement dite. Dans le cycle de vie des beans, c’est une autre histoire et nous reviendrons dessus dans l’article.
Si vous souhaitez en savoir plus sur la création d’un projet avec Spring et JSF, vous pouvez lire cet article => Faire communiquer Spring et JSF
Sommaire
Modification du faces-config.xml
Dépendances Maven
Tout d’abord, les dépendances Maven de JSF et Richfaces ont changé. Voici donc les nouvelles dépendances pour JSF 2:
<dependency> <groupId>com.sun.faces</groupId> <artifactId>jsf-api</artifactId> <version>2.1.7</version> </dependency> <dependency> <groupId>com.sun.faces</groupId> <artifactId>jsf-impl</artifactId> <version>2.1.7</version> </dependency>
Richfaces 4 utilise le principe de BOM Maven. Il faut donc ajouter cette dépendance dans la section dependencyManagement du pom.xml:
<dependency> <groupId>org.richfaces</groupId> <artifactId>richfaces-bom</artifactId> <version>4.2.0.Final</version> <scope>import</scope> <type>pom</type> </dependency>
Puis celles ci dans la section dependencies. Remarquez que grâce au principe du bom, nous n’avons pas besoin de spécifier les versions des dépendances:
<dependency> <groupId>org.richfaces.ui</groupId> <artifactId>richfaces-components-ui</artifactId> </dependency> <dependency> <groupId>org.richfaces.core</groupId> <artifactId>richfaces-core-impl</artifactId> </dependency>
Remplacez également la dépendance suivante:
<dependency> <groupId>com.sun.el</groupId> <artifactId>el-ri</artifactId> <version>1.0</version> </dependency>
Par:
<dependency> <groupId>javax.el</groupId> <artifactId>el-api</artifactId> <version>2.2</version> </dependency>
Facelets étant maintenant intégré dans JSF 2, il faut supprimer les dépendances liées à Facelets.
Modification du web.xml
Maintenant que nos dépendances sont à jour, passons au web.xml. Il s’agit principalement d’un changement de nom pour les listeners et les context-params du web.xml, je vous propose donc un tableau de comparaisons entre ancienne et nouvelle valeur:
| Ancienne valeur | Nouvelle valeur |
| facelets.BUFFER_SIZE | javax.faces.BUFFER_SIZE |
| facelets.REFRESH_PERIOD | javax.faces.FACELETS_REFRESH_PERIOD |
| facelets.RESOURCE_RESOLVER | javax.faces.FACELETS_RESOURCE_RESOLVER |
| facelets.RESOURCE_RESOLVER | javax.faces.FACELETS_RESOURCE_RESOLVER |
| org.richfaces.SKIN | org.richfaces.skin |
Il existe d’autres changements de nom, mais il s’agit d’un article sur un cas concret, je ne ferais donc pas la liste complète de ces changements.
Le context-param facelets.DEVELOPMENT a changé de manière plus importante. Il s’agissait auparavant d’indiquer si l’on était en développement ou non.
Son remplaçant est un peu plus complexe. Voici son code:
<context-param> <param-name>javax.faces.PROJECT_STAGE</param-name> <param-value>Development</param-value> </context-param>
Ce paramètre indique toujours le mode de l’application mais de manière plus précise. Voici les valeurs que peut prendre ce paramètre:
- Development
- UnitTest
- SystemTest
- Production, la valeur par défaut
Enfin, Facelets ayant été supprimé, vous pouvez supprimer le context-param et le filter suivants:
- org.ajax4jsf.VIEW_HANDLERS
- org.ajax4jsf.Filter
Modification du faces-config.xml
La seule modification nécessaire dans le faces-config.xml est de changer la version de ce dernier.
Concrètement remplacer:
<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">
Par:
<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_2_1.xsd" version="2.1">
Voila, c’est tout pour ce fichier
Modification coté xhtml
La partie configuration à proprement dite est maintenant prête. Attaquons nous maintenant au code même de l’application. Nous allons faire ceci en deux parties: le code des xhtml dans ce chapitre et le code Java dans le chapitre suivant.
Jsf étant une technologie de présentation, c’est clairement vos pages xhtml qui seront les plus impactées par cette migration.
Les principales modifications vont concerner les composants Richfaces, les composants Jsf étant compatibles d’une version à l’autre en grande majorité.
Un point avant de voir les modifications Richfaces. Les éléments HTML purs ont également besoin d’être déclarés dans les namespaces de votre page, sans quoi des erreurs seront remontées à l’exécution. Pour se faire rajouté ce namespace dans le ui:composition de votre page:
xmlns="http://www.w3.org/1999/xhtml"
Ce qui vous donnera un ui:composition de cette forme:
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich" xmlns:ui="http://java.sun.com/jsf/facelets" template="/templates/default.xhtml">
Jsf 2 apporte les fonctionnalités Ajax qui manquaient à la version 1.2. Richfaces 3 comblaient ces manques en apportant ces propres fonctionnalités Ajax.
Afin d’éviter un doublon entre les deux modes, Richfaces 4 supprime des tags apportant l’Ajax. D’autres tags sont également supprimés et vous devez donc fournir un équivalant. Voici les tags supprimés impactant l’application:
- a4j:keepAlive est remplacé par le scope View de Jsf 2, nous reviendrons dessus dans le chapitre suivant.
- a4j:form. Utilisé uniquement le tag h:form
- rich:spacer. Pas d’équivalent mais remplacez le par une simple <div> avec une classe css.
- a4j:loadStyle est remplacé par h:outputStylesheet
- a4j:loadScript est remplacé par h:outputScript
- rich:modalPanel est renommé rich:popupPanel
Comme je l’ai dit plus haut, Jsf 2 apporte des fonctionnalités Ajax. Le principal tag concernant cette fonctionnalité est f:ajax. Vous pouvez remplacer tous vos a4j:support par ce tag mais Richfaces propose son propre tags qui étend les fonctionnalités de f:ajax: le tag a4j:ajax.
Ce tag est simplement la mise à jour de a4j:support en standardisant ses attributs avec ce que propose Jsf 2. Ainsi les principaux changements concernant les attributs de tags sont:
- action devient listener. La signature de la méthode du listener coté Java devient:
public void function(AjaxBehaviorEvent event);
- reRender devient render. Il s’utilise de la même façon que dans Richfaces 3.
- Les paramètres de l’attribut event sont standardisés. Ils perdent le « on » de leur nom. Ainsi « onclick » devient « click », « onchange » devient « change » est ainsi de suite. Ceci afin de correspondre aux spécifications Jsf 2.
Il faut noter également l’apparition de l’attribut execute. Vous allez spécifier dans votre attribut quels éléments vont être envoyés au serveur lors de l’exécution de votre requête. Les paramètres possibles sont:
- @all qui enverra toute la page
- @this qui enverra uniquement le champ sur lequel s’applique le a4j:ajax
- @form qui enverra tout le formulaire ou le champ se trouve
- @none. Aucun élément ne sera envoyé
- @region qui enverra les éléments du a4j:region si vous l’utilisez
Vous pouvez également saisir une liste d’ids correspondant à des éléments de votre page. Ces éléments seront alors envoyés au serveur.
Un autre changement impactant pour vos pages xhtml est la gestion des fichiers css et javascript. Auparavant, vous pouviez placer vos fichiers où vous le vouliez et le tag de chargement les retrouvait afin de les charger dans votre page.
Maintenant avec l’utilisation des tags h:outputStylesheet et h:outputScript, vous devez obligatoirement placer vos fichiers dans les répertoires suivants (dans le cas d’un war):
webapp --resources ----js ----css
Vos javascripts étant dans le répertoire « js » et vos css dans le répertoire « css ».
Dernière indication concernant la migration de vos pages et Richfaces. Cette librairie de composant ne supporte plus Internet Explorer 6 (ce qui est très bien comme ça
), néanmoins, si vous devez toujours supporter ce navigateur, c’est un paramètre à prendre en compte.
Sachez également que Richfaces 4 ne propose pas à ce jour la compression de ses javascripts (ce que faisait Richfaces 3). Cela viendra certainement, mais ça sera à vous de le faire aujourd’hui.
Modification coté Java
Dernière étape de notre migration Jsf 1.2 vers Jsf 2: la modification du code Java.
Comme je l’ai signalé plus haut, Richfaces ne gère plus le KeepAlive, l’annotation @KeepAlive allant avec est donc supprimée. Cette suppression est dû à la mise en place par Jsf du scope View qui fait à peux près la même chose. Si vous souhaitez utiliser les nouvelles annotations Jsf, vous devrez annoter vos beans utilisant le KeepAlive par:
@ManagedBean @ViewScoped
Si vous utilisez Spring pour manager vos beans, vous devrez implémenter le scope View de Jsf vous même.
Si vos beans sont peu typés Jsf, c’est, avec le changement de signature des méthodes actions, à peut près les seules modifications que vous aurez à effectuer dans votre code Java.
Conclusion
C’est finit pour cette migration. Techniquement, cette migration se passe plus bien. Toutefois si vous avez une application complexe avec de grosses pages xhtml, elle peut vous coûter beaucoup de temps (et donc d’argent) surtout si vous utilisez beaucoup de fonctionnalités Ajax.
Si vous utilisiez Richfaces seulement pour ses capacités Ajax, il n’est peut être pas utile de garder ce framework. En effet, tout ce que propose Richfaces 3 en matière d’Ajax existe à présent de base dans Jsf 2. Néanmoins, les composants apportés par Richfaces 4 sont toujours intéressants.
Comme je l’ai dit au début de l’article, je présente un cas concret de migration depuis l’application « Personne » du blog. L’article ne présente donc pas une liste exhaustive de toutes les modifications que vous pourriez avoir à effectuer.
Néanmoins les problèmes principaux que vous pourriez rencontrer sont présentés.
Je vous invite à regarder le code source de la version 1.3.0 du projet « Personne » afin de voir l’exemple dans son ensemble
Liens utiles:
Javadoc des tags Jsf 2: http://javaserverfaces.java.net/nonav/docs/2.0/pdldocs/facelets/
Javadoc des tags Richfaces 4.2: http://docs.jboss.org/richfaces/latest_4_2_X/vdldoc/
Guide de migration Richfaces 3 vers Richfaces 4: http://www.jboss.org/richfaces/docs/3-x-4-x-migration
Démonstration des tags Richfaces 4: http://richfaces-showcase.appspot.com/richfaces/component-sample.jsf
Merci de ces explications précises.
En suivant la migration au niveau de Maven (bom) je suis face à un problème dans le pom.xml m’indiquant :
Project build error: 'dependencies.dependency.version' for org.richfaces.ui:richfaces-components-ui:jar is missing.Alors vous avez dit que grâce au principe du bom, nous n’avons pas besoin de spécifier les versions des dépendances..
Une idée pour résoudre ce problème ?
Merci
Bonjour,
Je confirme mon propos, vous pouvez d’ailleurs voir un exemple fonctionnel avec le projet « Personnes » du blog.
Vérifiez les points suivants qui peuvent être oubliés assez facilement:
Le bom est il en scope import et bien dans la section dependencyManagement ?
Si oui, postez votre pom.xml ici que je puisse regarder si je vois quelque chose d’anormal
(ou envoyez le via le formulaire de contact si vous préférez).
N’hésitez pas à comparer votre pom avec celui du projet du bom.
Merci Monsieur pour ce tuto que je trouve complet.
cependant j’ai le même souci que Issam.
Internal error: org.apache.maven.artifact.InvalidArtifactRTException: For artifact {org.richfaces.ui:richfaces-components-ui:null:jar}: The version cannot be empty. -> [Help 1]
org.apache.maven.InternalErrorException: Internal error: org.apache.maven.artifact.InvalidArtifactRTException: For artifact {org.richfaces.ui:richfaces-components-ui:null:jar}: The version cannot be empty.
Merci d’avance de votre aide.
Bonjour,
Veuillez vérifier les points que j’ai précisé dans ma réponse à Issam.
):
Dans tous les cas, voici un pom concis qui compile correctement et basé sur cet article (désolé pour la mise en forme, le système de commentaire n’aime pas trop le code
<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/xsd/maven-4.0.0.xsd« >
<modelVersion>4.0.0</modelVersion>
<groupId>net.blog.dev.test</groupId>
<artifactId>test-richfaces-4.2</artifactId>
<packaging>pom</packaging>
<version>1</version>
<name>${project.artifactId}</name>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.richfaces</groupId>
<artifactId>richfaces-bom</artifactId>
<version>4.2.0.Final</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.richfaces.ui</groupId>
<artifactId>richfaces-components-ui</artifactId>
</dependency>
<dependency>
<groupId>org.richfaces.core</groupId>
<artifactId>richfaces-core-impl</artifactId>
</dependency>
</dependencies>
</project>
Ce pom build parfaitement chez moi avec Maven 2.2.1.
Autre point, vérifiez que vous utilisez bien Maven 2.0.9 ou supérieur car les versions inférieur ne gèrent pas le scope import et donc peuvent provoquer ce problème.
N’hésitez pas à me faire un retour