Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot call reset() after response has been committed #1566

Closed
andrei-ivanov opened this issue Jun 30, 2016 · 48 comments
Closed

Cannot call reset() after response has been committed #1566

andrei-ivanov opened this issue Jun 30, 2016 · 48 comments
Labels
6.0.5 🐞 defect Bug...Something isn't working
Milestone

Comments

@andrei-ivanov
Copy link
Contributor

Hi,
I'm seeing a worrying number of exceptions regarding PrimeExceptionHandler trying to reset the response after it was commited when handling Ajax exceptions.

As far as I see, it checks if the response is committed (at

), but I'm wondering if the Mojarra workaround that follows triggers the commit of the response, calling the writer methods (including endDocument(), which seems to flush the response writer).

Using PF 6.0 with Mojarra 2.2.13 on Tomcat 8.0.36

30-Jun-2016 14:44:05.532 SEVERE [http-apr-443-exec-70] org.primefaces.application.exceptionhandler.PrimeExceptionHandler.handle Could not handle exception!
 java.lang.IllegalStateException: Cannot call reset() after response has been committed
    at org.apache.catalina.connector.ResponseFacade.reset(ResponseFacade.java:353)
    at javax.servlet.ServletResponseWrapper.reset(ServletResponseWrapper.java:194)
    at javax.servlet.ServletResponseWrapper.reset(ServletResponseWrapper.java:194)
    at javax.servlet.ServletResponseWrapper.reset(ServletResponseWrapper.java:194)
    at com.sun.faces.context.ExternalContextImpl.responseReset(ExternalContextImpl.java:949)
    at org.primefaces.application.exceptionhandler.PrimeExceptionHandler.handleAjaxException(PrimeExceptionHandler.java:156)
    at org.primefaces.application.exceptionhandler.PrimeExceptionHandler.handle(PrimeExceptionHandler.java:98)
    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 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:178)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at com.ericsson.gscro.common.security.web.filter.SecurityMdcFilter.doFilter(SecurityMdcFilter.java:60)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:178)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:178)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:178)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:112)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:206)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:121)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:106)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.access.channel.ChannelProcessingFilter.doFilter(ChannelProcessingFilter.java:157)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1099)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:670)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2508)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2497)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
@tandraschko
Copy link
Member

Please provide a simple small maven/jetty app.

@andrei-ivanov
Copy link
Contributor Author

Well, since I only see this error in the production logs, I don't think I can create a simple reproducer :-(
I can't tell what kind of request is triggering this.

Isn't my analysis regarding the Mojarra workaround helpful at all?

@tandraschko
Copy link
Member

I can't do any bugfix without an example to replicate it, so therefor it's only partial helpful ;)

@tandraschko tandraschko added the 🐞 defect Bug...Something isn't working label Jun 30, 2016
@andrei-ivanov
Copy link
Contributor Author

andrei-ivanov commented Jul 1, 2016

Hmm, managed to reproduce it quickly before the end of the program.
Going to the 2nd page on a lazy datatable triggers the issue (with Mojarra).

dataModel = new LazyDataModel<User>() {
    @Override
    public List<User> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
        if (first > 0) {
            throw new RuntimeException("Test");
        }
        // initialize result...
        return result;
    }

@tandraschko
Copy link
Member

As i said, please provide a full working sample application with maven and jetty

@andrei-ivanov
Copy link
Contributor Author

andrei-ivanov commented Jul 4, 2016

I've taken the lazy datatable showcase and I've modified LazyCarDataModel, adding

if (first > 0) {
      throw new RuntimeException("Test");
}

at the beginning of the load method.
See the attachment: pf-1566.zip

