Как исправить внедрение FacesContext на странице с ошибкой - PullRequest
0 голосов
/ 09 апреля 2019

У меня есть проект JSF 2.3 WAR со стандартной обработкой исключений JSF. Любая ошибка в запросе отправляется на страницу ошибки jsf, настроенную в web.xml. Я также использую новую улучшенную поддержку CDI JSF 2.3 для внедрения FacesContext.
Проблема в том, что на обычной странице есть какая-то необработанная ошибка и jsf отправляет запрос на страницу ошибки. Тогда я получаю IllegalStateException в com.sun.faces.context.FacesContextImpl.assertNotReleased.

После некоторой отладки я понял, что проблема заключается в том, что я ввожу FacesContext в оба представления. Ключевая проблема в этой ситуации состоит в том, что внедрение FacesContext сохраняется в области запроса, а когда оно снова вводится на странице ошибок, FacesContext, сохраненное в области запроса, уже освобождается и устаревает, так как создается снова при создании страницы ошибки .

Чтобы показать эту ситуацию, я создал небольшой демонстрационный проект, работающий на WildFly 16.0.0. Финал с простой страницей index.xhtml:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
<body>
<p>
    <h:outputText value="Index page"/>
</p>
<p>
    <h:outputText value="Is postback: #{facesContext.postback}"/>
    <h:outputText value="#{index.throwException()}"/>
</p>
</body>
</html>

и error.xhtml:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
<body>

<h:outputText value="Error page"/>
<h:outputText value="Is postback: #{facesContext.postback}"/>

</body>
</html>

Мой web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>

    <error-page>
        <exception-type>java.lang.Throwable</exception-type>
        <location>/error.jsf</location>
    </error-page>

    <default-context-path>/</default-context-path>

    <welcome-file-list>
        <welcome-file>index.jsf</welcome-file>
    </welcome-file-list>
</web-app>

После попытки показать index.jsf я получил следующее исключение:

14:26:12,688 ERROR [io.undertow.request] (default task-1) UT005022: Exception generating error page /error.jsf: javax.servlet.ServletException
    at javax.faces.api@2.3.9.SP01//javax.faces.webapp.FacesServlet.executeLifecyle(FacesServlet.java:725)
    at javax.faces.api@2.3.9.SP01//javax.faces.webapp.FacesServlet.service(FacesServlet.java:451)
    at io.undertow.servlet@2.0.19.Final//io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
    at io.undertow.servlet@2.0.19.Final//io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:81)
    at io.undertow.servlet@2.0.19.Final//io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
    at io.undertow.servlet@2.0.19.Final//io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
    at io.undertow.servlet@2.0.19.Final//io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
    at io.undertow.core@2.0.19.Final//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.core@2.0.19.Final//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.core@2.0.19.Final//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet@2.0.19.Final//io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:274)
    at io.undertow.servlet@2.0.19.Final//io.undertow.servlet.handlers.ServletInitialHandler.dispatchToPath(ServletInitialHandler.java:209)
    at io.undertow.servlet@2.0.19.Final//io.undertow.servlet.spec.RequestDispatcherImpl.error(RequestDispatcherImpl.java:502)
    at io.undertow.servlet@2.0.19.Final//io.undertow.servlet.spec.RequestDispatcherImpl.error(RequestDispatcherImpl.java:428)
    at io.undertow.servlet@2.0.19.Final//io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:331)
    at io.undertow.servlet@2.0.19.Final//io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
    at io.undertow.servlet@2.0.19.Final//io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
    at io.undertow.servlet@2.0.19.Final//io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
    at io.undertow.servlet@2.0.19.Final//io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
    at io.undertow.servlet@2.0.19.Final//io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
    at org.wildfly.extension.undertow@16.0.0.Final//org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
    at org.wildfly.extension.undertow@16.0.0.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
    at org.wildfly.extension.undertow@16.0.0.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
    at org.wildfly.extension.undertow@16.0.0.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
    at org.wildfly.extension.undertow@16.0.0.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1502)
    at io.undertow.servlet@2.0.19.Final//io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
    at io.undertow.servlet@2.0.19.Final//io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
    at io.undertow.servlet@2.0.19.Final//io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
    at io.undertow.core@2.0.19.Final//io.undertow.server.Connectors.executeRootHandler(Connectors.java:364)
    at io.undertow.core@2.0.19.Final//io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
    at org.jboss.threads@2.3.3.Final//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
    at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
    at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
    at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
    at java.base/java.lang.Thread.run(Thread.java:835)
