添加导致 java.lang.IllegalStateException:提交响应后无法创建会话
添加
后,我在一个非常简单的 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 上使用 Mojarra 2.1.3 和 PrimeFaces3.0M4 7.
该页面是一个非常基本的数据表:
<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>
该页面在浏览器上正确显示,但在控制台上我看到异常。如果我删除
,异常就会消失。
这是如何引起的以及如何解决?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这是一个已知问题,您已将其报告为问题 2215。当响应缓冲区溢出(由于内容较大)并且在创建会话之前提交响应时,就会发生这种情况。这是 Mojarra 过于热心地尝试尽可能推迟“不必要的”会话创建的结果(尽管这本身就是一件好事)。
在他们修复此问题之前,有几种解决方法:
创建一个
Filter
,它可以HttpServletRequest#getSession()
在FilterChain#doFilter()
。优点:无需更改 JSF 配置/代码。缺点:当您也想避免自己创建不必要的会话时。调用
ExternalContext#getSession()
在 bean 的(post)构造函数或preRenderView
侦听器中使用true
。优点:其实没什么。缺点:太老套了。向
web.xml
添加名称为com.sun.faces.writeStateAtFormEnd
且值为false
的上下文参数。优点:与 #1 和 #2 相比,将真正避免不必要的会话创建。缺点:响应现在将完全缓冲在内存中,直到到达为止。如果您的表单不是很大,那么影响应该很小。然而,如果您的
在视图中启动相对较晚,它仍然会失败。这可以与 #4 结合使用。添加名称为 javax.faces.FACELETS_BUFFER_SIZE 的上下文参数和 Facelets 响应缓冲区大小的值(以字节为单位,例如 65535 表示 64KB),以便整个HTML 输出或至少
(参见 #3)适合响应缓冲区。优点/缺点,请参阅 #3。将名称为
javax.faces.STATE_SAVING_METHOD
且值为client
的上下文参数添加到web.xml
。优点:除非您有会话范围的 bean,否则根本不会创建会话。它还可以立即解决潜在的ViewExpiredException
情况。缺点:增加网络带宽使用。如果您使用部分状态保存,那么影响应该很小。至于为什么删除
后问题就消失了,这是因为不需要创建会话来存储视图状态。更新:根据重复的问题 2277 已修复此问题自 Mojarra 2.1.8 起。因此,您也可以至少升级到该版本。
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:
Create a
Filter
which doesHttpServletRequest#getSession()
beforeFilterChain#doFilter()
. Advantage: no need to change JSF configuration/code. Disadvantage: when you want to avoid unnecessary session creation yourself as well.Call
ExternalContext#getSession()
withtrue
in bean's (post)constructor orpreRenderView
listener. Advantage: actually, nothing. Disadvantage: too hacky.Add a context parameter with name of
com.sun.faces.writeStateAtFormEnd
and value offalse
toweb.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.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.Add a context parameter with name of
javax.faces.STATE_SAVING_METHOD
and value ofclient
toweb.xml
. Advantage: session will not be created at all unless you have session scoped beans. It also immediately solves potentialViewExpiredException
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.
随着 javax.faces 昨天发布的新版本 2.1.21,这个问题似乎已经消失了。
声明新版本:
并替换 glassfish 模块文件夹中的 javax.faces.jar,替换新版本 2.1.21 的 javax.faces.jar。
With the new version 2.1.21 released yesterday of javax.faces this problem seems to have disappeared.
Declare the new version:
and replace the javax.faces.jar in the glassfish modules folder replacing the javax.faces.jar for the new version 2.1.21.
就我而言(myfaces-2.2.8 和 Tomcat 8.0.23),问题是
web.xml
的welcome-file
中的拼写错误。在调试时,我看到 Tomcat 按预期创建了 404,但不知何故 myfaces 尝试在之后访问会话,这导致了
java.lang.IllegalStateException: Cannot create a session after the response has been commited
。在
web.xml
的welcome-file
中使用有效页面解决了我的问题。In my case (myfaces-2.2.8 & Tomcat 8.0.23) the Problem was a typo in the
welcome-file
ofweb.xml
.While debugging i saw, that Tomcat created as expected a 404, but somehow myfaces tried to access afterwards the Session, which caused then a
java.lang.IllegalStateException: Cannot create a session after the response has been committed
.Using a valid page in
welcome-file
ofweb.xml
fixed the Problem for me.您可能需要在
h:form
元素之前和之后添加
和,再加上添加指向 jsf 标签的 html 标签的链接,
以使其正常工作。
You may need to add an
<f:view>
and</f:view>
before and afterh:form
elements, plus add the link to you html tag for jsf tagsfor this to work.
如果您使用 Spring MVC 并且由 Spring Forms 进行调用,那么我们应该使用 GET 方法而不是 POST(获取数据),并且不应该有我们可以使用的输入字段。
If you are using Spring MVC and call is made by Spring Forms then we should use GET method instead of POST(to fetch data) and there should be no input field we can use intead.