JSF/Facelets

Cette page a été rédigée il y a fort fort longtemps, et n'a pas tellement été mise à jour.

 

Vous savez, moi je ne crois pas qu'il y ait de bonne ou de mauvaise page. Moi, si je devais résumer mon wiki aujourd'hui avec vous, je dirais que c'est d'abord des rencontres. Des gens qui m'ont tendu la main, peut-être à un moment où je ne pouvais pas, où j'étais seul chez moi. Et c'est assez curieux de se dire que les hasards, les rencontres forgent une destinée... Parce que quand on a le goût de la chose, quand on a le goût de la chose bien faite, le beau geste, parfois on ne trouve pas l'interlocuteur en face je dirais, le miroir qui vous aide à avancer. Alors ça n'est pas mon cas, comme je disais là, puisque moi au contraire, j'ai pu ; et je dis merci au wiki, je lui dis merci, je chante le wiki, je danse le wiki... je ne suis qu'amour ! Et finalement, quand des gens me disent « Mais comment fais-tu pour avoir cette humanité ? », je leur réponds très simplement que c'est ce goût de l'amour, ce goût donc qui m'a poussé aujourd'hui à entreprendre une construction logicielle... mais demain qui sait ? Peut-être simplement à me mettre au service de la communauté, à faire le don, le don de soi.

Cet article décrit comment intégrer les tags du framework Shale Validator avec Facelets. Il s’agit notamment d’indiquer à Facelets comment interpréter les tags <s:commonsValidator>, <s:validatorVar> et <s:validatorScript>. Par exemple:

  <s:commonsValidator type="minlength" arg="#{bundle['login.login']}" server="true" client="true" minlength="4"/>
  <s:commonsValidator type="mask" arg="#{bundle['login.login']}" server="true" client="true">
    <s:validatorVar name="mask" value="^[a-zA-Z0-9]*$"/>
  </s:commonsValidator>
  <s:validatorScript functionName="validateForm"/>

Handler pour CommonsValidator

Un handler spécifique facelets doit être redéfini afin de pouvoir prendre en compte les variables de commons validator renseignées avec le tag <s:validatorVar>. L’exemple ci-dessous permet de traiter uniquement le cas de la variable "mask", mais la classe handler peut être facilement étendue afin de prendre en compte d’autres variables. A noter que ce handler n’hérite pas de ValidatorHandler, car précisément, la méthode apply() (méthode finale) de ValidatorHandler ne propage pas le traitement aux handlers fils. Le code ci-dessous est donc une copie de la classe ValidatorHandler qui permet de propager le traitement au handler du tag <s:validatorVar>.

 package fr.icodem.facelets.shale;

 public class CommonsValidatorHandler extends MetaTagHandler {

   //  validatorVar tag 
   // set mask variable on commons validator
   public static class MaskMetadata extends Metadata {
     public void applyMetadata(FaceletContext ctx, Object instance) {
       ValueExpression var = ctx.getVariableMapper().resolveVariable("mask");
       if (var != null) {
         String expression = var.getExpressionString();
         CommonsValidator v = (CommonsValidator)instance;
         v.setMask(expression);
       }
     }
   }

   private final TagAttribute binding;

   private String validatorId = "org.apache.shale.CommonsValidator";

   public CommonsValidatorHandler(TagConfig config) {
     super(config);
     this.binding = this.getAttribute("binding");
   }

   public final void apply(FaceletContext ctx, UIComponent parent)
          throws IOException, FacesException, FaceletException, ELException {

     if (parent == null || !(parent instanceof EditableValueHolder)) {
          throw new TagException(this.tag,
                   "Parent not an instance of EditableValueHolder: " + parent);
     }

     //  validatorVar tag 
     // get validator vars
     if (nextHandler != null) nextHandler.apply(ctx, parent);

     // only process if it's been created
     if (parent.getParent() == null) {
       // cast to a ValueHolder
       EditableValueHolder evh = (EditableValueHolder) parent;
       ValueExpression ve = null;
       Validator v = null;
       if (this.binding != null) {
         ve = this.binding.getValueExpression(ctx, Validator.class);
         v = (Validator) ve.getValue(ctx);
       }
       if (v == null) {
         v = this.createValidator(ctx);
         if (ve != null) {
           ve.setValue(ctx, v);
         }
       }
       if (v == null) {
         throw new TagException(this.tag, "No Validator was created");
       }
       this.setAttributes(ctx, v);
       evh.addValidator(v);
     }
   }

   protected Validator createValidator(FaceletContext ctx) {
     if (this.validatorId == null) {
       throw new TagException(
                   this.tag,
                   "Default behavior invoked of requiring a validator-id " +
                   "passed in the constructor, must override ValidateHandler(ValidatorConfig)");
       }
       return ctx.getFacesContext().getApplication().createValidator(
               this.validatorId);
   }

   //  commons validator tag 
   // create specific rule set
   @SuppressWarnings("unchecked")
   protected MetaRuleset createMetaRuleset(Class type) {
     MetaRuleset  metaRuleset = super.createMetaRuleset(type)
                                             .ignore("binding")
                                             .alias("minlength", "minLength")
                                             .alias("maxlength", "maxLength")
                                             .add(new MaskMetadata());

     return metaRuleset;
   }
 }

Handler pour ValidatorVar

Ce handler permet de placer dans le context de Facelets les variables renseignées avec le tag <s:validatorVar>.

 public class ValidatorVarHandler extends TagHandler {

   // possible attributes
   private final TagAttribute name;
   private final TagAttribute value;

   public ValidatorVarHandler(TagConfig config) {
     super(config);
     this.name = getRequiredAttribute("name");
     this.value = getRequiredAttribute("value");
   }

   @Override
   public void apply(FaceletContext ctx, UIComponent parent)
              throws IOException, FacesException, ELException {
     String nameStr = this.name.getValue(ctx);
     ValueExpression veObj = this.value.getValueExpression(ctx, Object.class);
     ctx.getVariableMapper().setVariable(nameStr, veObj);
   }
 }

Fichier taglib Facelets pour Shale

Les handlers définis précédemment sont utilisés dans le fichier shale.taglib.xml :

 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE facelet-taglib PUBLIC
   "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
   "http://java.sun.com/dtd/facelet-taglib_1_0.dtd">

 <facelet-taglib>
   <namespace>http://shale.apache.org/core</namespace>
     <tag>
       <tag-name>commonsValidator</tag-name>
       <handler-class>org.librairie.web.CommonsValidatorHandler</handler-class>
   </tag>
   <tag>
     <tag-name>validatorScript</tag-name>
     <component>
       <component-type>org.apache.shale.ValidatorScript</component-type>
     </component>
   </tag>
   <tag>
     <tag-name>validatorVar</tag-name>
     <handler-class>org.librairie.web.ValidatorVarHandler</handler-class>
   </tag>
 </facelet-taglib>