Outils pour utilisateurs

Outils du site


helloworld:web:java:jsf

Une page JSF avec l'utilisation des EL utilise du code HTML dans lequel est mis des tags définis par les spécifications des JSF. Ce sont ces tags qui appellent les fonctions Java. Le code généré par les appels aux fonctions JSF est du XHTML 1.0.

Avec JSF, les EL s'utilisent avec le symbole #.

Tous les exemples ci-dessous utilisent le BeanPersonne.

Cycle de vie

Création du projet

Nécessite un projet de type Dynamic Web Project.

Exemple 1 - La base

index.xhtml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.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" />
<title>Insert title here</title>
</h:head>
<h:body>
  <p>
    <h:outputText value="15 est un nombre pair." rendered="#{15 % 2 == 0}" />
    <h:outputText value="15 est un nombre impair." rendered="#{15 % 2 == 1}" />
    <br />
    <h:outputText value="16 est un nombre pair." rendered="#{16 % 2 == 0}" />
    <h:outputText value="16 est un nombre impair." rendered="#{16 % 2 != 0}" />
  </p>
</h:body>
</html>

Rendu

15 est un nombre impair. 
16 est un nombre pair.

Exemple 2 - Utilisation d'un Bean

Dans le cas de Beans utilisés par JSF, la valeur par défaut définie lors de la définition de l'attribut ou par le constructeur est initialisé à 0 (pourquoi ????). Il est donc nécessaire de définir une fonction init avec l'annotation @PostConstruct.

L'exemple est présenté ici afin de garder une cohérence avec les autres pages (servlet, JSP et JSP+JSTL). Cependant, il n'est pas possible de définir dans JSF la valeur d'attribut sans intervention de l'utilisateur.

Il est indispensable que le nom de la classe définissant le Bean managé commence par une majuscule. En effet, lorsqu'on désignera la classe, il faudra taper com.llgc.BeanPersonne mais si l'on soit désigner la référence à un attribut, il faudra taper beanPersonne.taille avec une minuscule.

index2.xhtml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.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">
<f:view>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title>Insert title here</title>
</head>
<body>
  <p>
    La personne possède une taille de #{beanPersonne.taille} cm et
    <h:outputText value="a" rendered="#{beanPersonne.yeuxBleus}"/>
    <f:subview rendered="#{!beanPersonne.yeuxBleus}">n'a pas</f:subview>
    les yeux bleus.
  </p>
</body>
</f:view>
</html>

Code à ajouter au BeanPersonne :

  @PostConstruct
  public void init ()
  {
    setTaille (150);
    setYeuxBleus (true);
    setDiplomes (null);
  }

Rendu :

La personne possède une taille de 150 cm et a les yeux bleus.

Exemple 3 - Formulaire avec Bean global et session

index3.xhtml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.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">
<f:view>
  <h:head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Insert title here</title>
  </h:head>
  <h:body>
    <p>
      <h:outputText value="Valeur en cours de la taille : #{beanPersonne.taille}" />
    </p>
    <h:form>
      <span class="label_nav"><h:outputLabel value="taille" /></span>
      <h:inputText id="taille" required="true" value="#{beanPersonne.taille}" />
      <h:commandButton value="Validation" id="button" action="#{index3Action.action}" />
    </h:form>
    <h:message for="taille" style="color:red" />
  </h:body>
</f:view>
</html>

La valeur retour de la méthode action définie la page de redirection.

Index3Action.java
package com.llgc;
 
import javax.faces.bean.ManagedBean;
 
@ManagedBean
public class Index3Action
{
  public String action ()
  {
    return "Servlet3";
  }
}

Rendu du formulaire : Rendu du formulaire

Rendu de la réponse : Rendu de la réponse

Exemple 3b - avec validation des données

Dans le cas de JSF, l'utilisation de Javascript n'est plus obligatoire mais reste conseillé pour réduire la charge serveur.

L'utilisation de Javascript n'empêche pas la vérification coté serveur, une page est facilement traficable depuis les navigateurs.

