Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente |
helloworld:web:java:jsf [2015/08/10 12:12] – Ajout de l'exemple 5 - cookies root | helloworld:web:java:jsf [2020/05/10 23:55] (Version actuelle) – Suppression de la taille par défaut pour les images root |
---|
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''. | 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''. |
| |
<note>Avec ''JSF'', les ''EL'' s'utilisent avec le symbole ''#''.</note> | <WRAP center round info 60%> |
| Avec ''JSF'', les ''EL'' s'utilisent avec le symbole ''#''. |
| </WRAP> |
| |
<note>Tous les exemples ci-dessous utilisent le [[helloworld:design_pattern:bean:java|BeanPersonne]].</note> | <WRAP center round info 60%> |
| Tous les exemples ci-dessous utilisent le [[helloworld:design_pattern:bean:java|BeanPersonne]]. |
| </WRAP> |
| |
=====Cycle de vie===== | =====Cycle de vie===== |
{{:helloworld:web:java:jsf:cycle.png?500|Cycle de vie}} | {{:helloworld:web:java:jsf:cycle.png|Cycle de vie}} |
| |
[[http://bet-nafet.ma/expert/Java/Tutoriels/J2EE/JSFAvancees.html|Source]] {{:helloworld:web:java:jsf:javaserver_faces.html.maff|Archive}} | <del>[[http://bet-nafet.ma/expert/Java/Tutoriels/J2EE/JSFAvancees.html|JavaServer Faces - techniques avancées]]</del> {{ :helloworld:web:java:jsf:javaserver_faces_2020-04-26_7_23_41_pm_.html |Archive le 2015}} |
| |
| {{:helloworld:web:java:jsf:jeett_dt_016.png|Cycle de vie}} |
| |
| [[http://docs.oracle.com/javaee/7/tutorial/jsf-intro006.htm#BNAQQ|The Lifecycle of a JavaServer Faces Application]], {{ lang:java:jeett.pdf |The Java EE Tutorial}} |
=====Création du projet===== | =====Création du projet===== |
Nécessite un projet de type [[eclipse:howto:dwp|Dynamic Web Project]]. | Nécessite un projet de type [[ide:eclipse:projet|Dynamic Web Project]]. |
| |
=====Exemple 1 - La base===== | =====Exemple 1 - La base===== |
| |
=====Exemple 2 - Utilisation d'un Bean===== | =====Exemple 2 - Utilisation d'un Bean===== |
<note important>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''.</note> | <WRAP center round important 60%> |
| 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''. |
| </WRAP> |
| |
L'exemple est présenté ici afin de garder une cohérence avec les autres pages ([[helloworld:web:java:servlet|servlet]], [[jsp|JSP]] et [[jsp_jstl_el|JSP+JSTL]]). Cependant, il n'est pas possible de définir dans ''JSF'' la valeur d'attribut sans intervention de l'utilisateur. | L'exemple est présenté ici afin de garder une cohérence avec les autres pages ([[helloworld:web:java:servlet|servlet]], [[jsp|JSP]] et [[jsp_jstl_el|JSP+JSTL]]). Cependant, il n'est pas possible de définir dans ''JSF'' la valeur d'attribut sans intervention de l'utilisateur. |
| |
<note important>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.</note> | <WRAP center round important 60%> |
| 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. |
| </WRAP> |
| |
<file xml index2.xhtml> | <file xml index2.xhtml> |
</html> | </html> |
</file> | </file> |
<note>La valeur retour de la méthode ''action'' définie la page de redirection.</note> | |
| <WRAP center round info 60%> |
| La valeur retour de la méthode ''action'' définie la page de redirection. |
| </WRAP> |
<file java Index3Action.java> | <file java Index3Action.java> |
package com.llgc; | package com.llgc; |
| |
Rendu du formulaire : | Rendu du formulaire : |
{{:helloworld:web:java:servlet:rendu_ex3-1.png?310|Rendu du formulaire}} | {{:helloworld:web:java:servlet:rendu_ex3-1.png|Rendu du formulaire}} |
| |
Rendu de la réponse : | Rendu de la réponse : |
{{:helloworld:web:java:servlet:rendu_ex3-2.png?310|Rendu de la réponse}} | {{:helloworld:web:java:servlet:rendu_ex3-2.png|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. |
| <WRAP center round important 60%> |
| L'utilisation de ''Javascript'' n'empêche pas la vérification coté serveur, une page est facilement traficable depuis les navigateurs. |
| </WRAP> |
| |
| <file java 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); |
| } |
| } |
| } |
| </file> |
| |
| <file xml 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> |
| </file> |
| |
| <WRAP center round info 60%> |
| 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. |
| </WRAP> |
| |
| Rendu, échec de conversion en nombre : |
| {{:helloworld:web:java:jsf:rendu_3b_1.png|Rendu exo3, échec string en nombre}} |
| <WRAP center round info 60%> |
| 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. |
| </WRAP> |
| |
| Rendu, échec du domaine du nombre : |
| {{:helloworld:web:java:jsf:rendu_3b_2.png|Rendu exo3, échec domaine du nombre}} |
| |
| Rendu, succès : |
| {{:helloworld:web:java:jsf:rendu_3b_3.png|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===== |
| <file java 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.")); |
| } |
| } |
| </file> |
| |
| <file xml 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> |
| </file> |
| |
| Rendu avec succès : |
| {{:helloworld:web:java:jsf:rendu_3c_1.png|}} |
| |
| Rendu sans succès : |
| {{:helloworld:web:java:jsf:rendu_3c_2.png|}} |
| |
| ====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===== | =====Exemple 4 - context-param et init-param===== |
</html> | </html> |
</file> | </file> |
<note important>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''.</note> | <WRAP center round important 60%> |
| 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''. |
| </WRAP> |
| |
Rendu : | Rendu : |
</file> | </file> |
| |
<note important>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''.</note> | <WRAP center round important 60%> |
| 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''. |
| </WRAP> |
| |
<file java ServletJSF5.java> | <file java ServletJSF5.java> |
compteur : 1 | compteur : 1 |
</code> | </code> |
| |
| =====Exemple 6 - Affichage d'une liste dans un tableau===== |
| La liste est générée par une classe Java [[helloworld:web:java:servlet#exemple_6_-_affichage_d_une_liste_dans_un_tableau|Liste6]] et affiche un type [[helloworld:design_pattern:bean:java#cas_general|BeanPersonne]]. |
| |
| <file xml 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> |
| </file> |
| |
| Rendu : |
| {{:helloworld:web:java:servlet:rendu_ex6.png|Rendu exemple 6}} |
| |
| <file xml 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> |
| </file> |
| |
| Le fichier ''.css'' ([[http://www.mkyong.com/jsf2/jsf-2-0-jdbc-integration-example/|JSF 2.0 + JDBC integration example]] {{ :helloworld:web:java:jsf:jsf_2.0_jdbc_integration_example_mkyong.com_2020-04-26_7_39_17_pm_.html |Archive du 29/08/2012 le 26/04/2020}}) doit être placé dans le dossier ''WebContent\resources\css''. |
| <file 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; |
| } |
| </file> |
| Rendu : |
| {{:helloworld:web:java:jsf:rendu_ex6-2.png|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. [[https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/HTML5-JSF/html5jsf.html|Creating HTML5 Pages in JavaServer Faces 2.2]] {{ :helloworld:web:java:jsf:java_ee7_creating_html5_pages_using_jsf_2.2_2020-04-26_7_41_06_pm_.html |Archive le 26/04/2020}}. |
| |
| Faire les modifications suivantes : |
| |
| ^Remplacer^par^ |
| |''<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">%%''| |
| |