Caused by: java.lang.IllegalStateException
    at com.sun.jsf-impl@2.3.9.SP01//com.sun.faces.context.FacesContextImpl.assertNotReleased(FacesContextImpl.java:692)
    at com.sun.jsf-impl@2.3.9.SP01//com.sun.faces.context.FacesContextImpl.isPostback(FacesContextImpl.java:185)
    at jdk.internal.reflect.GeneratedMethodAccessor29.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at javax.el.api@1.0.13.Final//javax.el.BeanELResolver.getValue(BeanELResolver.java:241)
    at com.sun.jsf-impl@2.3.9.SP01//com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:156)
    at com.sun.jsf-impl@2.3.9.SP01//com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:184)
    at org.glassfish.javax.el@3.0.1-b08-jbossorg-1//com.sun.el.parser.AstValue.getValue(AstValue.java:139)
    at org.glassfish.javax.el@3.0.1-b08-jbossorg-1//com.sun.el.parser.AstValue.getValue(AstValue.java:203)
    at org.glassfish.javax.el@3.0.1-b08-jbossorg-1//com.sun.el.parser.AstDeferredExpression.getValue(AstDeferredExpression.java:63)
    at org.glassfish.javax.el@3.0.1-b08-jbossorg-1//com.sun.el.parser.AstCompositeExpression.getValue(AstCompositeExpression.java:68)
    at org.glassfish.javax.el@3.0.1-b08-jbossorg-1//com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:226)
    at org.jboss.weld.core@3.1.0.Final//org.jboss.weld.module.web.el.WeldValueExpression.getValue(WeldValueExpression.java:50)
    at org.jboss.weld.core@3.1.0.Final//org.jboss.weld.module.web.el.WeldValueExpression.getValue(WeldValueExpression.java:50)
    at com.sun.jsf-impl@2.3.9.SP01//com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:73)
    at javax.faces.api@2.3.9.SP01//javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:170)
    at javax.faces.api@2.3.9.SP01//javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:157)
    at javax.faces.api@2.3.9.SP01//javax.faces.component.UIOutput.getValue(UIOutput.java:140)
    at com.sun.jsf-impl@2.3.9.SP01//com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getValue(HtmlBasicInputRenderer.java:181)
    at com.sun.jsf-impl@2.3.9.SP01//com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getCurrentValue(HtmlBasicRenderer.java:328)
    at com.sun.jsf-impl@2.3.9.SP01//com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeEnd(HtmlBasicRenderer.java:143)
    at javax.faces.api@2.3.9.SP01//javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:595)
    at javax.faces.api@2.3.9.SP01//javax.faces.component.UIComponent.encodeAll(UIComponent.java:1654)
    at javax.faces.api@2.3.9.SP01//javax.faces.component.UIComponent.encodeAll(UIComponent.java:1650)
    at com.sun.jsf-impl@2.3.9.SP01//com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:468)
    at com.sun.jsf-impl@2.3.9.SP01//com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:170)
    at javax.faces.api@2.3.9.SP01//javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:132)
    at javax.faces.api@2.3.9.SP01//javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:132)
    at com.sun.jsf-impl@2.3.9.SP01//com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:102)
    at com.sun.jsf-impl@2.3.9.SP01//com.sun.faces.lifecycle.Phase.doPhase(Phase.java:76)
    at com.sun.jsf-impl@2.3.9.SP01//com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:199)
    at javax.faces.api@2.3.9.SP01//javax.faces.webapp.FacesServlet.executeLifecyle(FacesServlet.java:708)
    ... 34 more

В конце концов, я не уверен, что это ошибка JSF или она сделана специально, и я должен использовать ее по-другому?

...