【问题标题】:Adding <h:form> causes java.lang.IllegalStateException: Cannot create a session after the response has been committed添加 <h:form> 会导致 java.lang.IllegalStateException:在提交响应后无法创建会话
【发布时间】:2011-12-25 17:13:14
【问题描述】:

在添加&lt;h:form&gt; 后,我在一个非常简单的 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>

页面在浏览器上正确显示,但在控制台上我看到了异常。如果我删除 &lt;h:form&gt;,异常确实会消失。

这是怎么引起的,我该如何解决?

【问题讨论】:

    标签: forms session jsf jsf-2 illegalstateexception


    【解决方案1】:

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

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

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

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

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

    4. 添加一个名为 javax.faces.FACELETS_BUFFER_SIZE 的上下文参数和一个以字节为单位的 Facelets 响应缓冲区大小的值(例如,65535 表示 64KB),以便整个 HTML 输出或至少 &lt;h:form&gt;(请参阅#3) 适合响应缓冲区。优势/劣势,见#3。

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

    至于为什么删除&lt;h:form&gt;后问题消失,这是因为不需要创建会话来存储视图状态。


    更新:根据重复的issue 2277,自 Mojarra 2.1.8 以来已修复此问题。因此,您也可以至少升级到该版本。

    【讨论】:

    • 谢谢!看来这个问题将通过 Mojarra 2.1.8 (java.net/jira/browse/JAVASERVERFACES-2277) 解决,该版本应该很快就会发布
    • 通读整个 JIRA 似乎问题仍然存在,2.1.16
    • 我遇到了类似的问题,当我使用 2.1.13 时,问题就出现了。然而,实施 #3 建议解决了它。
    【解决方案2】:

    随着昨天发布的 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。

    【讨论】:

      【解决方案3】:

      在我的情况下(myfaces-2.2.8 和 Tomcat 8.0.23),问题是 welcome-fileweb.xml 中的错字。 在调试时我看到,Tomcat 按预期创建了 404,但不知何故 myfaces 试图在之后访问会话,这导致了java.lang.IllegalStateException: Cannot create a session after the response has been committed。 在web.xmlwelcome-file 中使用有效页面为我解决了这个问题。

      【讨论】:

        【解决方案4】:

        您可能需要在h:form 元素之前和之后添加&lt;f:view&gt;&lt;/f:view&gt;,并为jsf 标记添加指向您的html 标记的链接

        <html xmlns:f="http://java.sun.com/jsf/core">
        

        为了这个工作。

        【讨论】:

          【解决方案5】:

          如果你使用 Spring MVC 并且调用是由 Spring Forms 进行的,那么我们应该使用 GET 方法而不是 POST(获取数据),并且应该没有我们可以使用的输入字段。

          【讨论】:

          猜你喜欢
          • 2011-01-04
          • 2012-06-06
          • 1970-01-01
          • 2014-12-08
          • 2014-05-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多