Hi Carsten,

> On 14 Jun 2022, at 17:14, Carsten Ziegeler <[email protected]> wrote:
> 
> Hi Radu,
> 
> there is a difference between flush and close. If some downstream code is 
> flushing then the dispatcher can still call flushBuffer.

Sure there is. However, in our case the dispatcher’s [1] and writer’s flush [3] 
methods are the ones that fail, since they throw an exception if the stream was 
closed. I don’t think this is correct. Flush should send the content to the 
client and commit the response, but IMO should not throw if the response has 
already been committed. The Servlet 3.1 specification [4] also doesn’t say that 
this method should throw an exception (see section 5.1 of the linked document).

> But if some downstream code is closing, then flushing will of course not 
> work. To be it sounds like there is some code illegally closing the response. 
> I think that should be fixed instead. I remember that we needed to fix this 
> in other servlets using johnzon as well and avoid that the json writer closes 
> the output stream/writer.

I don’t think that servlets should not be allowed to close the response object. 
While they indeed haven’t opened the stream, the Servlet 3.1 specification [4] 
mentions this in section “5.7. Lifetime of the Response Object”:

"Each response object is valid only within the scope of a servlet’s service 
method, or within the scope of a filter’s doFilter method, unless the 
associated request object has asynchronous processing enabled for the 
component. If asynchronous processing on the associated request is started, 
then the request object remains valid until complete method on AsyncContext is 
called.”

There are other aspects here as well, besides thinking about who is the owner 
of the stream (the container or the response object): a servlet should be able 
to close the stream for the simple fact that it owns the response processing. 
In some cases you might want to make sure that nothing more can be appended to 
the response. Another aspect could be that the original stream was wrapped 
(which would be the case with the Johnzon Json Writer): the servlet container 
would close the wrapped stream, but the wrapper would still stay open in this 
case.

> 
> flushBuffer is called to commit the response, which I think was required to 
> be complient with how forward works. We can of course as a sanity check call 
> response.isCommitted() but does this help here?
> 

I think it would help. Jetty seems to do the same thing [5].

Thanks,
Radu


[4] - 
https://download.oracle.com/otn-pub/jcp/servlet-3_1-fr-spec/servlet-3_1-final.pdf
 
<https://download.oracle.com/otn-pub/jcp/servlet-3_1-fr-spec/servlet-3_1-final.pdf>
[5] - 
https://github.com/eclipse/jetty.project/blob/jetty-11.0.x/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java#L218
 
<https://github.com/eclipse/jetty.project/blob/jetty-11.0.x/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java#L218>


Reply via email to