BeanPersonneValidatorTaille
package com.llgc;
 
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
 
@FacesValidator("com.llgc.BeanPersonneValidatorTaille")
public class BeanPersonneValidatorTaille implements Validator
{
 
  @Override
  public void validate (FacesContext arg0, UIComponent arg1, Object arg2) throws ValidatorException
  {
    int taille;
    try
    {
      taille = Integer.parseInt (arg2.toString ());
    }
    catch (NumberFormatException e)
    {
      FacesMessage msg = new FacesMessage ("Échec lorg de la vérification de la taille.",
          arg2.toString () + " n'est pas un nombre.");
      msg.setSeverity (FacesMessage.SEVERITY_ERROR);
      throw new ValidatorException (msg);
    }
    if (taille < 30 || taille > 250)
    {
      FacesMessage msg = new FacesMessage ("Échec lorg de la vérification de la taille.",
          "La taille doit être comprise entre 30 et 250 cm.");
      msg.setSeverity (FacesMessage.SEVERITY_ERROR);
      throw new ValidatorException (msg);
    }
  }
}
index3b.xhtml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.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">
<f:view>
  <h:head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Insert title here</title>
  </h:head>
  <h:body>
    <h:form>
      <span class="label_nav"><h:outputLabel value="taille" /></span>
      <h:inputText id="taille" required="true" value="#{beanPersonne.taille}" converterMessage="Enter Only Digits">
        <f:validator validatorId="com.llgc.BeanPersonneValidatorTaille" />
      </h:inputText>
      <h:commandButton value="Validation" id="button"
        action="#{index3Action.action}" />
    </h:form>
    <h:message for="taille" style="color:red" />
  </h:body>
</f:view>
</html>

La balise h:message permet d'indiquer la position et éventuellement le style du message d'erreur. Si cette balise est absente, le message sera affiché à la position par défaut.

Rendu, échec de conversion en nombre : Rendu exo3, échec string en nombre

C'est bien le message Enter Only Digits qui est affiché et pas auie n'est pas un nombre.. Je pense que comme la propriété taille est un nombre, il doit y avoir une conversion implicite avant la soumission au Bean validateur.

Rendu, échec du domaine du nombre : Rendu exo3, échec domaine du nombre

Rendu, succès : Rendu exo3, succès

Validateurs implémentés par défaut

<f:validateDoubleRange minimum=“10.11” maximum=“10000.11” />

<f:validateLength minimum=“8” maximum=“16” />

<f:validateLongRange minimum=“20” maximum=“1000” />

<f:validateRequired /> : nécessite que la chaîne de caractère doit être non-vide.