The result in Jetty when going to the next page (http://localhost:8080/showcase/ui/data/datatable/lazy.xhtml):

Iul 04, 2016 12:14:27 PM org.primefaces.application.exceptionhandler.PrimeExceptionHandler handle
SEVERE: Could not handle exception!
java.lang.IllegalStateException: cannot reset buffer on committed response
        at org.eclipse.jetty.server.Response.resetBuffer(Response.java:1245)
        at org.eclipse.jetty.server.Response.resetForForward(Response.java:1237)
        at org.eclipse.jetty.server.Response.reset(Response.java:1183)
        at com.sun.faces.context.ExternalContextImpl.responseReset(ExternalContextImpl.java:949)
        at org.primefaces.application.exceptionhandler.PrimeExceptionHandler.handleAjaxException(PrimeExceptionHandler.java:156)
        at org.primefaces.application.exceptionhandler.PrimeExceptionHandler.handle(PrimeExceptionHandler.java:98)
        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 org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:837)
        at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:583)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
        at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
        at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)
        at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
        at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
        at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:213)
        at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:119)
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
        at org.eclipse.jetty.server.Server.handle(Server.java:524)
        at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319)
        at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)
        at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
        at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
        at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
        at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
        at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
        at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
        at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
        at java.lang.Thread.run(Unknown Source)

@tandraschko
Copy link
Member

Did you try to set javax.faces.FACELETS_BUFFER_SIZE as mentioned in the userguide?

@andrei-ivanov
Copy link
Contributor Author

Seems I missed that part.
Unfortunately, it doesn't seem to fix it 👎 (
I've tested with 1024 (the default value from the standard, seen from https://java.net/jira/browse/JAVASERVERFACES-2068) and up to 8192.

I've setup a breakpoint in com.sun.faces.application.view.FaceletViewHandlingStrategy.initialize() to make sure it reads it properly.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
        version="3.1">
    <context-param>
        <param-name>javax.faces.FACELETS_BUFFER_SIZE</param-name>
        <param-value>8192</param-value>
    </context-param>
</web-app>

@tandraschko
Copy link
Member

I would try something like 100.000 to see if if it will be fixed ;)

@andrei-ivanov
Copy link
Contributor Author

I just did, didn't fix it :(

I've setup a breakpoint to see how the response gets marked as committed.
It is just as described in my initial analysis.
The Mojarra workaround that follows triggers the commit of the response, calling the writer methods, including endDocument(), which flushes the response writer and the buffer.
I don't think it matters what buffer size you have if you flush the buffer.

Daemon Thread [http-apr-8080-exec-7] (Suspended (modification of field commited in Response))   
    owns: AprEndpoint$AprSocketWrapper  (id=79) 
    Response.setCommitted(boolean) line: 225    
    InternalAprOutputBuffer.commit() line: 147  
    Http11AprProcessor(AbstractHttp11Processor<S>).action(ActionCode, Object) line: 740 
    Response.action(ActionCode, Object) line: 179   
    Response.sendHeaders() line: 350    
    OutputBuffer.doFlush(boolean) line: 338 
    OutputBuffer.flush() line: 320  
    CoyoteWriter.flush() line: 94   
    HtmlResponseWriter.endDocument() line: 442  
    PartialResponseWriter.endDocument() line: 152   
    PartialViewContextImpl$DelayedInitPartialResponseWriter(PartialResponseWriter).endDocument() line: 152  
    PrimePartialResponseWriter.endDocument() line: 97   
    PrimeExceptionHandler.handleAjaxException(FacesContext, Throwable, ExceptionInfo) line: 152 
    PrimeExceptionHandler.handle() line: 98 
    RenderResponsePhase(Phase).doPhase(FacesContext, Lifecycle, ListIterator<PhaseListener>) line: 119  
    LifecycleImpl.render(FacesContext) line: 219    
    FacesServlet.service(ServletRequest, ServletResponse) line: 659 
    ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 292  
    ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 207  
    WsFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 52    
    ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 240  
    ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 207  
    StandardWrapperValve.invoke(Request, Response) line: 212    
    StandardContextValve.invoke(Request, Response) line: 106    
    NonLoginAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 502    
    StandardHostValve.invoke(Request, Response) line: 141   
    ErrorReportValve.invoke(Request, Response) line: 79 
    AccessLogValve(AbstractAccessLogValve).invoke(Request, Response) line: 616  
    StandardEngineValve.invoke(Request, Response) line: 88  
    CoyoteAdapter.service(Request, Response) line: 528  
    Http11AprProcessor(AbstractHttp11Processor<S>).process(SocketWrapper<S>) line: 1099 
    Http11AprProtocol$Http11ConnectionHandler(AbstractProtocol$AbstractConnectionHandler<S,P>).process(SocketWrapper<S>, SocketStatus) line: 670    
    AprEndpoint$SocketProcessor.doRun() line: 2508  
    AprEndpoint$SocketProcessor.run() line: 2497    
    ThreadPoolExecutor(ThreadPoolExecutor).runWorker(ThreadPoolExecutor$Worker) line: 1142  
    ThreadPoolExecutor$Worker.run() line: 617   
    TaskThread$WrappingRunnable.run() line: 61  
    TaskThread(Thread).run() line: 745  

