在添加<h:form>
后,我在一个非常简单的JSF 2页面中遇到以下异常:
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)
我在Tomcat 7.0.22和JDK 7上使用Mojarra 2.1.3和PrimeFaces3.0M4。
该页面是一个非常基本的数据表:
<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>
页面在浏览器上正确显示,但在控制台上我看到了异常。如果我删除<h:form>
,则异常会消失。
这是如何引起的?如何解决?
答案 0 :(得分:83)
这是一个已知问题,您的报道确实为issue 2215。当响应缓冲区溢出(由于内容较大)并且在创建会话之前已提交响应时,将发生这种情况。这是Mojarra尽可能推迟“不必要的”会话创建的过度尝试的结果(尽管这本身就是好事)。
在修复之前,有几种解决方法:
在HttpServletRequest#getSession()
之前创建一个Filter
FilterChain#doFilter()
。优点:无需更改JSF配置/代码。缺点:当你想要自己避免不必要的会话创建时。
在bean(post)构造函数或true
侦听器中使用preRenderView
调用ExternalContext#getSession()
。优势:实际上,没有。缺点:太hacky。
将名称为com.sun.faces.writeStateAtFormEnd
且值为false
的上下文参数添加到web.xml
。优点:与#1和#2相比,将真正避免不必要的会话创建。缺点:响应现在将在内存中完全缓冲,直到达到</h:form>
。如果您的表格不是很大,那么影响应该是最小的。但是,如果<h:form>
在视图中相对较晚开始,它仍然会失败。这可以与#4结合使用。
添加名称为javax.faces.FACELETS_BUFFER_SIZE
的上下文参数和Facelets响应缓冲区大小的值(以字节为单位)(例如65535
为64KB),以便整个HTML输出或至少{ {1}}(参见#3)适合响应缓冲区。优点/缺点,见#3。
将名称为<h:form>
且值为javax.faces.STATE_SAVING_METHOD
的上下文参数添加到client
。优点:除非您有会话范围的bean,否则将不会创建会话。它还可以立即解决潜在的web.xml
个案例。缺点:增加了网络带宽使用率。如果您正在使用部分状态保存,那么影响应该是最小的。
至于删除ViewExpiredException
时问题消失的原因,这是因为不需要创建会话来存储视图状态。
更新:根据Mojarra 2.1.8修复了重复的issue 2277。所以,你也可以升级到至少那个版本。
答案 1 :(得分:6)
随着昨天发布的javax.faces新版本2.1.21,这个问题似乎已经消失了。 声明新版本:
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.faces</artifactId>
<version>2.1.21</version>
</dependency>
并替换glassfish模块文件夹中的javax.faces.jar,替换新版本2.1.21的javax.faces.jar。
答案 2 :(得分:3)
就我而言(myfaces-2.2.8&amp; Tomcat 8.0.23),问题是welcome-file
web.xml
中的拼写错误。
在我看到的调试时,Tomcat按预期创建了404,但不知何故myfaces尝试访问Session后,导致java.lang.IllegalStateException: Cannot create a session after the response has been committed
。
使用welcome-file
web.xml
中的有效页面为我修复了问题。
答案 3 :(得分:0)
您可能需要在<f:view>
元素之前和之后添加</f:view>
和h:form
,并添加指向jsf标记的html标记的链接
<html xmlns:f="http://java.sun.com/jsf/core">
让这个工作。
答案 4 :(得分:-1)
如果您正在使用Spring MVC并且由Spring Forms调用,那么我们应该使用GET方法而不是POST(获取数据),并且应该没有输入字段,我们可以使用intead。