<f:validateRegex pattern= “^[_a-z0-9-]+(\\.[_a-z0-9-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)+$”>

Exemple 3c - avec convertisseur des données

BeanPersonneConvertisseurYeuxBleus.java
package com.llgc;
 
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.convert.FacesConverter;
 
@FacesConverter("com.llgc.BeanPersonneConvertisseurYeuxBleus")
public class BeanPersonneConvertisseurYeuxBleus implements Converter
{
  @Override
  public Object getAsObject (FacesContext arg0, UIComponent arg1, String arg2)
  {
    if (arg2.equals ("non"))
    {
      return new Boolean (false);
    }
    if (arg2.equals ("oui"))
    {
      return new Boolean (false);
    }
    throw new ConverterException (new FacesMessage ("Échec de la convertion en boolean", arg2 + " ne vaut ni oui, ni non."));
  }
 
  @Override
  public String getAsString (FacesContext arg0, UIComponent arg1, Object arg2)
  {
    if (arg2 instanceof Boolean)
    {
      if ((Boolean)arg2)
      {
        return "non";
      }
      else
      {
        return "oui";
      }
    }
 
    throw new ConverterException (new FacesMessage ("Échec de la convertion en boolean", arg2.toString () + " ne vaut ni oui, ni non."));
  }
}
index3c.xhtml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.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">
<f:view>
  <h:head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Insert title here</title>
  </h:head>
  <h:body>
    <h:form>
      <span class="label_nav"><h:outputLabel value="yeuxBleus (oui ou non)" /></span>
      <h:inputText id="taille" required="true" value="#{beanPersonne.yeuxBleus}">
        <f:converter converterId="com.llgc.BeanPersonneConvertisseurYeuxBleus" />
      </h:inputText>
      <h:commandButton value="Validation" id="button" action="#{index3Action.action}" />
    </h:form>
    <h:message for="taille" style="color:red" />
  </h:body>
</f:view>
</html>

Rendu avec succès :

Rendu sans succès :

Convertisseurs implémentés par défaut

<f:convertDateTime pattern=“yyyy-MM-dd HH:mm:ss.SSS Z” />

<f:convertNumber type=“percent” />

<f:convertNumber pattern=“#0.000” />

Exemple 4 - context-param et init-param

Ajout de trois context-param.

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1">
  <display-name>EL</display-name>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
  </servlet>
  <context-param>
    <param-name>user</param-name>
    <param-value>utilisateur</param-value>
  </context-param>
  <context-param>
    <param-name>password</param-name>
    <param-value>mot de passe</param-value>
  </context-param>
  <context-param>
    <param-name>driver</param-name>
    <param-value>com.mysql.jdbc.Driver</param-value>
  </context-param>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
  </servlet-mapping></web-app>
index4.xhtml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.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">
<f:view>
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Insert title here</title>
</h:head>
<h:body>
  <p>
    nom : ${initParam['user']}<br />
    pass : ${initParam['password']}<br />
    driver : ${initParam['driver']}<br />
  </p>
</h:body>
</f:view>
</html>

Les init-param ne sont plus du tout accessibles en JSF, ce qui démontre bien la volonté de séparer la représentation visuelle (.xhtml) des servlets.

Rendu :

nom : utilisateur
pass : mot de passe
driver : com.mysql.jdbc.Driver

Exemple 5 - Cookies

Il n'est pas possible de modifier les cookies sans passer par des commandes Java. Il est donc nécessaire de passer par l'intermédiaire d'une servlet.

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
  <display-name>EL</display-name>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
  </servlet-mapping>
</web-app>

Il est important de noter la présence de /faces au début de l'URL de redirection /faces/indexjsf5.xhtml. Le fichier se trouve bien dans le dossier WebContent et non pas dans un hypothétique dossier WebContent/faces. Sans cette dénomination (conformément au fichier web.xml), les tags JSF ne seraient pas interprétés. Par contre, je n'ai pas réussi mettre le fichier indexjsf5.xhtml dans le dossier WEB-INF et y accéder via /faces/WEB-INF/indexjsf5.xhtml. La solution peut être de remplacer dans web.xml, <url-pattern>/faces/*</url-pattern> par <url-pattern>*.xhtml</url-pattern> et d'utiliser le lien de redirection /WEB-INF/indexjsf5.xhtml.

ServletJSF5.java
package com.llgc;
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 * Servlet implementation class ServletJSF5
 */
@WebServlet ("/ServletJSF5")
public class ServletJSF5 extends HttpServlet
{
  /**
   * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
   *      response)
   */
  protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
  {
    response.setCharacterEncoding ("UTF-8");
    String value = getCookie (request.getCookies (), "compteur");
    response.setContentType ("text/html");
    int compteur = 0;
    if (value != null)
    {
      compteur = Integer.parseInt (value);
    }
    compteur++;
    Cookie c = new Cookie ("compteur", "" + compteur);
    c.setMaxAge (3600);
    response.addCookie (c);
    this.getServletContext ().getRequestDispatcher ("/faces/indexjsf5.xhtml").forward (request, response);
  }
 
  /**
   * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
   *      response)
   */
  protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
  {
    doGet (request, response);
  }
 
  // Renvoie la valeur d'un cookie.
  protected static String getCookie (Cookie[] cookies, String cookieName)
  {
    if (cookies == null)
    {
      return null;
    }
    for (int i = 0; i < cookies.length; i++)
    {
      if (cookieName.equalsIgnoreCase (cookies[i].getName ()))
      {
        return cookies[i].getValue ();
      }
    }
    return null;
  }
}
indexjsf5.xhtml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.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" />
<title>Insert title here</title>
</h:head>
<h:body>
  <p>
    <h:outputText rendered="#{cookie.compteur != null}" value="compteur : #{cookie.compteur.value}" />
    <h:outputText rendered="#{cookie.compteur == null}" value="Pas de cookie, allez cuisiner !!!" />
  </p>
</h:body>
</html>

Rendu 1 :

Pas de cookie, allez cuisiner !!!

Rendu 2 :

compteur : 1

Exemple 6 - Affichage d'une liste dans un tableau

La liste est générée par une classe Java Liste6 et affiche un type BeanPersonne.

index6.xhtml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.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"
  xmlns:ui="http://java.sun.com/jsf/facelets">
<f:view>
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Insert title here</title>
</h:head>
<h:body>
  <table border="1">
    <tr>
      <td>Taille</td>
      <td>Yeux bleus</td>
    </tr>
    <ui:repeat var="perso" value="${liste6.getListePersonne ()}">
      <tr>
        <td>${perso.taille}</td>
        <td>${perso.yeuxBleus}</td>
      </tr>
    </ui:repeat>
  </table>
</h:body>
</f:view>
</html>

Rendu : Rendu exemple 6

index6-2.xhtml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.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"
  xmlns:ui="http://java.sun.com/jsf/facelets">
<f:view>
  <h:head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Insert title here</title>
    <h:outputStylesheet library="css" name="table-style.css" />
  </h:head>
  <h:body>
    <h:dataTable value="#{liste6.getListePersonne ()}" var="perso"
      styleClass="order-table" headerClass="order-table-header"
      rowClasses="order-table-odd-row,order-table-even-row">
      <h:column>
        <f:facet name="header">Taille</f:facet>
        #{perso.taille}
      </h:column>
      <h:column>
        <f:facet name="header">Yeux bleus</f:facet>
        #{perso.yeuxBleus}
      </h:column>
    </h:dataTable>
  </h:body>
</f:view>
</html>

Le fichier .css (JSF 2.0 + JDBC integration example Archive du 29/08/2012 le 26/04/2020) doit être placé dans le dossier WebContent\resources\css.

table-style.css
.order-table{   
  border-collapse:collapse;
}
 
.order-table-header{
  text-align:center;
  background:none repeat scroll 0 0 #E5E5E5;
  border-bottom:1px solid #BBBBBB;
  padding:16px;
}
 
.order-table-odd-row{
  text-align:center;
  background:none repeat scroll 0 0 #FFFFFFF;
  border-top:1px solid #BBBBBB;
}
 
.order-table-even-row{
  text-align:center;
  background:none repeat scroll 0 0 #F9F9F9;
  border-top:1px solid #BBBBBB;
}

Rendu : Rendu exemple 6

Exemple 7 - HTML5

La génération de page au format HTML5 nécessite l'utilisation des JSF 2.2 avec JavaEE 7 et Tomcat 8. Creating HTML5 Pages in JavaServer Faces 2.2 Archive le 26/04/2020.

Faire les modifications suivantes :

Remplacerpar
<html><html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:p="http://xmlns.jcp.org/jsf/passthrough">
<head></head><h:head></h:head>
<body></body><h:body></h:body>
<script src="resources/js/story-page.js" type="text/javascript"></script><h:outputScript library="js" name="story-page.js" target="body" />
<link href="resources/styles.css" rel="stylesheet" type="text/css" /><h:outputStylesheet name="styles.css" />
<img style="float:left;" draggable="true" ondragstart="drag(event);" data-sticker="robot.png" src="resources/stickers/robot.png"><h:graphicImage name="stickers/robot.png" style="float:left" p:draggable="true" p:ondragstart="drag(event);" p:data-sticker="robot.png" />
<div id="content"><h:panelGroup layout="block" id="content">
helloworld/web/java/jsf.txt · Dernière modification : 2020/05/10 23:55 de root