2016-04-15 2 views
1

Je cours Mojarra 2.2.0.Quand est-ce que JSF crée une session et que met-elle dans une carte de session?

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

La méthode d'action gérée de haricot est-

public void action() { 
     HttpSession session = (HttpSession) FacesContext.getCurrentInstance() 
       .getExternalContext().getSession(false); 
     System.out.println(session.getId()); // not null for stateful views 
    } 

Pour stateless vues session.getId() lancers francs NPE

Pour les vues qui ne sont pas apatridie Firing une requête GET, il y a JSESSIONID=340041C96D5AA446D761C3602F54A76D

Je l'ai lu here that-

Pour le mécanisme d'économie d'état côté client, JSF ne créera pas la session et mémorise l'état d'affichage dans un champ caché avec le nom javax.faces.ViewState sous la forme chaque fois que nécessaire.

En outre, il est mentionné ici that

JSF autocreate en effet la session parce que l'état d'affichage JSF a être stocké là-bas. Si vous définissez la méthode sauvegarde de l'état JSF client au lieu de serveur, il ne sera pas enregistrée en session et, par conséquent aucune session doit être créé

Je pense que la ligne ci-dessus est une source d'ennuis pour moi.

Si vous définissez la méthode sauvegarde de l'état JSF au client au lieu de serveur, alors il ne sera pas stocké en session // entièrement d'accord

et

donc aucune session doit être créé. // Cela crée une confusion parce que pour le mécanisme d'économie côté client , un identifiant de session est généré par le conteneur de servlet & d'où une session associée à la demande .

En ce qui concerne la discussion que j'eus avec BalusC dans ce question, je créé un HttpSessionListener-

@WebListener 
public class MyHttpSessionListener implements HttpSessionListener { 

    public void sessionCreated(HttpSessionEvent event) { 
     Thread.dumpStack(); 
    } 

    public void sessionDestroyed(HttpSessionEvent event) { 

    } 

} 

Voir les screenshots ci-dessous attachés (ces 2 captures d'écran sont pour la version 2.0.3, il faut ont été un vieux bug à cause duquel la session a été créée se) -

enter image description here

enter image description here

Libraby (Mojarra 2.2.0) - enter image description here

+0

@BalusC: Eclipse IDE auto l'a téléchargée pour moi. Je joins la capture d'écran aussi. –

+0

@BalusC: Désolé pour cette erreur idiote. Je pensais que supprimer la bibliothèque 2.0.3 du buildpath va les supprimer complètement. Pour Mojarra 2.2.0, maintenant le même écouteur HttpSession n'est pas appelé. Aucune suggestion? –

+0

@BalusC: Ahh, je vois. Maintenant j'ai compris. Je pense que la source de tout ce problème était le numéro de version. –

Répondre

3

Quand est-JSF crée une session

Eaiest façon de Naildown cela crée un HttpSessionListener, mettre un point d'arrêt de débogage sur la méthode sessionCreated() et inspecter la pile d'appel qui devait obtenir la session pour la première fois (et donc implicitement besoin de le créer).

Dans l'exemple ci-dessous, vous verrez une chaîne de getSession() appels dans la pile d'appels. Vous verrez que la méthode FaceletViewHandlingStrategy.renderView() est celle qui l'appelle pour la première fois.

enter image description here

Après avoir cliqué sur FaceletViewHandlingStrategy.renderView() ligne dans la pile d'appel de débogueur, vous entrerez dans son code source (Maven chargera automatiquement le code source, sinon vous devez attacher manuellement).

enter image description here

Vous voyez, quand l'économie d'état côté serveur est activé et la vue de rendre n'est pas transitoire (stateless), puis JSF crée implicitement la session, juste pour assurer qu'elle est créée à temps pour sauver la vue (si la session a été créée plus tard, par exemple pendant la phase de réponse du rendu, vous risquez sinon des exceptions telles que Adding <h:form> causes java.lang.IllegalStateException: Cannot create a session after the response has been committed). Vous verrez également dans le code source que lorsque la méthode d'économie d'état est définie sur client ou lorsque la vue est sans état comme dans <f:view transient="true">, JSF ne créera plus implicitement la session. Les anciennes versions de JSF peuvent faire cela comme vous l'avez pensé, mais cela doit être considéré comme un bug et devrait être corrigé dans une version plus récente.

Si vous souhaitez assurer l'apatridie et éviter la création de session accidentelle/imprévue, alors vous pouvez juste throw new IllegalStateException() à l'intérieur de la méthode sessionCreated(). Quand cela arrive, il suffit de regarder dans la pile d'appel qui est responsable de la création de la session, puis de corriger/modifier le code pour ne plus le faire.


ce qui ne le met dans une carte de la session?

Sous les couvertures, les délégués à ExternalContext#getSessionMap()HttpSession#setAttribute()/getAttribute()/removeAttribute(). Vous pouvez écouter sur ces méthodes en utilisant un HttpSessionAttributeListener.

Dans l'exemple ci-dessous, vous verrez que la ligne ViewScopeContextManager.getContextMap() appelle SessionMap#put() méthode afin de mettre quelque chose dans la carte de session. Lorsque vous développez l'argument event, vous verrez le nom et la valeur de l'attribut de session, qui est respectivement com.sun.faces.application.view.activeViewContexts et ConcurrentHashMap vide.

enter image description here

En effet, j'utilisais un @Named @ViewScoped qui a été référencé par une expression de valeur sur la page particulière (vous voyez résolveur EL et résolveur Weld plus bas dans la pile d'appels).Lorsque vous cliquez sur la ligne ViewScopeContextManager.getContextMap() dans la pile des appels, vous verrez qu'il s'agit simplement de préparer une carte dans la portée de la session afin de stocker les beans à portée de vue.

enter image description here

C'est juste un exemple. Il y a plus de choses qui pourraient être stockées dans la session. Utiliser un débogueur de cette façon et inspecter le code source associé en dira beaucoup sur le Pourquoi.