@tandraschko
Copy link
Member

The workaround was introduced because: #823

Maybe you could check if mojarra changed something in their responseWriter?

@tandraschko
Copy link
Member

Maybe we could just remove #endDocument but leave the other 2 #end calls to fix both issues?

@andrei-ivanov
Copy link
Contributor Author

andrei-ivanov commented Jul 4, 2016

Eh, I've added a comment to the commit, suggesting a ticket for Mojarra, but it was ignored 2d263ef2d17db2188a1964a729b54f906c6de89f0

Should I ask for a full working sample application with maven to reproduce #823? :-D
I don't see a unit test being introduced in that commit.

@tandraschko
Copy link
Member

i don't have a example as it was fixed by cagatay :P
We currently don't have unit tests for such hacks/integration thigns

@andrei-ivanov
Copy link
Contributor Author

I'll try sometime later today to see if I can reproduce #823 without the hack and see if removing endDocument helps.

@andrei-ivanov
Copy link
Contributor Author

I was thinking that since you have my reproducer, you could try to use that to reproduce #823 :-D

@tandraschko
Copy link
Member

:D i don't have time, sorry

@andrei-ivanov
Copy link
Contributor Author

Can you ask cagatay? It's his regression :-/

@tandraschko
Copy link
Member

I could ping him but he is likely very busy.
You have 3 solutions:

  • test both cases, provide a PR/patch and 2 samples with jetty/maven, i can run your tests, verify it and apply your patch
  • PrimeFaces pro
  • wait till someone other likes to fix your problem

@andrei-ivanov
Copy link
Contributor Author

Got it, thanks for your help.

@andrei-ivanov
Copy link
Contributor Author

Hmm, seems this is "caused" by https://java.net/jira/browse/JAVASERVERFACES-3647, starting from 2.2.10

@andrei-ivanov
Copy link
Contributor Author

Seems the workaround is really needed there, and I even found one more case where that has to be called.
The problem is that endDocument() flushes the buffer and I can't find a way to prevent that from happening :(

@tandraschko
Copy link
Member

AFAICS endDocument is only called that mojarra resets the internal FastStringWriter?
I would say, it's even invalid to call endDocument in our case as its really different how the implementations behave.

@andrei-ivanov
Copy link
Contributor Author

andrei-ivanov commented Sep 7, 2016

From my memory, as I don't have the code in my face, it's also calling the wrapped writers endDocument and one of them (I think PartialViewContextImpl$DelayedInitPartialResponseWriter) end the changes element, based on some internal boolean.
I tried ending that element by hand, but because that boolean never gets reset to false, it ends it again, duplicating the end tag, when we actually want to call the endDocument() at the end, before calling responseComplete().

tandraschko added a commit that referenced this issue Sep 7, 2016
@tandraschko tandraschko added this to the 6.1 milestone Sep 7, 2016
@tandraschko
Copy link
Member

Please give it a try ;)

@andrei-ivanov
Copy link
Contributor Author

Will do, but on Monday, when I'll get back at the office.
Thanks for the help :-)

@andrei-ivanov
Copy link
Contributor Author

Uf, still doesn't work :(
The response is still broken by PartialViewContextImpl$DelayedInitPartialResponseWriter.

This is where javax.faces.context.PartialResponseWriter.inChanges is set to true.

