Quand utiliser <ui: include>, des fichiers de balises, des composants composites et / ou des composants personnalisés?

102

J'ai récemment commencé à utiliser JSF 2.0 avec Facelets et j'ai été intrigué par les nouveaux composants composites connaissant les <ui:include>techniques existantes et d'autres techniques de modélisation proposées par Facelets 1.x.

Quelle est la différence entre ces approches? Fonctionnellement, ils semblent offrir à peu près la même chose: <ui:param>vs <cc:attribute>, <ui:insert>+ <ui:define>vs fichiers de balises, réutilisation des modèles existants. Y a-t-il autre chose que la syntaxe et la spécification d'interface claire dans le cas de composants composites? Les performances pourraient-elles différer?

mrembisz
la source

Réponses:

176

Quelle est la différence entre ces approches?

Modèles de facettes

Utilisez Facelet modèles (comme dans <ui:composition>, <ui:include>et <ui:decorate>) si vous voulez diviser les principaux fragments de mise en page dans les modèles reuseable. Par exemple, en-tête, menu, contenu, pied de page, etc.

Exemples:

Fichiers de balises Facelet

Utilisez des fichiers de balises Facelet si vous souhaitez disposer d'un groupe de composants réutilisable afin d'éviter / minimiser la duplication de code. Par exemple, un groupe de composants étiquette + entrée + message. La principale différence avec les composants composites est que la sortie d'un fichier de balises Facelet ne représente pas un seul UIComponentet peut dans certaines circonstances être la seule solution lorsqu'un composant composite ne suffit pas. Généralement, avoir un <ui:include>avec un ou plusieurs <ui:param>qui transmet une propriété de bean géré (et donc pas une valeur codée en dur) est un signal que le fichier d'inclusion peut mieux être un fichier de balise.

Exemples:

Composants composites

Utilisez des composants composites si vous souhaitez créer une personnalisation unique et réutilisable UIComponentavec une seule responsabilité à l'aide de XML pur. Un tel composant composite se compose généralement d'un ensemble de composants existants et / ou HTML et est rendu physiquement en tant que composant unique et est censé être lié à une seule propriété de bean. Par exemple, un composant qui représente une java.util.Datepropriété unique par 3 <h:selectOneMenu>composants dépendants , ou un composant qui combine <p:fileUpload>et <p:imageCropper>en un seul <my:uploadAndCropImage>référençant une seule com.example.Imageentité personnalisée en tant que propriété.

Exemples:

Composants personnalisés

Utilisez un composant personnalisé chaque fois que la fonctionnalité ne peut pas être obtenue avec des fichiers de balises Facelet ou des composants composites, en raison du manque de prise en charge dans l'ensemble de composants standard / disponible. Des exemples peuvent être trouvés partout dans le code source des bibliothèques de composants open source telles que PrimeFaces et OmniFaces .

Gestionnaires de balises

Lorsque vous souhaitez contrôler la construction de l'arborescence des composants JSF au lieu du rendu de la sortie HTML, vous devez utiliser un gestionnaire de balises au lieu d'un composant.

Exemples:

Exemples de projets

Voici quelques exemples de projets qui utilisent toutes les techniques mentionnées ci-dessus.


Les performances pourraient-elles différer?

Techniquement, le problème de performance est négligeable. Le choix doit être fait en fonction des exigences fonctionnelles concrètes et du degré final d'abstraction, de réutilisabilité et de maintenabilité de la mise en œuvre. Chaque approche a ses propres objectifs et limites bien définis.

Les composants composites ont cependant une surcharge importante lors de la création / restauration de la vue (en particulier: lors de l'enregistrement / de la restauration de l'état de la vue). Et, dans les anciennes versions de Mojarra, les composants composites avaient des problèmes de performances avec l'attribution de valeurs par défaut, ce problème est déjà résolu depuis la version 2.1.13. De plus, Mojarra avait une fuite de mémoire quand a <cc:attribute method-signature>est utilisé pour les expressions de méthode, fondamentalement, tout l'arborescence des composants est re-référencée dans la session HTTP, ce problème est corrigé depuis 2.1.29 / 2.2.8. La fuite de mémoire peut être contournée dans les anciennes versions 2.1 comme ci-dessous:

