1

I am using HttpURLConnection for making POST requests. I observe always the same behaviour during tests:

  1. first request runs very fast (miliseconds)
  2. all following requests take one second + some miliseconds

So something is causing 1 second delay. What can it be? The delay is happening exactly in HttpURLConnection#getInputStream(). I replaced the implementation with HttpClient - then everything is OK, no second delays (so it is not the server fault). But I really don't want to use any external dependency, so I would like to fix the HttpURLConnection thing... Any ideas?

Below current implementation. I tried some tips from stackoverflow (adding headers to the request), but with no success.

        URL obj = new URL(url);
    HttpURLConnection con = (HttpURLConnection) obj.openConnection();
    con.setRequestMethod("POST");

    con.setRequestProperty("Content-Length", ""
        + (body == null ? 0 : body.length));

    // Send post request
    con.setDoOutput(true);
    OutputStream wr = con.getOutputStream();
    if (body != null) {
    wr.write(body);
    }
    wr.flush();
    wr.close();

    BufferedReader rd = new BufferedReader(new InputStreamReader(
        con.getInputStream()));
    String line;
    String result = "";
    while ((line = rd.readLine()) != null) {
    result += line;
    }

    rd.close();
    con.disconnect();

    return result;

PS: It is about jse, not android.

Tomasz
  • 988
  • 1
  • 9
  • 23

1 Answers1

1

You're never closing the input stream from the connection - that may mean that the connection isn't eligible for pooling, and on the next attempt it's waiting for up to a second to see if the previous request's connection will become eligible for pooling.

At the very least, it would be a good idea to close the stream. Use a try-with-resources block if you're using Java 7 - and ditto for the writer.

As an aside, I suggest you explicitly state the encoding you expect when reading - or use a higher-level library which detects that automatically based on headers.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks Jon, i just tested it (and edited the question code), there is no difference.. Any other ideas? Generally the pooling looks like a good reason, as the first call is always fast – Tomasz Nov 08 '13 at 13:49
  • Closing input stream has nothing to do with the time latency, as the [doc](http://docs.oracle.com/javase/7/docs/api/java/net/HttpURLConnection.html) states: `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.` – Sage Nov 08 '13 at 13:52
  • Calling disconnect on connection releases the Socket, so from now on it should behave like there was no connection before. So what can cause the 1 second delay? – Tomasz Nov 08 '13 at 13:59
  • @Sage: I would read that as saying that it doesn't *close* the connection - but I think leaving it open could easily block things. This is mostly based on experience in .NET's connection pooling admittedly, but it would make sense in Java too. – Jon Skeet Nov 08 '13 at 14:12
  • @Tomasz: The docs state that calling disconnect *may* close the socket of a persistent connection. It doesn't say that it will. – Jon Skeet Nov 08 '13 at 14:13
  • @Tomasz: Have you tried removing the `disconnect` call, mind you? – Jon Skeet Nov 08 '13 at 14:14
  • @JonSkeet, `leaving it open could easily block things`- yes, especially if we are creating a *number* of connection at once that might affect, but from OP's question it seems he is trying with single connection with consecutive creation, from his question `first request runs very fast (miliseconds), all following requests take one second + some miliseconds` so he is saying the latency is happening from `second` request of the connection – Sage Nov 08 '13 at 14:23
  • 2
    @Sage: My point is that by leaving the input stream open, the connection may not be reused - but the connection pooling system may decide to wait a little while to hope that it *can* reuse it, before opening a new connection. It sounds like it hasn't helped in the end, but I still think it was a legitimate idea to propose... and I'd certainly recommend closing all streams *anyway*. – Jon Skeet Nov 08 '13 at 14:27