[ 
https://issues.apache.org/jira/browse/SLING-2039?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13012890#comment-13012890
 ] 

Felix Meschberger commented on SLING-2039:
------------------------------------------

Investigation shows a problematic interfaction between three bundles:

   * the Engine maintaining buffers per included resource
   * Scripting Core using OnDemandWriter to postpone accessing the actual 
writer until data is written
   * JSP's JspWriter which itself buffers output (8K by default in Sling's 
Jasper)

What happens is as follows:

(1) html.jsp writes to the JspWriter 1 which is based on OnDemandWriter 1. The 
actual response writer is not retrieved yet
(2) list.html.jsp is included
(3) list.html.jsp writes to JspWriter 2 which is based on OnDemandWriter 2
(4) Once list.html.jsp writes data in excess of the JspWriter2's buffer the 
data is written to OnDemandWriter 2.
(5) This causes OnDemandWriter 2 to write to JspWriter 1.
(6) This will immediately cause JspWriter 1 to have to write since the buffer 
overflows.
(7) Thus OnDemandWriter 1 gets the PrintWriter from the 
SlingHttpServletResponseImpl
(8) SlingHttpServlteResponseImpl gets a BufferedPrintWriter 2 from the 
currentContentData (which is related to the list.html.jsp script)
(8a) the BufferedPrintWriter 2 is backed by BufferedPrintWriter 1 related to 
the html.jsp script
(9) OnDemandWriter 1 writes to the BufferedPrintWriter
(10) list.html.jsp terminates and the of JspWriter 2 is flushed to 
OnDemandWriter 2 and in turn to JspWriter 1 (buffering again)
(11) upon termination of list.html.jsp the currentContentData is disposed and 
BufferedPrintWriter 2 is written to the BufferedPrintWriter 1
(11) html.jsp writes some more data to JspWriter 1
(12) html.jsp terminates and remaining data from JspWriter 1 is flushed to 
OnDemandWriter 1 and thus BufferedPrintWriter 2
(13) upon termination of html.jsp the currentContentData is disposed and 
BufferedPrintWriter 1 sent to the client

The problem is that the "lowest" OnDemandWriter 1 is backed by 
BufferedPrintWriter 2 which belonged to the highest included request. But since 
BufferedPrintWriter 2 is not flushed any more when the html.jsp script ends 
(because it has already been flushed when list.html.jsp ended) some output 
remains in the defunct buffer.

The simplest fix is to not use a buffer per ContentData but a single global 
buffer for the RequestData. This also uses less memory, is easier to handle 
(less cycles spent managing it), simpler to maintain. Having a buffer per 
ContentData dates way back before Apache Sling and has probably (cannot 
remember any more, sorry) done for some stupid reason in the 
pre-HttpServletWrapper days.....

> Output lost with JSPs and sling:include
> ---------------------------------------
>
>                 Key: SLING-2039
>                 URL: https://issues.apache.org/jira/browse/SLING-2039
>             Project: Sling
>          Issue Type: Bug
>          Components: Engine
>    Affects Versions: Engine 2.2.2
>            Reporter: Felix Meschberger
>            Assignee: Felix Meschberger
>             Fix For: Engine 2.2.4
>
>
> Using a single output buffer per included resource may lead to loss of 
> response data.
> Consider this setup:
>    - main request handled by html.jsp. Some data is written to "out" 
> (buffering JspWriter)
>    - html.jsp incudes another jsp (list.html.jsp) which in turn writes more 
> data
>    - html.jsp continues writing to the output
> If list.html.jsp sends less than the JspWriter's buffer, everything is fine.
> As soon as the JspWritter buffer overflows, though, only the first bytes of 
> the actual response (exactly the size of the JspWriter buffer) is returned.

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

Reply via email to