Je fais face à l'exception suivante dans une page JSF 2 très simple après avoir ajouté <h:form>
:
Java.lang.IllegalStateException: Cannot create a session after the response has been committed
at org.Apache.catalina.connector.Request.doGetSession(Request.Java:2758)
at org.Apache.catalina.connector.Request.getSession(Request.Java:2268)
J'utilise Mojarra 2.1.3 et PrimeFaces3.0M4, sur Tomcat 7.0.22 et JDK 7.
La page est un tableau de données très basique:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://Java.Sun.com/jsf/html"
xmlns:f="http://Java.Sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h:form>
<p:dataTable var="car" value="#{tableBean.cars}">
......
</p:dataTable>
</h:form>
</h:body>
</html>
La page s'affiche correctement sur le navigateur, mais sur la console, je vois l'exception. L'exception disparaît si je supprime le <h:form>
.
Comment cela est-il causé et comment puis-je le résoudre?
C’est un problème connu qui a été rapporté par le vôtre comme: numéro 2215 . Cela se produira lorsque la mémoire tampon de réponse aura débordé (en raison d'un contenu volumineux) et que la réponse aura été validée avant la création de la session. Ceci est le résultat de tentatives un peu trop zélées de Mojarra pour reporter autant que possible la création de session "inutile" (ce qui est cependant une bonne chose).
Jusqu'à ce qu'ils le résolvent, il existe plusieurs solutions de contournement:
Créez une Filter
qui fait HttpServletRequest#getSession()
before FilterChain#doFilter()
. Avantage: pas besoin de changer la configuration/le code JSF. Inconvénient: lorsque vous voulez éviter la création de session inutile vous-même.
Appelez ExternalContext#getSession()
avec true
dans le constructeur (post) du bean ou l'auditeur preRenderView
. Avantage: en réalité, rien. Inconvénient: trop hacky.
Ajoutez un paramètre de contexte portant le nom com.Sun.faces.writeStateAtFormEnd
et la valeur false
à web.xml
. Avantage: la création de session inutile sera vraiment évitée par opposition aux n ° 1 et n ° 2. Inconvénient: la réponse sera désormais entièrement mise en mémoire tampon jusqu'à ce que </h:form>
soit atteint. Si vos formulaires ne sont pas extrêmement volumineux, l'impact devrait cependant être minimal. Cependant, il échouerait toujours si votre <h:form>
commençait relativement tard dans la vue. Ceci peut être combiné avec # 4.
Ajoutez un paramètre de contexte portant le nom javax.faces.FACELETS_BUFFER_SIZE
et une valeur de la taille du tampon de réponse de Facelets en octets (par exemple, 65535
pour 64 Ko) de sorte que la sortie HTML entière ou au moins le <h:form>
(voir n ° 3) s'intègre dans le tampon de réponse. Avantage/désavantage, voir n ° 3.
Ajoutez un paramètre de contexte portant le nom javax.faces.STATE_SAVING_METHOD
et la valeur client
à web.xml
. Avantage: la session ne sera pas créée du tout sauf si vous avez une session haricot. Cela résout également immédiatement les cas potentiels ViewExpiredException
. Inconvénient: utilisation accrue de la bande passante du réseau. Si vous utilisez une sauvegarde d'état partielle, l'impact devrait cependant être minime.
La raison pour laquelle le problème disparaît lorsque vous supprimez <h:form>
est qu’aucune session n’a besoin d’être créée pour stocker l’état de la vue.
Update: cela a été corrigé depuis le duplicata numéro 2277 depuis Mojarra 2.1.8. Vous pouvez donc simplement mettre à niveau au moins cette version.
Avec la nouvelle version 2.1.21 publiée hier de javax.faces, ce problème semble avoir disparu . Déclarez la nouvelle version:
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.faces</artifactId>
<version>2.1.21</version>
</dependency>
et remplacez javax.faces.jar dans le dossier des modules de glassfish, en remplacement de javax.faces.jar pour la nouvelle version 2.1.21.
Dans mon cas (myfaces-2.2.8 & Tomcat 8.0.23), le problème était une faute de frappe dans le welcome-file
du web.xml
. Lors du débogage, j'ai constaté que Tomcat avait créé comme prévu un 404, mais que mon Session, qui a ensuite provoqué un Java.lang.IllegalStateException: Cannot create a session after the response has been committed
. Utiliser une page valide dans welcome-file
sur web.xml
a résolu le problème pour moi.
Vous devrez peut-être ajouter un <f:view>
et un </f:view>
avant et après les éléments h:form
, en plus d'ajouter le lien vers votre balise HTML pour les balises jsf
<html xmlns:f="http://Java.Sun.com/jsf/core">
pour que cela fonctionne.