Pourquoi JSF enregistre l'état des composants de l'interface utilisateur sur le serveur?

108
  1. Jusqu'à quel moment JSF enregistre-t-il l'état des composants d'interface utilisateur côté serveur et quand exactement les informations d'état du composant d'interface utilisateur sont-elles supprimées de la mémoire du serveur? Lorsqu'un utilisateur connecté sur l'application navigue à travers les pages, l'état des composants continuera-t-il à s'accumuler sur le serveur?

  2. Je ne comprends pas quel est l'avantage de conserver l'état des composants de l'interface utilisateur sur le serveur!? Le passage direct des données validées / converties aux beans gérés n'est-il pas suffisant? Puis-je ou devrais-je essayer de l'éviter?

  3. Cela ne consomme-t-il pas trop de mémoire côté serveur, s'il y a des milliers de sessions utilisateur simultanées? J'ai une application où les utilisateurs peuvent publier des blogs sur certains sujets. Ces blogs sont assez volumineux. Lorsqu'il y aura des articles ou des demandes de consultation des blogs, ces données volumineuses seront-elles enregistrées dans le cadre de l'état des composants? Cela mangerait trop de mémoire. N'est-ce pas un problème?


Mise à jour 1:

Désormais, il n'est plus nécessaire de sauvegarder l'état lors de l'utilisation de JSF. Une implémentation JSF sans état haute performance est disponible. Voir ce blog et cette question pour des détails pertinents et des discussions. En outre, il existe un problème ouvert à inclure dans les spécifications JSF, une option permettant de fournir un mode sans état pour JSF. (PS Envisagez de voter pour les problèmes ceci et cela si c'est une fonctionnalité utile pour vous.)


Mise à jour 2 (24-02-2013):

Une bonne nouvelle que Mojarra 2.1.19 est sorti avec le mode sans état !

Vois ici:

http://weblogs.java.net/blog/mriem/archive/2013/02/08/jsf-going-stateless?force=255

http://java.net/jira/browse/JAVASERVERFACES-2731

http://balusc.blogspot.de/2013/02/stateless-jsf.html

Rajat Gupta
la source

Réponses:

199

Pourquoi JSF doit-il enregistrer l'état des composants de l'interface utilisateur côté serveur?

Parce que HTTP est sans état et JSF est avec état. L'arborescence des composants JSF est sujette à des modifications dynamiques (programmatiques). JSF a simplement besoin de connaître l'état exact tel qu'il était lorsque le formulaire a été affiché à l'utilisateur final, afin qu'il puisse traiter avec succès l'ensemble du cycle de vie JSF en fonction des informations fournies par l'arborescence des composants JSF d'origine lorsque le formulaire a été renvoyé à le serveur. L'arborescence des composants fournit des informations sur les noms des paramètres de demande, les convertisseurs / validateurs nécessaires, les propriétés de bean géré lié et les méthodes d'action.


Jusqu'à quel moment JSF enregistre-t-il l'état des composants d'interface utilisateur côté serveur et quand exactement les informations d'état du composant d'interface utilisateur sont-elles supprimées de la mémoire du serveur?

Ces deux questions semblent se résumer à la même chose. Quoi qu'il en soit, c'est spécifique à l'implémentation et dépend également du fait que l'état est enregistré sur le serveur ou le client. Une implémentation un peu décente la supprimera lorsqu'elle aura expiré ou lorsque la file d'attente sera pleine. Mojarra, par exemple, a une limite par défaut de 15 vues logiques lorsque la sauvegarde d'état est définie sur session. Ceci est configurable avec le paramètre de contexte suivant dans web.xml:

<context-param>
    <param-name>com.sun.faces.numberOfLogicalViews</param-name>
    <param-value>15</param-value>
</context-param>

Voir aussi la FAQ Mojarra pour d'autres paramètres spécifiques à Mojarra et cette réponse connexe com.sun.faces.numberOfViewsInSession vs com.sun.faces.numberOfLogicalViews


Lorsqu'un utilisateur connecté sur l'application navigue dans les pages, l'état des composants continuera-t-il à s'accumuler sur le serveur?

Techniquement, cela dépend de la mise en œuvre. Si vous parlez de navigation de page à page (juste des requêtes GET), Mojarra n'enregistrera rien en session. S'il s'agit cependant de requêtes POST (formulaires avec liens de commande / boutons), Mojarra sauvegardera l'état de chaque formulaire en session jusqu'à la limite max. Cela permet à l'utilisateur final d'ouvrir plusieurs formulaires dans différents onglets de navigateur dans la même session.

