Question

Il y a quelques choses que j'ai du mal à comprendre en ce qui concerne le développement de composants personnalisés dans JSF.Pour les besoins de ces questions, vous pouvez supposer que tous les contrôles personnalisés utilisent des liaisons/expressions de valeurs (et non des liaisons littérales), mais je suis également intéressé par des explications à leur sujet.

  1. Où puis-je définir la valeur de la liaison de valeur ?Est-ce censé se produire en décodage ?Ou decode devrait-il faire autre chose et ensuite définir la valeur dans encodeBegin ?
  2. Lire à partir de la liaison de valeur - Quand puis-je lire les données de la liaison de valeur par rapport à.le lire à partir de la valeur soumise et le mettre dans la liaison de valeur ?
  3. Quand les auditeurs d'action sur les formulaires sont-ils appelés par rapport à tout cela ?Les pages du cycle de vie JSF mentionnent toutes des événements qui se produisent à différentes étapes, mais je ne comprends pas très bien quand un simple écouteur d'un bouton de commande est appelé.

J'ai essayé quelques combinaisons, mais je me retrouve toujours avec des bogues difficiles à trouver qui, je pense, proviennent de malentendus fondamentaux sur le cycle de vie des événements.

Était-ce utile?

La solution

Il y a un assez bon diagramme dans le Spécification JSF qui montre le cycle de vie de la demande - essentiel pour comprendre ce genre de choses.

Les étapes sont les suivantes :

  • Restaurer la vue.L'arborescence UIComponent est reconstruite.
  • Appliquer les valeurs de requête.Les composants modifiables doivent implémenter EditableValueHolder.Cette phase parcourt l'arborescence des composants et appelle le processusDécodes méthodes.Si le composant n'est pas quelque chose de complexe comme un UIData, il ne fera pas grand-chose sauf appeler le sien décoder méthode.Le décoder la méthode ne fait pas grand chose sauf trouver son moteur de rendu et invoque son décoder méthode, se passant comme argument.C'est le travail du moteur de rendu d'obtenir toute valeur soumise et de la définir via setSubmittelValue.
  • Validations des processus.Cette phase appelle ProcessValidateurs qui appellera valider.Le valider La méthode prend la valeur soumise, la convertit avec n'importe quel convertisseur, la valide avec n'importe quel validateur et (en supposant que les données réussissent ces tests) appelle définirValeur.Cela stockera la valeur en tant que variable locale.Bien que cette variable locale ne soit pas nulle, elle sera renvoyée et non la valeur de la liaison de valeur pour tout appel à obtenirValeur.
  • Mettre à jour les valeurs du modèle.Cette phase appelle processusMises à jour.Dans un composant d'entrée, cela appellera mettre à jour le modèle qui obtiendra le ExpressionValeur et appelez-le pour définir la valeur sur le modèle.
  • Appeler une application.Les écouteurs d'événements de bouton, etc. seront invoqués ici (tout comme la navigation si ma mémoire est bonne).
  • Rendre la réponse.L'arborescence est rendue via les moteurs de rendu et l'état est enregistré.
  • Si l'une de ces phases échoue (par ex.une valeur n'est pas valide), le cycle de vie passe à la réponse de rendu.
  • Divers événements peuvent être déclenchés après la plupart de ces phases, en appelant des écouteurs le cas échéant (comme des écouteurs de changement de valeur après les validations de processus).

Il s'agit d'une version quelque peu simplifiée des événements.Reportez-vous aux spécifications pour plus de détails.

Je me demande pourquoi vous écrivez votre propre UIComponent.Il s'agit d'une tâche non triviale et une compréhension approfondie de l'architecture JSF est nécessaire pour bien faire les choses.Si vous avez besoin d'un contrôle personnalisé, il est préférable de créer un contrôle concret qui étend un UIComponent existant (comme le fait HtmlInputText) avec un moteur de rendu équivalent.

Si la contamination n'est pas un problème, il existe une implémentation JSF open source sous la forme d'Apache MyFaces.

Autres conseils

Les écouteurs d'action, comme pour un Bouton de commande, sont appelés pendant la Appeler une application phase, qui est la dernière phase avant la finale Rendre la réponse phase.Ceci est montré dans Le cycle de vie JSF - figure 1.

C'est le seul cadre que j'ai jamais utilisé où la création de composants est un processus complexe profond comme celui-ci.Aucun des autres cadres Web (que ce soit dans le monde .NET ou non) ne rend cela si douloureux, ce qui est complètement inexplicable pour moi.

Certaines des décisions de conception derrière JSF commencent à prendre un peu plus de sens si l'on considère les objectifs.JSF a été conçu pour être utilisé : il expose de nombreuses métadonnées pour les IDE.JSF n'est pas un framework Web - c'est un MVP framework qui peut être utilisé comme framework web.JSF est hautement extensible et configurable : vous pouvez remplacer 90 % de l'implémentation pour chaque application.

La plupart de ces éléments ne font que compliquer votre travail si tout ce que vous voulez faire est d'insérer un contrôle HTML supplémentaire.

Le composant est une composition de plusieurs composants de base InputText (et d'autres), BTW.

Je suppose que les fragments de page basés sur des outils/includes JSP ne répondent pas à vos besoins.

J'envisagerais d'utiliser votre UIComponentELTag.createComponent pour créer un contrôle composite avec une base UIPanel et créer tous ses enfants à partir d'implémentations existantes.(Je suppose que vous utilisez des JSP/taglibs et que vous faites quelques autres suppositions.) Vous voudriez probablement un moteur de rendu personnalisé si aucun des moteurs de rendu UIPanel existants n'a fait le travail, mais les moteurs de rendu sont faciles.

Le meilleur article que j'ai trouvé est Écriture de composants Jsf, comme pour 2 où puis-je lire la valeur d'une valeur de valeur dans votre composant, vous avez un getteur qui ressemble à ceci


public String getBar() {  
     if (null != this.bar) {  
         return this.bar ;  
     }  
     ValueBinding _vb = getValueBinding("bar");  
     return (_vb != null) ? (bar) _vb.getValue(getFacesContext()) : null;  
}
  

comment cela est-il entré dans getValueBinding ?Dans votre méthode setProperties de classe de balises

  if (bar!= null) {  
         if (isValueReference(bar)) {  
             ValueBinding vb = Util.getValueBinding(bar);  
             foo.setValueBinding("bar", vb);  
         } else {  
             throw new IllegalStateException("The value for 'bar' must be a ValueBinding.");  
         }  
     }  
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top