PartialViewContextImpl$DelayedInitPartialResponseWriter(PartialResponseWriter).startChangesIfNecessary() line: 382  
    PartialViewContextImpl$DelayedInitPartialResponseWriter(PartialResponseWriter).startUpdate(String) line: 220    
    PrimePartialResponseWriter.startUpdate(String) line: 150    
    PartialViewContextImpl$PhaseAwareVisitCallback.visit(VisitContext, UIComponent) line: 580   
    PartialVisitContext.invokeVisitCallback(UIComponent, VisitCallback) line: 183   
    DataTable(UIData).visitTree(VisitContext, VisitCallback) line: 827  
    HtmlPanelGroup(UIComponent).visitTree(VisitContext, VisitCallback) line: 1700   
    HtmlForm(UIComponent).visitTree(VisitContext, VisitCallback) line: 1700 
    HtmlForm(UIForm).visitTree(VisitContext, VisitCallback) line: 362   
    Panel(UIComponent).visitTree(VisitContext, VisitCallback) line: 1700    
    LayoutUnit(UIComponent).visitTree(VisitContext, VisitCallback) line: 1700   
    Layout(UIComponent).visitTree(VisitContext, VisitCallback) line: 1700   
    HtmlBody(UIComponent).visitTree(VisitContext, VisitCallback) line: 1700 
    UIViewRoot(UIComponent).visitTree(VisitContext, VisitCallback) line: 1700   
    PartialViewContextImpl.processComponents(UIComponent, PhaseId, Collection<String>, FacesContext) line: 403  
    PartialViewContextImpl.processPartial(PhaseId) line: 322    
    PrimePartialViewContext.processPartial(PhaseId) line: 57    
    UIViewRoot.encodeChildren(FacesContext) line: 1004  
    UIViewRoot(UIComponent).encodeAll(FacesContext) line: 1856  
    FaceletViewHandlingStrategy.renderView(FacesContext, UIViewRoot) line: 432  
    MultiViewHandler.renderView(FacesContext, UIViewRoot) line: 134 
    RenderResponsePhase.execute(FacesContext) line: 120 
    RenderResponsePhase(Phase).doPhase(FacesContext, Lifecycle, ListIterator<PhaseListener>) line: 101  
    LifecycleImpl.render(FacesContext) line: 219    

Calling endDocument() triggers an automatic call to endChanges(), which means the generated XML is broken.

PartialViewContextImpl$DelayedInitPartialResponseWriter(PartialResponseWriter).endChangesIfNecessary() line: 396    
    PartialViewContextImpl$DelayedInitPartialResponseWriter(PartialResponseWriter).endDocument() line: 141  
    PrimePartialResponseWriter.endDocument() line: 103  
    PrimeExceptionHandler.handleAjaxException(FacesContext, Throwable, ExceptionInfo) line: 237 
    PrimeExceptionHandler.handle() line: 98 
    RenderResponsePhase(Phase).doPhase(FacesContext, Lifecycle, ListIterator<PhaseListener>) line: 119  
    LifecycleImpl.render(FacesContext) line: 219    
<?xml version='1.0' encoding='UTF-8'?>
<partial-response id="j_id1"><changes><update id="exceptionDialog"><![CDATA[<div id="exceptionDialog"
 class="ui-dialog ui-widget ui-widget-content ui-corner-all ui-shadow ui-hidden-container"><div class
="ui-dialog-titlebar ui-widget-header ui-helper-clearfix ui-corner-top"><span id="exceptionDialog_title"
 class="ui-dialog-title">An error has occured!</span><a href="#" class="ui-dialog-titlebar-icon ui-dialog-titlebar-close
 ui-corner-all" aria-label="Close"><span class="ui-icon ui-icon-closethick"></span></a></div><div class
="ui-dialog-content ui-widget-content">
        Message: Test <br />
        Type: java.lang.RuntimeException <br /></div></div><script id="exceptionDialog_s" type="text/javascript"
>$(function(){PrimeFaces.cw("Dialog","exceptionDialogWV",{id:"exceptionDialog",width:"500",height:"100"
});});</script>]]></update><eval><![CDATA[var hf=function(type,message,timestampp){PF('exceptionDialogWV'
).show()};hf.call(this,"java.lang.RuntimeException","Test","2016-09-12 14:16:37");]]></eval></changes
></changes></partial-response>

@andrei-ivanov
Copy link
Contributor Author

endChangesIfNecessary() is private and called from 3 places:

  • endDocument
  • redirect
  • startError

So I don't see how to make it ignore that inChanges flag :(

@tandraschko
Copy link
Member

Hmpf? I thought the problem was the endDocument call? If not, then our other workaround is completely unrelated to this issue?

@andrei-ivanov
Copy link
Contributor Author