Ou, lorsque l'enregistrement d'état est défini sur client, JSF ne stockera rien dans la session. Vous pouvez le faire avec le paramètre de contexte suivant dans web.xml:

<context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>client</param-value>
</context-param>

Il sera ensuite sérialisé en une chaîne cryptée dans un champ de saisie masqué avec le nom javax.faces.ViewStatedu formulaire.


Je ne comprends pas quel est l'avantage de conserver l'état du composant de l'interface utilisateur côté serveur. Le passage direct des données validées / converties aux beans gérés n'est-il pas suffisant? Puis-je / devrais-je essayer de l'éviter?

Cela ne suffit pas pour garantir l'intégrité et la robustesse de JSF. JSF est un framework dynamique avec un seul point de contrôle d'entrée. Sans une gestion étatique, on serait spoof / pirater les requêtes HTTP en mesure d'une certaine manière (par exemple manipulation disabled, readonlyet renderedattributs), de laisser faire des choses différentes JSF -et potentiellement hazardful-. Il serait même sujet aux attaques CSRF et au phishing.


Et cela ne consommera-t-il pas trop de mémoire côté serveur, s'il y a des milliers de sessions utilisateur simultanées? J'ai une application où les utilisateurs peuvent publier des blogs sur certains sujets. Ces blogs sont assez volumineux. Lorsqu'il y aura publication ou demande de consultation des blogs, les gros blogs seront enregistrés dans le cadre de l'état des composants. Cela consommerait trop de mémoire. N'est-ce pas un problème?

La mémoire est particulièrement bon marché. Donnez simplement suffisamment de mémoire au serveur d'applications. Ou si la bande passante du réseau est moins chère pour vous, basculez simplement la sauvegarde de l'état du côté client. Pour trouver la meilleure correspondance, il suffit de stresstest et de profiler votre application Web avec le nombre maximal d'utilisateurs simultanés attendus, puis de donner au serveur d'applications 125% ~ 150% de la mémoire maximale mesurée.

Notez que JSF 2.0 a beaucoup amélioré la gestion des états. Il est possible de sauvegarder un état partiel (par exemple, seul le <h:form>sera sauvegardé au lieu de tout le contenu de <html>tout le chemin jusqu'à la fin). Mojarra, par exemple, fait cela. Un formulaire moyen avec 10 champs de saisie (chacun avec une étiquette et un message) et 2 boutons ne prendrait pas plus de 1 Ko. Avec 15 vues en session, cela ne devrait pas dépasser 15 Ko par session. Avec ~ 1000 sessions utilisateur simultanées, cela ne devrait pas dépasser 15 Mo.

Votre préoccupation devrait être davantage centrée sur les objets réels (beans gérés et / ou même entités DB) dans le périmètre de session ou d'application. J'ai vu beaucoup de codes et de projets qui dupliquent inutilement toute la table de base de données dans la mémoire de Java dans la saveur d'un bean à portée de session où Java est utilisé au lieu de SQL pour filtrer / regrouper / organiser les enregistrements. Avec ~ 1000 enregistrements, cela dépasserait facilement 10 Mo par session utilisateur .

BalusC
la source
1
Pouvez-vous clarifier le n ° 2? Pourquoi l'arborescence des composants ne peut-elle pas être simplement recréée à chaque demande? Quel état doit réellement être stocké entre les requêtes et pourquoi? Il semble que la seule raison de sauvegarder l'arborescence des composants entre les demandes serait la performance.
Ryan
Question plus ciblée ici: stackoverflow.com/questions/7349174/…
Ryan
Votre réponse était très claire pour moi! Les problèmes de performances et d'évolutivité JSF ont une relation intrinsèque avec l'implémentation du programmeur! Il faut savoir utiliser la technologie de la bonne manière!
Lucas Batistussi
"Donnez juste assez de mémoire au serveur d'applications." Euh, j'ai l'impression que nous parlons ici de choses au niveau de l'entreprise, si nous parlons de milliers de sessions utilisateur simultanées. Si vous avez un équipement de niveau entreprise dans une entreprise, vous ne pouvez pas simplement "donner suffisamment de mémoire au serveur d'applications" comme vous pouvez le faire dans votre machine Linux à la maison.
STU
Votre réponse était très claire et merci pour cela. Pourquoi la portée flash JSF a-t-elle disparu si javax.faces.PARTIAL_STATE_SAVING a la valeur true. getFacesContext (). getExternalContext (). getFlash (). put ("buildingId", buildingId).
May Thet