添加< h:表格>导致java.lang.IllegalStateException:响应提交后无法创建会话 [英] Adding <h:form> causes java.lang.IllegalStateException: Cannot create a session after the response has been committed

查看:186
本文介绍了添加< h:表格>导致java.lang.IllegalStateException:响应提交后无法创建会话的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在添加< h:form> 后,我在一个非常简单的JSF 2页面中遇到以下异常:

  java.lang.IllegalStateException:在提交响应之后无法创建会话
位于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:头>

< / h:head>
< h:body>
< h:form>
< p:dataTable var =carvalue =#{tableBean.cars}>

......
< / p:dataTable>
< / h:表格>
< / h:body>
< / html>

页面在浏览器上正确显示,但在控制台上我看到异常。如果我删除了< h:form> ,那么异常消失了。



这是如何引起的?我解决了这个问题? 解决方案

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



直到他们得到它修复了,有几个解决方法:


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

  2. ExternalContext#getSession() with true 在bean的(后)构造函数或 preRenderView 侦听器中。优点:实际上,没有。
  3. 添加名称为的上下文参数com.sun.faces.writeStateAtFormEnd false web.xml 的值。优点:与#1和#2相反,不必要的会话创建将被真正避免。缺点:响应现在将完全缓冲在内存中,直到达到< / h:form> 。如果你的表格不是特别大,那么影响应该是最小的。但是,如果您的< h:form> 在视图中启动相对较晚,它仍然会失败。这可能与#4结合在一起。

  4. 添加名称为的javax.faces.FACELETS_BUFFER_SIZE 和一个以字节为单位的Facelets响应缓冲区大小的值(例如,对于64KB, 65535 ),以便整个HTML输出或至少< h :form> (见#3)适合响应缓冲区。添加一个上下文参数,其名称为 javax.faces.STATE_SAVING_METHOD 客户端 web.xml 的值。优点:除非你有会话范围的bean,否则根本不会创建会话。它也立即解决潜在的 ViewExpiredException 个案。缺点:增加网络带宽使用量。如果您使用的是部分状态保存,那么影响应该是最小的。




  5. 至于问题为何消失当你删除< h:form> 时,这是因为不需要创建会话来存储视图状态。






    更新:根据重复的 issue 2277 自Mojarra 2.1.8以来已经修复。所以,你也可以升级到至少那个版本。


    I'm facing the following exception in a very simple JSF 2 page after adding <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)
    

    I'm using Mojarra 2.1.3 and PrimeFaces3.0M4, on Tomcat 7.0.22 and JDK 7.

    The page is a very basic data table:

    <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>
    

    The page shows correctly on the browser, but on the console I see the exception. The Exception does disappear if I remove the <h:form>.

    How is this caused and how can I solve it?

    解决方案

    This is a known problem and has been reported by yours truly as issue 2215. This will occur when the response buffer has overflowed (due to large content) and the response is been committed before the session is been created. This is result of bit overzealous attempts of Mojarra to postpone "unnecessary" session creation as much as possible (which is at its own a Good Thing though).

    Until they get it fixed, there are several workarounds:

    1. Create a Filter which does HttpServletRequest#getSession() before FilterChain#doFilter(). Advantage: no need to change JSF configuration/code. Disadvantage: when you want to avoid unnecessary session creation yourself as well.

    2. Call ExternalContext#getSession() with true in bean's (post)constructor or preRenderView listener. Advantage: actually, nothing. Disadvantage: too hacky.

    3. Add a context parameter with name of com.sun.faces.writeStateAtFormEnd and value of false to web.xml. Advantage: unnecessary session creation will be really avoided as opposed to #1 and #2. Disadvantage: response will now be fully buffered in memory until </h:form> is reached. If your forms are not extremely large, the impact should however be minimal. It would however still fail if your <h:form> starts relatively late in the view. This may be combined with #4.

    4. Add a context parameter with name of javax.faces.FACELETS_BUFFER_SIZE and a value of the Facelets response buffer size in bytes (e.g. 65535 for 64KB) so that the entire HTML output or at least the <h:form> (see #3) fits in the response buffer. Advantage/disadvantage, see #3.

    5. Add a context parameter with name of javax.faces.STATE_SAVING_METHOD and value of client to web.xml. Advantage: session will not be created at all unless you have session scoped beans. It also immediately solves potential ViewExpiredException cases. Disadvantage: increased network bandwidth usage. If you're using partial state saving, then the impact should however be minimal.

    As to why the problem disappears when you remove <h:form>, this is because no session needs to be created in order to store the view state.


    Update: this has as per the duplicate issue 2277 been fixed since Mojarra 2.1.8. So, you can also just upgrade to at least that version.

    这篇关于添加&lt; h:表格&gt;导致java.lang.IllegalStateException:响应提交后无法创建会话的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