2010-11-26 13 views
4

Tenir compte d'un UIComponent personnalisé (à des fins de test uniquement):JSF 2.0: Quand est-ce que encodeAll est appelé et quand encodeBegin est appelé?

public class UITest extends UIComponentBase { 

    @Override 
    public void encodeBegin(FacesContext context) throws IOException { 
     System.out.println("encodeBegin"); 
    } 

    @Override 
    public void encodeAll(FacesContext context) throws IOException { 
     System.out.println("encodeAll"); 
    } 

} 

Lorsque je l'ajoute à la page à l'intérieur d'une pièce composite, la méthode encodeBegin() est appelée. Cependant, lorsque vous l'ajoutez à la page en dehors d'un composant composite, la méthode encodeAll() est appelée à la place.

L'ajouter à l'intérieur d'autres UIComponents ne fait aucune différence, seul le wrapper de composant composite semble changer le comportement.

Impossible de trouver l'information pourquoi c'est ainsi? Un lien vers la spécification?

Répondre

4

La spécification est vraiment désordre dans ce cas, en déclarant que:. « Ces méthodes sont appelées au cours de la phase de réponse rendu du cycle de vie de traitement des demandes encodeAll() sera à ce composant et tous ses enfants et facettes qui renvoient true de isRendered() pour être rendu, indépendamment de de la valeur de la valeur de retour getRendersChildren() encodeBegin(), encodeChildren(), et encodeEnd() ont la responsabilité de créer les données de réponse pour le début de ce composant, cette enfants du composant (uniquement appelés si la propriété rendersChildren de ce composant est true) et la fin de ce composant, respectivement. "

Cependant, cela semble être un mélange de nouvelles et anciennes fonctionnalités, où les nouvelles fonctionnalités (encodeAll) semble être incomplète à certains égards:

J'ai essayé les éléments suivants:

A) Appeler la composants directement dans la page (pas emballage)

  1. étendre UIComponentBase (ou une autre classe UIComponent tels que UIInput, UIOutput .. etc), déclarerons comme étiquette, et l'utiliser dans l'interface utilisateur. Dans ce cas, la méthode encodeAll est appelée si elle est présente (surchargée), sinon les méthodes encodeBegin et encodeEnd seront appelées !!

  2. Une autre chose à noter est que vous pouvez créer un Renderer personnalisé pour le composant, afin de pouvoir séparer la logique de rendu du comportement. (en créant une autre classe qui étend Renderer, et en l'annotant avec @FacesRenderer) C'est là que ça devient intéressant; Renderer définit seulement encodeBegin, encodeChildren et encodeEnd (sans mention de encodeAll). Maintenant, la logique semble aller à peu près comme ceci: si (encodeAll est présent) encodeAll est appelée (et le moteur de rendu est ignoré!) sinon if (l'un des encodageBegin, Children, ou fin existe dans la classe qui étend UIComponent) appelle la méthode qui a été trouvée dans ce composant sinon si (encodeBegin, enfants ou fin existe dans la classe qui étend Renderer) appelle la méthode correspondante qui a été trouvée.

Cela signifie donc que la mise en œuvre encodeAll (ou encodeBegin .. etc) dans la classe UIComponent provoque l'extension à ignorer renderer!

B) Emballage du composant (cc: mise en œuvre .. etc)

Dans ce cas, la même chose que ci-dessus, sauf que encodeAll n'a pas été appelé dans tous les cas, peu importe ce que je faisais. Conclusion: Il semble que l'encodage est une sorte de nouvelle fonctionnalité (ou raccourci) pour implémenter le code de rendu, et il semble que l'implémentation cc: ait un bug dans ce cas (elle ne cherche pas encodeAll).

J'espère que c'est au moins d'une certaine valeur pour vous, malheureusement, je ne peux pas fournir une réponse plus complète. :

+0

Cela ressemble beaucoup à mes découvertes, car le comportement est un peu compliqué, voire bizarre (en comparant un composant à l'intérieur et à l'extérieur d'un wrapper), je pense que je le ferai Soyez sûr de passer du temps à inspecter cela et bienvenue à SO! :) –

+0

Il semble y avoir un bug enregistré pour cela [ici] (http://java.net/jira/browse/JAVASERVERFACES-1875). – Lucas