Well, the problem with endDocument is that it flushes the output buffer, so it cannot be reset anymore.
But calling it had another side effect, that it was setting inChanges to false, which means that the 2nd call would not call endChanges.

@andrei-ivanov
Copy link
Contributor Author

andrei-ivanov commented Sep 12, 2016

Found a workaround:

writer.startError("");
writer.endError();

Before writer.getWrapped().endElement("changes");

I think writer.getWrapped().endElement("changes"); can be removed, as javax.faces.context.PartialResponseWriter.startError(String errorName) also does that by itself.

tandraschko added a commit that referenced this issue Sep 12, 2016
@tandraschko
Copy link
Member

done, please test ;)

@andrei-ivanov
Copy link
Contributor Author

andrei-ivanov commented Sep 12, 2016

Seems to work now, the response received by the browser is fine now :)
Not sure it it matters, but this is how the response that was reset looks:

<?xml version='1.0' encoding='UTF-8'?>
<partial-response id="j_id1"><changes><update id="siteAccessRequestsTable"><![CDATA[]]>]]></insert>]]></update></changes><error><error-name></error-name><error-message><![CDATA[]]></error-message></error></changes></partial-response>

Doesn't seem correct, but since the response will be reset, not sure if it actually matters.

@tandraschko
Copy link
Member

Thats not the response which is received by the browser? where do you got this from?

@andrei-ivanov
Copy link
Contributor Author

Well, after the workaround is applied, by calling the various writer methods, the buffer is reset on line 166: externalContext.responseReset();.
Using a debugger I grabbed the content before it was reset :-)

@andrei-ivanov
Copy link
Contributor Author

So, any interest in fixing the response in the buffer that will be reset?
If not, I think this issue can be closed and I hope merged to 6.0.5 :-)

@tandraschko
Copy link
Member

I don't think that we can fix for every case. We could do it if we would completely develop our own ResponseWriter etc.

@andrei-ivanov
Copy link
Contributor Author

Yes, I also don't think it matters what happens to the throwaway response.
@mertsincan Will you please merge this for 6.0.5?

@tandraschko
Copy link
Member

I always depends on what you set as BUFFER_SIZE. If the BUFFER_SIZE is to small, the response could be broken anyway. Setting the buffer to big means that you loss a little bit performance.
ExceptionHandling is a stupid thing and should be done in the JSF impl actually.

@andrei-ivanov
Copy link
Contributor Author

So, can this issue be closed? :-)
Who should I ask for it to be merged for 6.0.5?

@tandraschko
Copy link
Member

I could also only ping @mertsincan, so lets see if he will his mails ;)

@andrei-ivanov
Copy link
Contributor Author

@mertsincan Will you please merge this for 6.0.5?

@mertsincan
Copy link
Member

I'm sorry for the late reply. I was on holiday :) I'll add it into 6.0.5.

smellinet pushed a commit to smellinet/primefaces that referenced this issue Oct 1, 2016
smellinet pushed a commit to smellinet/primefaces that referenced this issue Oct 1, 2016
@fosorio
Copy link

fosorio commented Jul 10, 2018

