Nach dem Hinzufügen von <h:form>
steht mir auf einer sehr einfachen JSF 2-Seite die folgende Ausnahme bevor:
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)
Ich verwende Mojarra 2.1.3 und PrimeFaces3.0M4 auf Tomcat 7.0.22 und JDK 7.
Die Seite ist eine sehr grundlegende Datentabelle:
<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>
Die Seite wird im Browser richtig angezeigt, aber auf der Konsole wird die Ausnahme angezeigt. Die Ausnahme verschwindet, wenn ich den <h:form>
entferne.
Wie wird das verursacht und wie kann ich es lösen?
Dies ist ein bekanntes Problem und wurde von Ihnen wirklich als Ausgabe 2215 gemeldet. Dies tritt auf, wenn der Antwortpuffer (aufgrund von großem Inhalt) übergelaufen ist und die Antwort festgeschrieben wurde, bevor die Sitzung erstellt wurde. Dies ist das Ergebnis von übereifrigen Versuchen von Mojarra, die "unnötige" Sitzungserstellung so weit wie möglich zu verschieben (was allerdings eine gute Sache ist).
Bis es behoben wird, gibt es mehrere Problemumgehungen:
Erstellen Sie eine Filter
, die HttpServletRequest#getSession()
vor FilterChain#doFilter()
tut. Vorteil: JSF-Konfiguration/Code muss nicht geändert werden. Nachteil: wenn Sie selbst unnötige Sitzungserstellung vermeiden möchten.
Rufen Sie ExternalContext#getSession()
mit true
im Bean-Konstruktor (post) oder preRenderView
-Listener auf. Vorteil: eigentlich nichts. Nachteil: zu hackig.
Fügen Sie einen Kontextparameter mit dem Namen com.Sun.faces.writeStateAtFormEnd
und dem Wert von false
zu web.xml
hinzu. Vorteil: unnötige Sitzungserstellung wird im Gegensatz zu # 1 und # 2 wirklich vermieden. Nachteil: Die Antwort wird jetzt vollständig im Speicher zwischengespeichert, bis </h:form>
erreicht ist. Wenn Ihre Formulare nicht sehr groß sind, sollte die Auswirkung jedoch minimal sein. Es würde jedoch immer noch fehlschlagen, wenn Ihr <h:form>
relativ spät in der Ansicht beginnt. Dies kann mit # 4 kombiniert werden.
Fügen Sie einen Kontextparameter mit dem Namen javax.faces.FACELETS_BUFFER_SIZE
und einem Wert der Antwortpuffergröße von Facelets in Bytes hinzu (z. B. 65535
für 64 KB), so dass die gesamte HTML-Ausgabe oder zumindest der <h:form>
(siehe # 3) in den Antwortpuffer passt. Vorteil/Nachteil, siehe Punkt 3.
Fügen Sie einen Kontextparameter mit dem Namen javax.faces.STATE_SAVING_METHOD
und dem Wert von client
zu web.xml
hinzu. Vorteil: Sitzung wird nicht erstellt, es sei denn, Sie haben Beans mit Sitzungsbereich. Es löst auch sofort mögliche ViewExpiredException
Fälle. Nachteil: erhöhte Netzwerkbandbreite. Wenn Sie eine teilweise Zustandsersparnis verwenden, sollte die Auswirkung jedoch minimal sein.
Das Problem verschwindet, wenn Sie <h:form>
entfernen. Dies liegt daran, dass zum Speichern des Ansichtsstatus keine Sitzung erstellt werden muss.
Update: Dies wurde gemäß dem Duplikat issue 2277 seit Mojarra 2.1.8 behoben. Sie können also auch mindestens auf diese Version upgraden.
Mit der neuen Version 2.1.21, die gestern von javax.faces veröffentlicht wurde, scheint dieses Problem verschwunden zu sein . Deklarieren Sie die neue Version:
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.faces</artifactId>
<version>2.1.21</version>
</dependency>
und ersetzen Sie die Datei "javax.faces.jar" im Ordner "glassfish modules" und ersetzen Sie die Datei "javax.faces.jar" für die neue Version 2.1.21.
In meinem Fall (myfaces-2.2.8 & Tomcat 8.0.23) war das Problem ein Tippfehler im welcome-file
von web.xml
. Beim Debuggen sah ich, dass Tomcat erwartungsgemäß eine 404 erstellt hatte, aber irgendwie versuchte myfaces nachher darauf zuzugreifen Session, die dann einen Java.lang.IllegalStateException: Cannot create a session after the response has been committed
verursacht hat. Durch Verwendung einer gültigen Seite in welcome-file
von web.xml
wurde das Problem für mich behoben.
Möglicherweise müssen Sie vor und nach den <f:view>
-Elementen einen </f:view>
- und einen h:form
-Element hinzufügen. Außerdem muss der Link zu Ihrem html-Tag für jsf-Tags hinzugefügt werden
<html xmlns:f="http://Java.Sun.com/jsf/core">
damit dies funktioniert.