添加<h:form>会导致java.lang.IllegalStateException:在提交响应后无法创建会话</h:form>

时间:2011-11-09 21:58:08

标签: forms session jsf jsf-2 illegalstateexception

在添加<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>,则异常会消失。

这是如何引起的?如何解决?

5 个答案:

答案 0 :(得分:83)

这是一个已知问题,您的报道确实为issue 2215。当响应缓冲区溢出(由于内容较大)并且在创建会话之前已提交响应时,将发生这种情况。这是Mojarra尽可能推迟“不必要的”会话创建的过度尝试的结果(尽管这本身就是好事)。

在修复之前,有几种解决方法:

  1. HttpServletRequest#getSession()之前创建一个Filter FilterChain#doFilter()。优点:无需更改JSF配置/代码。缺点:当你想要自己避免不必要的会话创建时。

  2. 在bean(post)构造函数或true侦听器中使用preRenderView调用ExternalContext#getSession()。优势:实际上,没有。缺点:太hacky。

  3. 将名称为com.sun.faces.writeStateAtFormEnd且值为false的上下文参数添加到web.xml。优点:与#1和#2相比,将真正避免不必要的会话创建。缺点:响应现在将在内存中完全缓冲,直到达到</h:form>。如果您的表格不是很大,那么影响应该是最小的。但是,如果<h:form>在视图中相对较晚开始,它仍然会失败。这可以与#4结合使用。

  4. 添加名称为javax.faces.FACELETS_BUFFER_SIZE的上下文参数和Facelets响应缓冲区大小的值(以字节为单位)(例如65535为64KB),以便整个HTML输出或至少{ {1}}(参见#3)适合响应缓冲区。优点/缺点,见#3。

  5. 将名称为<h:form>且值为javax.faces.STATE_SAVING_METHOD的上下文参数添加到client。优点:除非您有会话范围的bean,否则将不会创建会话。它还可以立即解决潜在的web.xml个案例。缺点:增加了网络带宽使用率。如果您正在使用部分状态保存,那么影响应该是最小的。

  6. 至于删除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。