Добавление <h: form> вызывает java.lang.IllegalStateException: не удается создать сеанс после того, как ответ был зафиксирован - программирование
Подтвердить что ты не робот

Добавление <h: form> вызывает java.lang.IllegalStateException: не удается создать сеанс после того, как ответ был зафиксирован

Я сталкиваюсь со следующим исключением на очень простой странице JSF 2 после добавления <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)

Я использую Mojarra 2.1.3 и PrimeFaces3.0M4, на Tomcat 7.0.22 и JDK 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>

Страница отображается правильно в браузере, но на консоли я вижу исключение. Исключение исчезает, если я удаляю <h:form>.

Как это вызвано и как я могу его решить?

4b9b3361

Ответ 1

Это известная проблема, о которой вы действительно сообщили в проблема 2215. Это произойдет, когда буфер ответа переполнится (из-за большого содержимого), и ответ будет выполнен до того, как будет создан сеанс. Это результат чересчур переусердствующих попыток Мохарры отложить "ненужное" создание сессии как можно больше (что само по себе является хорошим делом).

Пока они не будут исправлены, существует несколько способов:

  • Создайте Filter, который HttpServletRequest#getSession() перед FilterChain#doFilter(). Преимущество: нет необходимости изменять конфигурацию/код JSF. Недостаток: когда вы тоже хотите избежать ненужного создания сеанса.

  • Вызовите ExternalContext#getSession() с помощью true в конструкторе bean (post) или preRenderView. Преимущество: на самом деле, ничего. Недостаток: слишком хаки.

  • Добавьте параметр контекста с именем com.sun.faces.writeStateAtFormEnd и значением false в web.xml. Преимущество: ненужное создание сеанса будет действительно устранено, в отличие от # 1 и # 2. Недостаток: теперь реакция будет полностью забуферирована в памяти до достижения </h:form>. Если ваши формы не очень велики, воздействие должно быть минимальным. Тем не менее он все равно потерпит неудачу, если ваш <h:form> начнет относительно поздно в представлении. Это может быть объединено С# 4.

  • Добавьте параметр контекста с именем javax.faces.FACELETS_BUFFER_SIZE и значением размера буфера ответа Facelets в байтах (например, 65535 для 64 КБ), чтобы весь вывод HTML или, по крайней мере, <h:form> (см. # 3) вписывается в буфер ответа. Преимущество/недостаток, см. № 3.

  • Добавьте параметр контекста с именем javax.faces.STATE_SAVING_METHOD и значением client в web.xml. Преимущество: сеанс вообще не создается, если у вас нет сеанса beans. Он также немедленно решает потенциальные случаи ViewExpiredException. Недостаток: увеличение использования пропускной способности сети. Если вы используете частичное сохранение состояния, тогда воздействие должно быть минимальным.

В связи с тем, что проблема исчезает, когда вы удаляете <h:form>, это связано с тем, что сеанс не нужно создавать, чтобы сохранить состояние представления.


Обновление: это соответствует дубликат issue 2277, который был исправлен с Mojarra 2.1.8. Таким образом, вы можете просто обновить, по крайней мере, эту версию.

Ответ 2

В новой версии 2.1.21, выпущенной вчера из javax.faces, эта проблема, похоже, исчезла. Объявите новую версию:

<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.faces</artifactId>
    <version>2.1.21</version>
</dependency>

и замените javax.faces.jar в папке модулей Glassfish, заменив javax.faces.jar для новой версии 2.1.21.

Ответ 3

В моем случае (myfaces-2.2.8 и Tomcat 8.0.23) проблема была опечаткой в ​​welcome-file of web.xml. Во время отладки я увидел, что Tomcat создал, как ожидалось, 404, но каким-то образом myfaces попытался получить доступ к сеансу, что вызвало тогда java.lang.IllegalStateException: Cannot create a session after the response has been committed. Использование допустимой страницы в welcome-file of web.xml исправило проблему для меня.

Ответ 4

Вам может потребоваться добавить элементы <f:view> и </f:view> до и после h:form, а также добавить ссылку на тэг html для тегов jsf

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

для этого.

Ответ 5

Если вы используете Spring MVC, а вызов выполняется с помощью Spring Forms, тогда мы должны использовать GET-метод вместо POST (для получения данных), и не должно быть поля ввода, которое мы можем использовать.