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?