Java Server Faces
Java Server Faces (JSF) est défini par la JSR 314. Il s'agit d'un framework permettant de créer des applications Web complètes.
Créer un projet avec JSF
L'implémentation de JSF intégrée dans TomEE est celle de la communauté Apache : MyFaces. MyFaces est une Servlet qu'il faut déclarer dans le fichier web.xml de son application :
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!--La servlet de JSF est configurée pour répondre à toutes les requêtes de fichiers XHTML-->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
JSF supporte une configuration de développement pour permettre un rechargement presque à chaud lorsque des modifications sont apportées à l'application. Pour l'activer, il faut rajouter au début du fichier web.xml un paramètre d'application :
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
Lorsque vous déploierez votre application dans TomEE, vous verrez dans la log de démarrage un message d'avertissement confirmant l'activation du mode développement :
*******************************************************************
*** WARNING: Apache MyFaces-2 is running in DEVELOPMENT mode. ***
*** ^^^^^^^^^^^ ***
*** Do NOT deploy to your live server(s) without changing this. ***
*** See Application#getProjectStage() for more information. ***
*******************************************************************
Comme tous les services Java EE, JSF dispose d'un fichier de déploiement au format XML. Ce fichier de déploiement s'appelle faces-config.xml et doit être situé dans le répertoire WEB-INF. Le contenu minimal de ce fichier est :
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2">
</faces-config>
Pour l'utilisation de JSF en vue d'un déploiement dans TomEE, nous allons également avoir besoin d'un service Java EE : CDI (Contexts and Dependency Injection). Nous reviendrons plus tard sur l'utilité de ce service. CDI n'est pas activé par défaut pour une application Web. Pour l'activer, il suffit d'ajouter le fichier de déploiement de CDI pour l'application. Ce fichier doit s'appeler beans.xml et être situé dans le répertoire WEB-INF. Le contenu minimal de ce fichier est :
<?xml version="1.0" encoding="UTF-8"?>
<beans
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/beans_1_0.xsd">
</beans>
La vue : facelets
JSF n'utilise pas les JSP, JSF dispose de son propre langage de déclaration de vue appelé facelet. Du point de vue du développeur, nous allons voir qu'il n'y a pas une très grande différence entre une JSP et une facelet. Par contre, il s'agit de deux technologies différentes : les balises supportées ne sont pas les mêmes et une facelet n'est pas transformée en Servlet.
Une facelet est un document XHTML 1.0 qui doit se conformer à la DTD XHTML-1.0-Transitional. Avec le succés de HTML5, des adaptations ont été faites dans JSF (Java EE 7) pour permettre de développer des facelets HTML5. Néanmoins, une facelet doit être un document XML bien formé.
<?xml version="1.0" encoding="UTF-8" ?>
<!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">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p>Hello XHTML 1.0</p>
</body>
</html>
Une facelet est un document XML que le moteur JSF va analyser pour rechercher des balises spécifiques JSF. L'utilisation des balises de facelets se fait grâce aux espaces de nom XML (XML namespaces). Il existe six bibliothèques standards de balises JSF. Chacune dispose de son propre espace de nom XML.
Préfixe | XML namespace | Description | Exemples de balise |
---|---|---|---|
h | http://java.sun.com/jsf/html | Contient les balises pour le rendu HTML des éléments pris en charge par JSF | h:head h:body h:form h:inputText |
f | http://java.sun.com/jsf/core | Contient les balises qui ne génèrent pas de rendu HTML mais assurent l'intéraction avec le serveur et le formattage de données | f:actionListener f:ajax |
c | http://java.sun.com/jsp/jstl/core | Contient les balises de la bibliothèque JSTL core (Cf cours sur les JSP).
Attention cette bibliothèque a été amputée notamment de la balise c:out par rapport à la version JSP.
En JSF, on utilise h:outputText à la place. |
c:if c:forEach |
fn | http://java.sun.com/jsp/jstl/functions | Contient les fonctions de la bibliothèque JSTL functions (Cf cours sur les JSP). Cette bibliothèque ne contient pas de balise. | fn:contains fn:join |
ui | http://java.sun.com/jsf/facelets | Contient les balises permettant des compositions de vues. Il est possible de définir un layout pour l'ensemble de l'application et d'appliquer automatiquement ce layout à chaque facelet. | ui:component ui:composition |
cc | http://java.sun.com/jsf/composite | Permet de définir de nouveaux composants graphiques. | cc:interface cc:implementation |
La bibliothèque JSF HTML (http://java.sun.com/jsf/html) contient notamment les balises h:head, h:body. Ces balises permettent d'indiquer au moteur JSF les parties du document HTML qui correspondent aux en-entêtes et au corps. JSF utilise ces informations pour éventuellement enrichir la page XHTML finale avec des balises supplémentaires.
<?xml version="1.0" encoding="UTF-8" ?>
<!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:h="http://java.sun.com/jsf/html" >
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</h:head>
<h:body>
<p>Hello Facelet</p>
</h:body>
</html>
On retrouve beaucoup de similitudes entre facelets et JSP. Par exemple, voici une facelet affichant les paramètres de la requête HTTP :
<?xml version="1.0" encoding="UTF-8" ?>
<!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:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:fn="http://java.sun.com/jsp/jstl/functions">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</h:head>
<h:body>
<table>
<tbody>
<c:forEach var="entry" items="#{paramValues}">
<tr>
<td><h:outputText value="#{entry.key}"/></td>
<td><h:outputText value="#{fn:join(entry.value, ', ')}" /></td>
</tr>
</c:forEach>
</tbody>
</table>
</h:body>
</html>
Il existe quasiment les mêmes objets implicites accessibles avec l'expression language (EL) que pour les JSP. Comme une JSP, une facelet peut accéder aux attributs des différentes portées (page, request, session, application). Cependant pour créer ces attributs, nous n'allons plus utiliser l'API servlet comme vu précédemment, nous allons utiliser le service CDI.
Une introduction à CDI
Contexts and Dependency Injection (CDI) est un service Java EE permettant de déclarer des objets Java qui seront automatiquement créés par le serveur et positionnés comme attributs dans la portée désirée. Ensuite ces objets sont accessibles depuis une JSP ou une facelets ou encore peuvent être injectés dans un composant Java EE ou un autre objet géré par CDI.
Déclarer un objet avec CDI
Nous verrons dans l'exemple ci-dessous une déclaration par annotations :
package fr.epsi;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
@Named
@RequestScoped
public class PersonneControleur {
public Personne getPersonne() {
// ...
}
}
L'annotation @Named
suffit à indiquer que cette classe peut être gérée par CDI.
L'annotation @RequestScoped
indique que l'instance de l'objet sera un attribut de portée requête.
Sur le même principe, il existe les annotations
@SessionScoped
et @ApplicationScoped
.
Par défaut, le nom de l'instance sera le même que le nom de la classe commençant par une minuscule. Ainsi, une fois cette classe ajoutée dans le projet, il est possible de l'utiliser dans une facelet :
<?xml version="1.0" encoding="UTF-8" ?>
<!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:h="http://java.sun.com/jsf/html" >
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</h:head>
<h:body>
<p>Bonjour #{personneControleur.personne.nom}</p>
</h:body>
</html>
S'il n'existe pas d'attribut personneControleur
, celui-ci sera automatiquement créé avec une portée requête.
Il est également possible de spécifier soi-même le nom du bean dans l'annotation @Named
:
@Named("monControleurDePersonne")
Le fichier de déploiement beans.xml
Comme la plupart des services Java EE, CDI dispose d'un fichier de déploiement appelé beans.xml. Ce fichier sert à déclarer des fonctionnalités avancées pour CDI mais il doit également être présent dans l'arborescence de l'application pour indiquer à TomEE d'activer le service CDI pour cette application. Pour une application Web, le fichier beans.xml doit se trouver dans le répertoire WEB-INF. Sa structure minimale est :
<?xml version="1.0" encoding="UTF-8"?>
<beans
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/beans_1_0.xsd">
</beans>
Le modèle
Dans une application JSF, n'importe quelle instance d'objet Java peut jouer le rôle du modèle. Le
modèle peut être un objet géré par CDI ou rendu disponible par un objet géré par CDI (ce dernier jouant alors le rôle de contrôleur).
Par exemple, une instance de la classe Personne
peut être utilisée comme modèle
dans un formulaire d'une facelet en y accédant via le bean CDI personneControleur vu précédemment :
<?xml version="1.0" encoding="UTF-8" ?>
<!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:h="http://java.sun.com/jsf/html" >
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</h:head>
<h:body>
<h:form acceptcharset="UTF-8" >
<h:outputLabel for="nom" value="nom" />
<h:inputText id="nom" value="#{personneControleur.personne.nom}"/>
<h:outputLabel for="age" value="âge" />
<h:inputText id="age" value="#{personneControleur.personne.age}" />
<h:commandButton />
</h:form>
</h:body>
</html>
Notez que depuis le début de ce chapitre, les expressions en EL (expression language) utilisées dans les facelets
sont délimitées par #{ }. Comme pour les JSP, JSF supporte l'écriture d'une EL
sous la forme ${ }. Cependant, l'utilisation du caractère #
indique que l'on souhaite activer le value binding. Cette fonctionnalité
indique au moteur JSF, que le contenu du bean personneControleur.personne
devra également être mis à jour
avec les données envoyées par le client. Concrètement, il est plus simple d'utiliser
systématiquement avec JSF la notation #{ }.
Le contrôleur
JSF est basé sur l'API servlet mais il permet aux développeurs d'application Web de s'en affranchir. Ainsi, avec JSF, un contrôleur est simplement une classe Java gérée par CDI qui expose des méthodes qui seront appelées par JSF lors de la réception des requêtes du client. Dans la terminologie JSF, on parle de backing beans pour désigner les objets Java avec lesquels la facelet iteragit.
La génération d'action vers le contrôleur se fait lorsque le client envoie des données vers le serveur.
En HTML, cela se fait par la soumission de formulaire. Avec JSF, la soumission de formulaire peut se faire avec la balise h:commandLink
ou
la balise h:commandButton
. Ces deux balise JSF disposent de l'attribut action
qui permet d'écrire une EL définissant l'appel à une fonction d'un backing bean (une instance gérée par CDI).
Il est possible de préciser dans l'EL les paramètres qui seront passés à la méthode côté serveur.
<?xml version="1.0" encoding="UTF-8" ?>
<!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:h="http://java.sun.com/jsf/html" >
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</h:head>
<h:body>
<h:form acceptcharset="UTF-8" >
<h:outputLabel for="nom" value="nom" />
<h:inputText id="nom" value="#{personneControleur.personne.nom}"/>
<h:outputLabel for="age" value="âge" />
<h:inputText id="age" value="#{personneControleur.personne.age}" />
<h:commandButton action="#{personneControleur.chercher()}"
value="chercher" />
</h:form>
</h:body>
</html>
Dans la facelet ci-dessus, l'action déclenchée par le bouton "chercher" est :
#{personneControleur.chercher()}
Cela signifie que JSF va chercher un bean CDI portant le nom "personneControleur"
et il va invoquer la méthode chercher
. Au préalable, les attributs nom
et age
de la propriété personneControleur.personne
auront
été mis à jour avec les valeurs envoyées dans la requête.
Ainsi un contrôleur valide pourrait être :
package fr.epsi;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
@Named
@RequestScoped
public class PersonneControleur {
private Personne personne = new Personne();
public Personne getPersonne() {
return personnes;
}
public void chercher() {
String nomAChercher = personne.getNom();
// ... effectuer la recherche dans un référentiel de personnes
}
}
La navigation
Une fonctionnalité importante des frameworks Web est la gestion de la navigation. Après avoir traité une requête, vers quelle vue, un contrôleur doit-il déléguer le traitement pour construire la représentation finale ?
Dans JSF, les vues sont les fichiers XHTML (les facelets). Les identifiants des facelets correspondent simplement au nom du fichier sans l'extension .xhtml. Une méthode de contrôleur indique la vue résultat en retournant son identifiant. Si la méthode de contrôleur ne retourne aucune valeur (void) ou retourne null, la vue résultat est la vue courante.
Si nous reprenons notre exemple de contrôleur, nous pouvons indiquer la vue résultat en modifiant
la méthode chercher
pour qu'elle retourne une chaîne de caractères.
package fr.epsi;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
@Named
@RequestScoped
public class PersonneControleur {
private Personne personne = new Personne();
public Personne getPersonne() {
return personnes;
}
public String chercher() {
String nomAChercher = personne.getNom();
// ... effectuer la recherche dans un référentiel de personnes
// il doit exister un fichier resultat.xhtml qui correspond
// à la facelet qui génèrera la vue.
return "resultat";
}
}
Pour la navigation par liens, il est possible d'utiliser les balises h:link
et h:button
dans les facelets. Ces balises disposent de l'attribut outcome
. Cet attribut donne l'identifiant
de la facelet cible. Bien sûr, la valeur de l'attribut outcome
peut être le résultat d'une EL.
<?xml version="1.0" encoding="UTF-8" ?>
<!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:h="http://java.sun.com/jsf/html" >
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</h:head>
<h:body>
<ul>
<!-- un lien vers la facelet entree.xhtml -->
<li><h:link outcome="entree" value="Entrée"/></li>
<!-- un lien vers la facelet plat.xhtml -->
<li><h:link outcome="plat" value="Plat"/></li>
<!-- un lien vers la facelet fromage.xhtml ou vers la facelet dessert.xhtml -->
<li><h:link outcome="#{param['fromage'] ? 'fromage' : 'dessert'}"
value="Fromage ou Dessert"/></li>
</ul>
</h:body>
</html>
La validation de formulaire
La validation des données de formulaire est une autre fonctionnalité importante des frameworks Web.
La biblothèque de balises core
de JSF fournit, entre autres, les balises f:validateDoubleRange
, f:validateLength
, f:validateLongRange
,
f:validateRegex
et f:validateRequired
.
Utilisées comme balises filles des entrées de formulaire, elles permettent d'ajouter des règles de validité
pour les données de formulaire. JSF validera automatiquement les données soumises par l'utilisateur avant
de transférer le traitement au contrôleur.
<?xml version="1.0" encoding="UTF-8" ?>
<!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:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core" >
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</h:head>
<h:body>
<h:form acceptcharset="UTF-8" >
<h:outputLabel for="nom" value="nom" />
<h:inputText id="nom" value="#{personneControleur.personne.nom}">
<f:validateLength minimum="1"/>
</h:inputText>
<h:message for="nom"/>
<h:outputLabel for="age" value="âge" />
<h:inputText id="age" value="#{personneControleur.personne.age}">
<f:validateLongRange minimum="1" maximum="99"/>
</h:inputText>
<h:message for="age"/>
<h:commandButton action="#{personneControleur.chercher()}"
value="chercher" />
</h:form>
</h:body>
</html>
Si la validation échoue, JSF retourne la même vue au client sans solliciter le contrôleur.
La vue dispose dans son contexte des messages d'erreur de validation. La balise h:message
permet d'indiquer où les erreurs d'une entrée de formulaire seront affichées dans la réponse.
Il est également possible de fournir sa propre implémentation d'un validateur. Pour cela, il suffit de créer une classe qui implémente l'interface
javax.faces.validator.Validator
.
Cette interface ne contient la déclaration que d'une seule méthode :
void validate(FacesContext context, UIComponent component, Object value)
throws ValidatorException
La validation échoue si un appel à cette méthode lance une ValidatorException
.
Le premier paramètre représente le contexte d'exécution JSF, le deuxième paramètre représente le composant graphique pour lequel la validation a été demandée.
Par exemple, pour un champ de formulaire de type input
, ce composant sera une instance de
UIInput
qui hérite de UIComponent
.
Enfin le troisième paramètre représente la valeur qui doit être validée. Selon le type de composant, cette valeur peut être de type String, Boolean...
La classe du validateur doit également porter l'annotation @FacesValidator
indiquant le
nom du validateur qui sera utilisé pour le référencer dans les facelets.
L'exemple ci-dessous montre un exemple de validateur permettant de s'assurer qu'une case à cocher (checkbox) a bien été cochée par l'utilisateur.
<?xml version="1.0" encoding="UTF-8" ?>
<!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:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core" >
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</h:head>
<h:body>
<h:form acceptcharset="UTF-8" >
<h:selectBooleanCheckbox id="myCheckbox" validatorMessage="Vous devez cocher la case">
<f:validator validatorId="booleanValidator"/>
</h:selectBooleanCheckbox>
<h:outputLabel for="myCheckbox" value="case à cocher" />
<h:message styleClass="error" for="myCheckbox"/><br/>
<h:commandButton action="#{controleur.doSomething()}" value="Go" />
</h:form>
</h:body>
</html>
package fr.epsi;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
// L'annotation ci-dessous permet de déclarer le nom du validateur pour JSF
@FacesValidator("booleanValidator")
public class BooleanValidator implements Validator {
@Override
public void validate(FacesContext ctx, UIComponent uiComponent, Object value)
throws ValidatorException {
// Puisque ce validateur est utilisé avec un h:selectBooleanCheckbox,
// on s'attend à ce que value soit de type Boolean.
if (! Boolean.TRUE.equals(value)) {
// Si la valeur n'est pas true, le validateur signale une ValidatorException.
// Le message d'erreur du validateur est directement extrait de l'attribut
// validatorMessage du composant dans la facelet.
UIInput uiInput = (UIInput) uiComponent;
throw new ValidatorException(new FacesMessage(uiInput.getValidatorMessage()));
}
}
}
La validation avec Bean Validation
Le serveur d'application fournit un autre service nommé Bean Validation (JSR303).
Bean Validation permet d'exprimer les contraintes de validité d'un objet avec des annotations. JSF est capable d'interagir
avec Bean Validation pour la validation de formulaire. Ainsi, plutôt que de déclarer la validation dans une facelet comme
dans la section précédente, il est possible d'ajouter des annotations directement sur le bean Personne
package fr.epsi;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.Size;
public class Personne {
@Size(min = 1, message = "Le nom est obligatoire !")
private String nom;
@Min(value=1, message = "L'âge doit être un nombre positif !")
@Max(value=99, message = "L'âge ne peut pas dépasser 99 ans !")
private int age;
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
La documentation des annotations de Bean Validation est disponible dans la documentation de l'API Java EE : http://docs.oracle.com/javaee/7/api/javax/validation/constraints/package-summary.html
Bean Validation est une bonne alternative aux balises JSF de validation si un bean doit être réutilisé comme modèle dans des facelets différentes.
Les requêtes Ajax
Une requête Ajax est une requête asynchrone qui est exécutée par le navigateur. Lorsque le serveur renvoie la réponse au navigateur, ce dernier ne modifie pas la page affichée mais rend accessible la réponse en JavaScript.
JSF supporte Ajax sans que le développeur Web n'ait à implémenter du code JavaScript. JSF injecte lui-même le code JavaScript nécessaire au moment du rendu de la facelet.
Pour activer Ajax, il suffit, par exemple, de spécifier la balise f:ajax
comme balise fille d'un
h:commandButton
:
<h:commandButton value="un bouton" action="#{monControleur.traiter()}">
<f:ajax execute="@form" render="resultat" />
</h:commandButton>
La déclaration ci-dessus suffit à générer automatiquement le code javascript dans la page XHTML pour que,
lorsque l'utilisateur clique sur le bouton, une requête Ajax soit soumise au serveur. La balise f:ajax
a deux attributs importants :
execute
: liste les composants qui sont pris en compte par la requête Ajax. Il est possible de lister les id des élements d'un formulaire séparés par un espace. On peut aussi utiliser un des mots-clés suivants : @form (tous les éléments du formulaire courant), @this (uniquement le composant qui contient la balisef:ajax
), @all (tous les composants graphiques JSF de la page), @none (aucune composant n'est associé à la requête Ajax).render
: spécifie l'ID ou la liste des ID des composants graphiques JSF dans la facelet qui doivent être mis à jour lors de la réception de la réponse Ajax. Comme pour l'attribut précédent, il est possible d'utiliser les mots-clés @this, @form, @all et @none
Pour le support d'Ajax, l'implémentation du contrôleur se fait souvent avec deux méthodes : une méthode pour permettre au contrôleur de recevoir les données de la facelet et une méthode pour permettre à la facelet d'obtenir, en retour, les résultats qui permettront de mettre à jour une partie de la page.
Un exemple simple mais complet serait :
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</h:head>
<h:body>
<h:form>
<h:commandButton value="un bouton" action="#{monControleur.traiter()}">
<f:ajax execute="@form" render="resultat" />
</h:commandButton>
</h:form>
<h:outputText id="resultat" value="#{monControleur.resultat}"/>
</h:body>
</html>
package fr.epsi;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
@Named
@RequestScoped
public class MonControleur {
private String resultat;
public String getResultat() {
return resultat;
}
public void traiter() {
resultat = "Bravo, vous avez fait une requête Ajax !";
}
}
... et bien plus
Ce chapitre n'avait pour ambition que de présenter les fonctionnalités les plus essentielles de JSF. Avec JSF, vous avez aussi la possibilité de créer un layout pour l'ensemble de l'application ou de créer en facelet vos propres composants graphiques réutilisables.
Vous pouvez également enrichir votre application avec des composants graphiques plus complexes. On pourra par exemple incorporer des bibliothèques tierces comme la très impressionante PrimeFaces.