<context-param>
    <param-name>com.sun.faces.serializeServerState</param-name>
    <param-value>true</param-value>
</context-param>

Ou dans les anciennes versions 2.2 comme ci-dessous:

<context-param>
    <param-name>javax.faces.SERIALIZE_SERVER_STATE</param-name>
    <param-value>true</param-value>
</context-param>

Pourtant, lorsque vous avez relativement "beaucoup" de composants composites et que vous avez javax.faces.STATE_SAVING_METHOD choisi client, alors les performances seront pénibles. N'abusez pas des composants composites si vous voulez simplement les fonctionnalités de base qui sont déjà possibles avec un simple fichier d'inclusion ou un fichier de balise. N'utilisez pas la facilité de configuration (lire: aucun *.taglib.xmlfichier nécessaire) comme excuse pour préférer les composants composites aux fichiers de balises.

Lorsque vous utilisez Mojarra 2.2.10 ou une version antérieure, n'oubliez pas de désactiver la période de rafraîchissement relativement courte des Facelets pour le mode production:

<context-param>
    <param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
    <param-value>-1</param-value>
</context-param>

N'utilisez pas ce paramètre pour le développement, sinon vous devez redémarrer tout le serveur pour que les modifications des fichiers Facelets soient reflétées! Mojarra 2.2.11 et plus récent, et MyFaces est déjà défini par défaut sur -1quand javax.faces.PROJECT_STAGEn'est pas défini sur Development.

BalusC
la source
pourquoi voudriez-vous rendre 1 composant (composant composite) au lieu de disons 3 (fichier de balise facelet)? Je veux dire bien, par une journée ensoleillée, vous vous sentirez peut-être comme 1 au lieu de 3 ... mais je suppose qu'il y a autre chose derrière. Dans votre exemple, vous étendez UINamingContainer ... cela pourrait-il être l'une des raisons d'opter pour un cc (pour pouvoir écraser certaines fonctions spécifiques à l'implémentation jsf)?
Toskan
2
Un fichier de balise doit être considéré comme une sorte d'inclusion. Un composant composite doit être considéré comme un composant réel. Un composant composite doit être implémenté NamingContainer, sinon vous vous retrouvez avec des problèmes d'ID en double lorsque le même composant est réutilisé plusieurs fois.
BalusC
@BalusC Disons que j'ai un tas de HTML et JSF qui créent un «bloc» qui me permet d'ajouter ou de supprimer des adresses (et tous ses attributs: rue, numéro, ville, etc.). J'ai besoin d'utiliser ce même bloc en 2 ou 3 pages. Cela relève-t-il de votre description d'un composant composite?
RinaldoPJr
1
@Rinaldo: Je pense que j'utiliserais un fichier de balise pour cela avec des identifiants de composants remplis dynamiquement, comme illustré dans stackoverflow.com/questions/5713718/… . IMO, si cela peut être fait avec un fichier de balises, utilisez-le. Si cela ne peut pas être fait avec un fichier de balises, utilisez un composite. Si vous avez besoin de plusieurs composants pour manipuler une seule propriété (pas d'adresse, mais par exemple nom de rue + numéro de maison qui devrait aller dans une seule propriété), alors un composant composite serait la seule solution.
BalusC
2
@Tarik: les composites ont beaucoup de frais généraux par rapport aux tagfiles. En d'autres termes: de mauvaises performances. Utilisez-le uniquement si vous devez créer un seul composant d'interface utilisateur personnalisé basé sur un ensemble de composants existants étroitement liés. Cela ne peut pas être fait avec un tagfile. ZEEF.com, par exemple , a un seul composite: le upload / download / recadrer l' image tout-en-une chose qui est utilisé dans ao image page, photo de profil, en- tête de bloc de liaison, des blocs d'images, etc. Il est lié à seulement une Imagepropriété en haricot.
BalusC