FullAjaxExceptionHandler with Mojarra 2.2.12 flushes the closing tags when resetting the response #248

Closed
VsevolodGolovanov opened this Issue May 5, 2016 · 6 comments

Projects

None yet

2 participants

@VsevolodGolovanov

Encountered on Wildfly 10.
The exception happens at the Render Response phase.

  • Writing the happy path response into the buffer
  • Exception
  • FullAjaxExceptionHandler#resetResponse does externalContext.responseReset(); - resets the response buffer successfully
  • FullAjaxExceptionHandler#resetResponse does OmniPartialViewContext.getCurrentInstance(context).resetPartialResponse();
    • Writes >]]>]]></update></changes></partial-response> into the buffer
    • com.sun.faces.renderkit.html_basic.HtmlResponseWriter.endDocument() calls writer.flush(); - this flushes the response
    • Attempts to reset the buffer - fails, since the response is already commited:
2016-05-05 16:01:44,308 ERROR [io.undertow.request] (default task-6) UT005023: Exception handling request to /reproducer/index.xhtml: java.lang.IllegalStateException: UT010019: Response already commited
    at io.undertow.servlet.spec.ServletOutputStreamImpl.resetBuffer(ServletOutputStreamImpl.java:716)
    at io.undertow.servlet.spec.HttpServletResponseImpl.reset(HttpServletResponseImpl.java:507)
    at com.sun.faces.context.ExternalContextImpl.responseReset(ExternalContextImpl.java:949)
    at javax.faces.context.ExternalContextWrapper.responseReset(ExternalContextWrapper.java:904)
    at org.omnifaces.util.FacesLocal.responseReset(FacesLocal.java:976)
    at org.omnifaces.util.Faces.responseReset(Faces.java:1291)
    at org.omnifaces.context.OmniPartialViewContext$OmniPartialResponseWriter.reset(OmniPartialViewContext.java:391)
    at org.omnifaces.context.OmniPartialViewContext.resetPartialResponse(OmniPartialViewContext.java:187)
    at org.omnifaces.exceptionhandler.FullAjaxExceptionHandler.resetResponse(FullAjaxExceptionHandler.java:415)
    at org.omnifaces.exceptionhandler.FullAjaxExceptionHandler.canRenderErrorPageView(FullAjaxExceptionHandler.java:398)
    at org.omnifaces.exceptionhandler.FullAjaxExceptionHandler.handleAjaxException(FullAjaxExceptionHandler.java:311)
    at org.omnifaces.exceptionhandler.FullAjaxExceptionHandler.handle(FullAjaxExceptionHandler.java:277)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:119)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:659)
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
    at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
    at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
    at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:284)
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:263)
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:174)
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:793)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
@VsevolodGolovanov

Could be relevant, that between Mojarra 2.2.8 (Wildfly 8.2.0.Final) and 2.2.12 (Wildfly 10.0.0.Final) HtmlResponseWriter gained this code in its endDocument method:

        /*
         * If the FastStringWriter is kept because of an error in <script>
         * writing we get it here and write out the result. See issue #3473
         */
        if (writer instanceof FastStringWriter) {
            FastStringWriter fastStringWriter = (FastStringWriter) writer;
            String result = fastStringWriter.getBuffer().toString();
            fastStringWriter.reset();
            writer = origWriter;
            writer.write(result);
        }

https://java.net/jira/browse/JAVASERVERFACES-3473

@VsevolodGolovanov

The HtmlResponseWriter change is not really relevant, but the same JSF-3473 also added writer.endDocument() call to the PartialResponseWriter:

    public void endDocument() throws IOException {
        endChangesIfNecessary();
        ResponseWriter writer = getWrapped();
        /*
         * Because during a <script> writing an exception can occur we need to
         * make sure the wrapped response only writes one partial-response, but
         * also calls to end the document (so we can properly cleanup in the 
         * wrapped HtmlResponseWriter). See issue #3473.
         */
        if (!(writer instanceof PartialResponseWriter)) {
            writer.endElement("partial-response");
        }
        writer.endDocument();
    }
@BalusC
Member
BalusC commented May 5, 2016

Nice catch. Thank you for reporting!

@BalusC BalusC closed this in 4620359 May 15, 2016
@BalusC
Member
BalusC commented May 15, 2016

Reproduced and fixed in today's 2.4-SNAPSHOT. Can you let me know if it works in your specific case too?

@VsevolodGolovanov

Works fine in the actual app.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment