Do I need to "flush" the OutputStream from the HttpServletResponse?
I already saw from to Should I close the servlet outputstream? that I don't need to close it, but it's not clear if I need to flush it. Should I expect it from the container as well?
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
byte[] response = getResponse();
String responseType = getResponseType();
response.setContentLength(response.length);
response.setContentType(responseType);
response.getOutputStream().write(response);
response.getOutputStream().flush(); // yes/no/why?
}
You don't need to. The servletcontainer will flush and close it for you. The close by the way already implicitly calls flush.
See also chapter 5.6 of Servlet 3.1 specification:
5.6 Closure of Response Object
When a response is closed, the container must immediately flush all remaining
content in the response buffer to the client. The following events indicate that the servlet has satisfied the request and that the response object is to be closed:
The termination of the service method of the servlet.
The amount of content specified in the setContentLength or
setContentLengthLong method of the response has been greater than zero and
has been written to the response.
The sendError method is called.
The sendRedirect method is called.
The complete method on AsyncContext is called.
Calling flush while still running the servlet's service is usually only beneficial when you have multiple writers on the same stream and you want to switch of the writer (e.g. file with mixed binary/character data), or when you want to keep the stream pointer open for an uncertain time (e.g. a logfile).
Guess that the same answer you got in your other question applies here: if it is your stream, flush and close it. Otherwise the stream creator should be doing it, unless otherwise stated.
To point out an insidious exception to the rule “no need to flush”: Working with IBM WebSphere Application Server and using the response Writer (rather than the OutputStream) I found that I had to flush it; otherwise a final portion of my response data was lost. I suppose that IBM's HttpServletResponse class does indeed flush the OutputStream but uses a separate buffer for the Writer and does not flush it. Other application servers seem to do this.
So if you send your response data to the Writer it is safer to flush it. But there is no need to flush the OutputStream into the bargain.
(I would have posted this as a comment but lack the reputation to do it.)
java.lang.Object
extended byjava.io.Writer
extended byjavax.servlet.jsp.JspWriter
close
public abstract void close()
throws IOException
Close the stream, flushing it first.
This method needs not be invoked explicitly for the initial JspWriter as the code generated by the JSP container will automatically include a call to close().
Closing a previously-closed stream, unlike flush(), has no effect.
Throws:
IOException - If an I/O error occurs
============================
So, DO NOT close the output stream explicitly.
Related
How can I detect that the client side of a tomcat servlet request has disconnected? I've read that I should do a response.getOutputStream().print(), then a response.getOutputStream().flush() and catch an IOException, but is there a way I can detect this without writing any data?
EDIT:
The servlet sends out a data stream that doesn't necessarily end, but doesn't necessarily have any data flowing through it (it's a stream of real time events). I need to actually detect when the client disconnects because I have some cleanup I have to do at that point (resources to release, etcetera). If I have the HttpServletRequest available, will trying to read from that throw an IOException if the client disconnects?
is there a way I can detect this
without writing any data?
No because there isn't a way in TCP/IP to detect it without writing any data.
Don't worry about it. Just complete the request actions and write the response. If the client has disappeared, that will cause an IOException: connection reset, which will be thrown into the servlet container. Nothing you have to do about that.
I need to actually detect when the client disconnects because I have some cleanup I have to do at that point (resources to release, etcetera).
There the finally block is for. It will be executed regardless of the outcome. E.g.
OutputStream output = null;
try {
output = response.getOutputStream();
// ...
output.flush();
// ...
} finally {
// Do your cleanup here.
}
If I have the HttpServletRequest available, will trying to read from that throw an IOException if the client disconnects?
Depends on how you're reading from it and how much of request body is already in server memory. In case of normal form encoded requests, whenever you call getParameter() beforehand, it will usually be fully parsed and stored in server memory. Calling the getInputStream() won't be useful at all. Better do it on the response instead.
Have you tried to flush the buffer of the response:
response.flushBuffer();
Seems to throw an IOException when the client disconnected.
How can I detect that the client side of a tomcat servlet request has disconnected? I've read that I should do a response.getOutputStream().print(), then a response.getOutputStream().flush() and catch an IOException, but is there a way I can detect this without writing any data?
EDIT:
The servlet sends out a data stream that doesn't necessarily end, but doesn't necessarily have any data flowing through it (it's a stream of real time events). I need to actually detect when the client disconnects because I have some cleanup I have to do at that point (resources to release, etcetera). If I have the HttpServletRequest available, will trying to read from that throw an IOException if the client disconnects?
is there a way I can detect this
without writing any data?
No because there isn't a way in TCP/IP to detect it without writing any data.
Don't worry about it. Just complete the request actions and write the response. If the client has disappeared, that will cause an IOException: connection reset, which will be thrown into the servlet container. Nothing you have to do about that.
I need to actually detect when the client disconnects because I have some cleanup I have to do at that point (resources to release, etcetera).
There the finally block is for. It will be executed regardless of the outcome. E.g.
OutputStream output = null;
try {
output = response.getOutputStream();
// ...
output.flush();
// ...
} finally {
// Do your cleanup here.
}
If I have the HttpServletRequest available, will trying to read from that throw an IOException if the client disconnects?
Depends on how you're reading from it and how much of request body is already in server memory. In case of normal form encoded requests, whenever you call getParameter() beforehand, it will usually be fully parsed and stored in server memory. Calling the getInputStream() won't be useful at all. Better do it on the response instead.
Have you tried to flush the buffer of the response:
response.flushBuffer();
Seems to throw an IOException when the client disconnected.
How can I detect that the client side of a tomcat servlet request has disconnected? I've read that I should do a response.getOutputStream().print(), then a response.getOutputStream().flush() and catch an IOException, but is there a way I can detect this without writing any data?
EDIT:
The servlet sends out a data stream that doesn't necessarily end, but doesn't necessarily have any data flowing through it (it's a stream of real time events). I need to actually detect when the client disconnects because I have some cleanup I have to do at that point (resources to release, etcetera). If I have the HttpServletRequest available, will trying to read from that throw an IOException if the client disconnects?
is there a way I can detect this
without writing any data?
No because there isn't a way in TCP/IP to detect it without writing any data.
Don't worry about it. Just complete the request actions and write the response. If the client has disappeared, that will cause an IOException: connection reset, which will be thrown into the servlet container. Nothing you have to do about that.
I need to actually detect when the client disconnects because I have some cleanup I have to do at that point (resources to release, etcetera).
There the finally block is for. It will be executed regardless of the outcome. E.g.
OutputStream output = null;
try {
output = response.getOutputStream();
// ...
output.flush();
// ...
} finally {
// Do your cleanup here.
}
If I have the HttpServletRequest available, will trying to read from that throw an IOException if the client disconnects?
Depends on how you're reading from it and how much of request body is already in server memory. In case of normal form encoded requests, whenever you call getParameter() beforehand, it will usually be fully parsed and stored in server memory. Calling the getInputStream() won't be useful at all. Better do it on the response instead.
Have you tried to flush the buffer of the response:
response.flushBuffer();
Seems to throw an IOException when the client disconnected.
What exactly happens when you don't close the below input stream?
InputStream is = new URL(queryUrl).openStream();
Since it's a URL connection, would it be smart enough to close automatically after request?
I tried looking at the documentation, but it is pretty vague. From what we gather, this is the same as doing HTTPUrlConnection.getInputStream().
I'm just trying to figure out the impacts of not doing is.close(). Would this definitely cause resource leaks?
When you call close, associated system resources are released. If you look at implementation of method URL.openStream()
public final InputStream openStream() throws java.io.IOException {
return openConnection().getInputStream();
}
public URLConnection openConnection() throws java.io.IOException {
return handler.openConnection(this);
}
It returns a URLConnection, according to javadoc
Invoking the close() methods on the InputStream or OutputStream of an URLConnection after a request may free network resources associated with this instance, unless particular protocol specifications specify different behaviours for it.
As an example if you see HttpURLConnection, their docs say:
Calling the close() methods on the InputStream or OutputStream of an HttpURLConnection after a request may free network resources associated with this instance but has no effect on any shared persistent connection. Calling the disconnect() method may close the underlying socket if a persistent connection is otherwise idle at that time.
Cheers !!
Let's say I'm writing chunks of data to an HttpServletResponse. So my method receives an array of bytes, I write it to response.getOutputStream(), and then I release the thread. When I receive another chunk of data, my method will be awaken, and it will write to getOutputStream() again. In the end, I call to AsyncContext.complete().
Now, the WriteListener.onWritePossible() spec says:
this method will be invoked by the container the first time when it is
possible to write data. The container will subsequently invoke the
onWritePossible method if and only if isReady method on
ServletOutputStream, described below, returns false.
It seems that when the container calls this method, I already need to have my response buffered somewhere, because onWritePossible() may never be called again. So, for the previous example, I need to write all chunks of data I receive in a buffer (a byte array, or maybe a temporary file if the buffer is big enough), and if onWritePossible() is called before my response is complete, what should I do? Block the thread until I have all my response data?
Check code in following link. May not be the exact solution but it's idea can be a solution for your case:
Servlet 3.1 Async IO Echo
hmm.. Maintaining a buffer seems to be the way
public void onWritePossible() throws IOException {
doWrite();
}
// this is some callback where you received next chunk of data
public void onMoreDataReceived(byte[] data) {
putDataToBuffer(data);
doWrite();
}
// this method is non-blocking
private void synchronized doWrite() throws IOException {
while (_servletOutputStream.isReady() && hasMoreDataInBuffer()) {
_servletOutputStream.write(getMoreBytesFromBuffer());
}
}