1

I've got JSF 2.3 WAR project with standard JSF exception handling. Any error in request is dispatching to the jsf error page which is configured inweb.xml. I'm also use new JSF 2.3 improved CDI support to inject FacesContext.
The problem is when on ordinal page is some unhandled error and jsf dispatch the request to the error page. Then I get an IllegalStateException in com.sun.faces.context.FacesContextImpl.assertNotReleased.

After some debugging I've realized that the problem is when I inject FacesContext in both views. The key problem in this situation is that injection of FacesContext is stored in Request Scope and when it is injected again on error page, FacesContext stored in Request scope is already released and obsolete as it is created again when error page is created.

To show this situation I made small demo project running on WildFly 16.0.0.Final with simple index.xhtml page:

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

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

My web.xml is:

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

After trying to show index.jsf I've got the following exception:

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

On the end I'm not sure if this is the JSF bug or it is made by design and I should use it in different way?

Tomazz
  • 23
  • 6
  • Throwing an exception in a getter is not the best design. What if you add a button with an action and throw it from there? (Not saying that is the solution but just to see if it makes a difference) – Kukeltje Apr 09 '19 at 06:40
  • Oh and please read https://stackoverflow.com/questions/10534187/why-use-a-jsf-exceptionhandlerfactory-instead-of-error-page-redirection – Kukeltje Apr 09 '19 at 06:44
  • In this demo project I'm just simulate an exception during Rendering phase. In my real project I'm using omnifaces and their FullAjaxExceptionHandler and got the same result. – Tomazz Apr 09 '19 at 10:50
  • Ok, good additional information. I van try tomorrow to see what happens in my environment. – Kukeltje Apr 09 '19 at 11:19
  • Take a look at https://stackoverflow.com/questions/18410007/jsf-2-global-exception-handling-navigation-to-error-page-not-happening. Take a look at the comments of BalusC (guy from omnifaces) – Thomas Herzog May 05 '19 at 09:22
  • I have the exact same problem in my web application. The problem persists to happen on Wildfly 17.0.1, i.e. Mojarra 2.3.9.SP02. Falling back to JSF 2.2. seems to solve the problem. – Björn Zurmaar Sep 05 '19 at 12:55
  • Unfortunately the problem persists in Wildfly 19 / Mojarra 2.3.9.SP06. Did you find a satisfactory solution to this problem? – Björn Zurmaar Apr 08 '20 at 12:34
  • I didn't find any useful solution. As I remember I didn't use @Inject for FacesContext in my backing been, instead I call FacesContext pragmatically. – Tomazz Apr 09 '20 at 19:33

0 Answers0