Excuse me, but can you clarify if the workaround to close invalid partial output due to open tags (PrimeExceptionHandler.handleAjaxException) is expected to work for all cases? Why does it perform this specific sequence of actions?: (I'm using primefaces 6.2, mojarra 2.2.14)

                    writer.endCDATA();

                    writer.endInsert();
                    writer.endUpdate();

                    writer.startError("");
                    writer.endError();

                    writer.getWrapped().endElement("changes");
                    writer.getWrapped().endElement("partial-response");

This breaks the partial response in my case, which doesn't allow an ajax error dialog on the client side to open up, as chrome breaks with a javascript error: "Request return with error:parsererror."

<?xml version='1.0' encoding='UTF-8'?>
<partial-response id="j_id1"><changes><eval><![CDATA[if(window.PrimeFaces){PrimeFaces.ajax.Utils.loadScripts(['/dtax/javax.faces.resource/tree.js.jsf?ln=oam.custom.tree2.javascript','/dtax/javax.faces.resource/cookielib.js.jsf?ln=oam.custom.tree2.javascript']);}]]></eval><eval><![CDATA[if(window.PrimeFaces){PrimeFaces.ajax.Utils.loadScripts(['/dtax/javax.faces.resource/tree.js.jsf?ln=oam.custom.tree2.javascript','/dtax/javax.faces.resource/cookielib.js.jsf?ln=oam.custom.tree2.javascript']);}]]></eval><update id="mainForm:cityMappingGrid"><![CDATA[<table id="mainForm:cityMappingGrid" class="centered" style="text-align: left">
<tbody>
<tr>
<td>State: </td>
<td>AE: </td>
</tr>
<tr>
<td>Map By: </td>
<td><select id="mainForm:selectMapBy" name="mainForm:selectMapBy" size="1" onchange="PrimeFaces.ab({s:this,e:&quot;valueChange&quot;,p:&quot;mainForm&quot;,u:&quot;mainForm:cityMappingGrid mainForm:commandButtonsGrid&quot;,onco:function(xhr,status,args){clearFields();}});">	<option value="NONE">-- Select --</option>
	<option value="both" selected="selected">City/County</option>
	<option value="city">City</option>
</select></td>
</tr>
<tr>
<td>County: </td>
<td><select id="mainForm:selectCounty" name="mainForm:selectCounty">]]>]]></insert>]]></update></changes><error><error-name></error-name><error-message><![CDATA[]]></error-message></error></changes></partial-response><?xml version='1.0' encoding='UTF-8'?>
<partial-response id="j_id1"><changes><update id="exceptionDialog"><![CDATA[<div id="exceptionDialog" class="ui-dialog ui-widget ui-widget-content ui-corner-all ui-shadow ui-hidden-container"><div class="ui-dialog-titlebar ui-widget-header ui-helper-clearfix ui-corner-top"><span id="exceptionDialog_title" class="ui-dialog-title">Exception during ajax request: java.lang.NullPointerException occured</span><a href="#" class="ui-dialog-titlebar-icon ui-dialog-titlebar-close ui-corner-all" aria-label="Close"><span class="ui-icon ui-icon-closethick"></span></a></div><div class="ui-dialog-content ui-widget-content"><span class="warning">An unexpected processing error has occurred.
Message:  <br />
StackTrace: java.lang.NullPointerException<br/>	at [...STACKTRACE EDITED]</div></div><script id="exceptionDialog_s" type="text/javascript">PrimeFaces.cw("Dialog","exceptionDialog",{id:"exceptionDialog",width:"650px",height:"500px"});</script>]]></update><eval><![CDATA[var hf=function(type,message,timestampp){PF('exceptionDialog').show();};hf.call(this,"java.lang.NullPointerException","null","2018-07-10 00:41:18");]]></eval></changes></partial-response>

Notice in the response that the sequence

name="mainForm:selectCounty">]]>]]></ insert>]]></ update></ changes>

is malformed, as there are too many cdata end sections, a non existent insert start tag, and a duplicate </ changes> end tag.

If this is a known issue, are there known workarounds you can suggest?

Thanks

@maelmonnier
Copy link

Same problem with Primefaces 6.1 (using jsf-undertow-spring-boot-starter 2.4.1). Upgraded JSF from org.glassfish from 2.2.14 to 2.2.18 without success. Tried to switch back to Tomcat without success too. Two partial-response elements are written.
responseResetted flag is true but response doesn't seem to be actually resetted.

Here is my stack in the PrimeExceptionHandler :

