user291701
user291701

Reputation: 39681

Retrying an http connection

I'm making an http request. I'm on a platform (android) where network operations often fail because the network connection might not be immediately available. Therefore I'd like to try the same connection N times before completely failing. Was thinking of something like this:

DefaultHttpClient mHttp = ...;

public HttpResponse runHttpRequest(HttpRequestBase httpRequest) 
    throws IOException
{
    IOException last = null;
    for (int attempt = 0; attempt < 3; attempt++) {
        try {
            HttpResponse response = mHttpClient.execute(httpRequest);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) {
                return response;
            }
        } catch (IOException e) {
            httpRequest.abort();
            last = e;
        }
    }

    throw last;
}

I'm mostly worried about the connection being in some state which is invalid on subsequent retries. In other words, do I need to completely recreate 'httpRequest', should I avoid calling httpRequest.abort() in the catch block, and only call it in the final failure?

Thanks

Upvotes: 7

Views: 15332

Answers (3)

yegor256
yegor256

Reputation: 105073

I'd recommend to use AOP and Java annotations from jcabi-aspects (I'm a developer):

@RetryOnFailure(attempts = 3, delay = 5)
public String load(URL url) {
  return url.openConnection().getContent();
}

Upvotes: 3

BenV
BenV

Reputation: 1206

A HttpRequestRetryHandler seems like it might be helpful here.

Upvotes: 6

Michael Aaron Safyan
Michael Aaron Safyan

Reputation: 95509

The documentation does not mention that such a thing will occur, although you'd have to try it. More importantly, though, there are some things that you should consider with your code...

  1. You should probably expose the number of retries, allowing the caller to specify this value.
  2. You should only retry if an exception was thrown; you currently retry unless you get a 200. However if, for example, you get a 404... this doesn't mean your request failed in the sense that the network did not fail... rather, you made a successful round-trip to the server, but the server simply doesn't have the requested resource... so it really doesn't make sense to retry in such a case.
  3. As-is, you might suppress all sorts of different types of exceptions. It might make sense to record all the exceptions that occurred in a List and return some sort of result object which contains the response (possibly null if all attempts failed) in addition to a list of all exceptions. Otherwise, you throw some arbitrary exception from the set of exceptions that occurred, possibly obscuring failure.
  4. Right now you just hammer away with the same request, over and over again... if there is congestion, you are just adding to it. And if your IP address was banned for too much activity, you are probably going to be adding to that... any sort of retry logic should have a back-off behavior where there is some amount of waiting between retries and that interval increases with each failure.

Upvotes: 9

Related Questions