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 !!
Related
I want to get streaming data from the server. Server sends data as a multipart/x-mixed-replace format, and it has Connection: close property. Connection: close means, it wants that client must be close the connection when receive the chunked data. Am I right?
Or, connection not closed because of data is streaming (server sends chunked data each time, I'm not send get request to the server at each time. Or is this done in the background?). So, connection is not closing at any time until I call the inputStream.close() method. Right?
Also, if server is down at any time, http url connection will be thrown the IOException. In this case, Must I call the disconnect() method of the http url connection? Or, should I call just inputStream.close()?
How can I close the HttpURLConnection safely at any time?
Connection: close means, it wants that client must be close the
connection when receive the chunked data. Am I right?
Not exactly. A Connection: close header in an HTTP message is informative, not prescriptive. It advises the receiver that the server intends to close the connection after sending the response (see RFC 7230, section 6.1). The user is not obligated to take specific action in response, but it may save itself some time by not attempting any further communication over that connection after receiving the HTTP payload. In practice, however, yes, after receiving the response, the client should close the application-layer connection on its end, too, for until it does, it will tie up associated system resources for no good reason.
But none of that is really your concern if you're working with an HttpURLConnection and / or the InputStream obtained from one. Per its documentation:
Each HttpURLConnection instance is used to make a single request but
the underlying network connection to the HTTP server may be
transparently shared by other instances. 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.
That is, HttpURLConnection manages the details of persistent connections for you.
You continue,
Or, connection not closed because of data is streaming(server sends
chunked data each time, I'm not send get request to the server at each
time. Or is this done in the background?).
It seems that you simply mean that the server does not specify a content-length, and sends a response of indeterminate length over an extended period of time. In that case, the Connection header probably hasn't much practical relevance.
So, connection is not
closing at any time until I close the inputStream.close() method.
Right?
The server will not ordinarily close the connection at its end until it has sent the complete response. If, in principle, the response has unbounded length, then there is no reason to expect the server to initiate a connection closure from its end other than server shutdown or failure.
Also, if server is down at any time, http url connection will be
thrown the IOException.
Maybe. If the attempt to establish a connection in the first place fails, then you can expect an IOException of some flavor. If the server goes down while delivering the response then you might get an exception, but you might also just see the end of the stream.
In this case, Must I call the disconnect()
method of the http url connection? Or, should I call just
inputStream.close()?
You do not ever need to disconnect(), and if you do then it is merely advisory, as described in the docs quoted above. If you reach the end of the stream then you should indeed close it. If an IOException is thrown while you are reading the stream then it's probably best to attempt to close() the stream, but be prepared for that to fail, too, as the stream might be in an inconsistent state.
How can I close the http url connection safely at any time?
Once you've actually connected an HttpURLConnection instance to the underlying resource, closing its stream(s) should be enough to indicate that you're done with it. Before you've connected, you don't need to do anything at all.
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.
I'm using HttpURLConnection to do download of pages in Java. I forgot to release the connections and I think this was causing some problems to my system (a webcrawler).
Now I've done some tests and see that after disconnecting, some connections still like TIME_WAIT in the results from the netstat command on Windows.
How I do to free this connection immediately?
Example code:
private HttpURLConnection connection;
boolean openConnection(String url) {
try {
URL urlDownload = new URL(url);
connection = (HttpURLConnection) urlDownload.openConnection();
connection.setInstanceFollowRedirects(true);
connection.connect();
connection.disconnect();
return true;
} catch (Exception e) {
System.out.println(e);
return false;
}
}
In some implementations, if you have called getInputStream or getOutputStream, you need to ensure that those streams are closed. Otherwise, the connection can stay open even after calling disconnect.
EDIT:
This is from the J2SE docs for HttpURLConnection [emphasis added]:
Calling the disconnect() method may close the underlying socket if a persistent connection is otherwise idle at that time.
And this is from the Android docs:
To reduce latency, this class may reuse the same underlying Socket for multiple request/response pairs. As a result, HTTP connections may be held open longer than necessary. Calls to disconnect() return the socket to a pool of connected sockets. This behavior can be disabled by setting the "http.keepAlive" system property to "false" before issuing any HTTP requests. The "http.maxConnections" property may be used to control how many idle connections to each server will be held.
I don't know what platform you are using, but it could have similar behavior.
The TME_WAIT state is imposed by TCP, not by Java. It lasts two minutes. This is normal.
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.