handleAjaxException:183, PrimeExceptionHandler (org.primefaces.application.exceptionhandler)
handle:98, PrimeExceptionHandler (org.primefaces.application.exceptionhandler)
doPhase:119, Phase (com.sun.faces.lifecycle)
render:219, LifecycleImpl (com.sun.faces.lifecycle)
service:659, FacesServlet (javax.faces.webapp)
handleRequest:74, ServletHandler (io.undertow.servlet.handlers)
doFilter:129, FilterHandler$FilterChainImpl (io.undertow.servlet.handlers)
doFilterInternal:178, OpenEntityManagerInViewFilter (org.springframework.orm.jpa.support)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
doFilter:61, ManagedFilter (io.undertow.servlet.core)
doFilter:131, FilterHandler$FilterChainImpl (io.undertow.servlet.handlers)
doFilter:232, MonitoringFilter (net.bull.javamelody)
doFilter:209, MonitoringFilter (net.bull.javamelody)
doFilter:61, ManagedFilter (io.undertow.servlet.core)
doFilter:131, FilterHandler$FilterChainImpl (io.undertow.servlet.handlers)
doFilter:317, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
invoke:127, FilterSecurityInterceptor (org.springframework.security.web.access.intercept)
doFilter:91, FilterSecurityInterceptor (org.springframework.security.web.access.intercept)
doFilter:331, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilter:114, ExceptionTranslationFilter (org.springframework.security.web.access)
doFilter:331, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilter:137, SessionManagementFilter (org.springframework.security.web.session)
doFilter:331, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilter:111, AnonymousAuthenticationFilter (org.springframework.security.web.authentication)
doFilter:331, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilter:170, SecurityContextHolderAwareRequestFilter (org.springframework.security.web.servletapi)
doFilter:331, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilter:63, RequestCacheAwareFilter (org.springframework.security.web.savedrequest)
doFilter:331, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilter:200, AbstractAuthenticationProcessingFilter (org.springframework.security.web.authentication)
doFilter:331, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilter:116, LogoutFilter (org.springframework.security.web.authentication.logout)
doFilter:331, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilterInternal:66, HeaderWriterFilter (org.springframework.security.web.header)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
doFilter:331, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilter:105, SecurityContextPersistenceFilter (org.springframework.security.web.context)
doFilter:331, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilterInternal:56, WebAsyncManagerIntegrationFilter (org.springframework.security.web.context.request.async)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
doFilter:331, FilterChainProxy$VirtualFilterChain (org.springframework.security.web)
doFilterInternal:214, FilterChainProxy (org.springframework.security.web)
doFilter:177, FilterChainProxy (org.springframework.security.web)
invokeDelegate:347, DelegatingFilterProxy (org.springframework.web.filter)
doFilter:263, DelegatingFilterProxy (org.springframework.web.filter)
doFilter:61, ManagedFilter (io.undertow.servlet.core)
doFilter:131, FilterHandler$FilterChainImpl (io.undertow.servlet.handlers)
doFilterInternal:99, RequestContextFilter (org.springframework.web.filter)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
doFilter:61, ManagedFilter (io.undertow.servlet.core)
doFilter:131, FilterHandler$FilterChainImpl (io.undertow.servlet.handlers)
doFilterInternal:109, HttpPutFormContentFilter (org.springframework.web.filter)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
doFilter:61, ManagedFilter (io.undertow.servlet.core)
doFilter:131, FilterHandler$FilterChainImpl (io.undertow.servlet.handlers)
doFilterInternal:81, HiddenHttpMethodFilter (org.springframework.web.filter)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
doFilter:61, ManagedFilter (io.undertow.servlet.core)
doFilter:131, FilterHandler$FilterChainImpl (io.undertow.servlet.handlers)
doFilterInternal:197, CharacterEncodingFilter (org.springframework.web.filter)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
doFilter:61, ManagedFilter (io.undertow.servlet.core)
doFilter:131, FilterHandler$FilterChainImpl (io.undertow.servlet.handlers)
handleRequest:84, FilterHandler (io.undertow.servlet.handlers)
handleRequest:62, ServletSecurityRoleHandler (io.undertow.servlet.handlers.security)
handleRequest:64, ServletChain$1 (io.undertow.servlet.handlers)
handleRequest:36, ServletDispatchingHandler (io.undertow.servlet.handlers)
handleRequest:132, SSLInformationAssociationHandler (io.undertow.servlet.handlers.security)
handleRequest:57, ServletAuthenticationCallHandler (io.undertow.servlet.handlers.security)
handleRequest:43, PredicateHandler (io.undertow.server.handlers)
handleRequest:46, AbstractConfidentialityHandler (io.undertow.security.handlers)
handleRequest:64, ServletConfidentialityConstraintHandler (io.undertow.servlet.handlers.security)
handleRequest:60, AuthenticationMechanismsHandler (io.undertow.security.handlers)
handleRequest:77, CachedAuthenticatedSessionHandler (io.undertow.servlet.handlers.security)
handleRequest:43, AbstractSecurityContextAssociationHandler (io.undertow.security.handlers)
handleRequest:43, PredicateHandler (io.undertow.server.handlers)
handleRequest:43, PredicateHandler (io.undertow.server.handlers)
handleFirstRequest:292, ServletInitialHandler (io.undertow.servlet.handlers)
access$100:81, ServletInitialHandler (io.undertow.servlet.handlers)
call:138, ServletInitialHandler$2 (io.undertow.servlet.handlers)
call:135, ServletInitialHandler$2 (io.undertow.servlet.handlers)
call:48, ServletRequestContextThreadSetupAction$1 (io.undertow.servlet.core)
call:43, ContextClassLoaderSetupAction$1 (io.undertow.servlet.core)
dispatchRequest:272, ServletInitialHandler (io.undertow.servlet.handlers)
access$000:81, ServletInitialHandler (io.undertow.servlet.handlers)
handleRequest:104, ServletInitialHandler$1 (io.undertow.servlet.handlers)
executeRootHandler:336, Connectors (io.undertow.server)
run:830, HttpServerExchange$1 (io.undertow.server)
runWorker:1149, ThreadPoolExecutor (java.util.concurrent)
run:624, ThreadPoolExecutor$Worker (java.util.concurrent)
run:748, Thread (java.lang)

I would be glad if you could let me know if there is a compatibility problem with Spring Boot or if someone else has the same problem.

Note : I had the same problem with FullAjaxExceptionHandler of Omnifaces.

@tandraschko
Copy link
Member

tandraschko commented Oct 1, 2018

See: https://stackoverflow.com/questions/5893460/problems-with-redirect-after-catching-exception (little bit different case but probably the same root cause ;))

@tandraschko
Copy link
Member

If this doesn't help, and everything mentioned in the ticket, you can still try myfaces.

@maelmonnier
Copy link

Thanks for your responses and suggestions.

I had already tried to change jsf.facelets-buffer-size in my application.yml. I increased it from 100K to 1MB as suggested by BalusC in the response, but without any effect. (I have increase it even to 10 MB)

I tried to switch to myfaces, but it is not compatible with the application (even the login page becomes very badly rendered with el not evaluated).

With Primefaces 5.0 error pages declared via ErrorPageRegistrar are not taken into account, so there is a NullPointerException in PrimeExceptionHandler.
In Primefaces 5.3 which correct some issues about error pages, I had a "java.lang.IllegalStateException: CDATA tags may not nest" at org.primefaces.application.exceptionhandler.PrimeExceptionHandler.handleAjaxException(PrimeExceptionHandler.java:199) ~[primefaces-5.3.jar:5.3]

I try again with Primefaces 5.0 with an extended PrimeExceptionHandlerFactory and PrimeExceptionHandler to force an error page, but I have the same problem as with Primefaces 6.1 with two partial-response :

<?xml version='1.0' encoding='UTF-8'?>
<partial-response id="j_id1"><changes><update id="form:j_idt31"><![CDATA[<span id="form:j_idt31"></span><script id="form:j_idt31_s" type="text/javascript">$(function(){PrimeFaces.cw('Growl','widget_form_j_idt31',{id:'form:j_idt31',sticky:false,life:6000,escape:true,msgs:[]});});</script>]]></update><update id="fdialog"><![CDATA[
<form id="fdialog" name="fdialog" method="post" action="/app/administration/utilisateurs.xhtml" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="fdialog" value="fdialog" />
[...]<input id="fdialog:email" name="fdialog:email" type="text"><?xml version='1.0' encoding='UTF-8'?>
<partial-response id="j_id1"></changes><redirect url="/gcblo-ihm/errors/error500.xhtml"></redirect>]]>]]></update></partial-response>

Perhaps interesting to investigate this problem I have a NoSuchElementException in java EL :
javax.el.ELException: /administration/utilisateurs.xhtml @100,132 value="#{utilisateurBean.utilisateurSelectionne.courriel}": java.util.NoSuchElementException

So previous partial response is broken during the JSF render phase. We can see that form element is never closed as some p:inputText elements cannot be rendered. I am wondering if JSF writer is not in a bad state after that and its buffer could not be reset properly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
6.0.5 🐞 defect Bug...Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants