InsanityOnABun
InsanityOnABun

Reputation: 6143

Retry a connection on timeout in Java

I have a method (below) that pulls down and returns the source of a webpage as a String. It all works fine and dandy, but when the connection times out, the program throws an exception and exits. Is there a better method to do this that would allow it to try again on timeout, or is there a way to do it within this method?

public static String getPage(String theURL) {
    URL url = null;
    try {
        url = new URL(theURL);
    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        exitprint();
    }
    InputStream is = null;
    try {
        is = url.openStream();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        exitprint();
    }
    int ptr = 0;
    StringBuffer buffer = new StringBuffer();
    try {
        while ((ptr = is.read()) != -1) {
            buffer.append((char)ptr);
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        exitprint();
    }

    return buffer.toString();
}

Upvotes: 12

Views: 26701

Answers (5)

yegor256
yegor256

Reputation: 105073

I think AOP and Java annotations is a good option. I would recommend to use a read-made mechanism from jcabi-aspects:

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

Upvotes: 2

andronikus
andronikus

Reputation: 4210

You could put the whole thing in a while loop:

while (true) {

  try {
    ...
  } catch (IOException e) {
    continue;
  }

  return buffer.toString();
}

The return statement will break you out of the loop. You might also want to keep track of the number of attempts and stop after 5-10, for politeness, but that's the basic shape of it.

Edit

The better version, based on comments:

int retries = 10;
for (int i = 0 ; i < retries ; i++) {

  try {
    ...
  } catch (IOException e) {
    continue;
  }

  return buffer.toString();
}

Upvotes: 1

bpgergo
bpgergo

Reputation: 16037

Instead of

try {
    is = url.openStream();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    exitprint();
}

you can try set longer timeout and you can still handle timeout exception by catching it

try {
    URLConnection con= url.openConnection();
    con.setConnectTimeout(5000); 
    con.setReadTimeout(50000);
    BufferedReader in = new BufferedReader(
        new InputStreamReader(con.getInputStream()));
    String inputLine;
    while ((inputLine = in.readLine()) != null) 
        System.out.println(inputLine);
    in.close();
} catch (SocketTimeoutException e) {
    //here you can still handle timeout like try again under certain conditions
}

Upvotes: 1

aioobe
aioobe

Reputation: 421020

Here's a refactoring of your code that should retry the download N times. Haven't tested it though, but it should kick you off in the right direction.

public static String getPage(String theURL) {

    URL url = null;
    try {
        url = new URL(theURL);
    } catch (MalformedURLException e) {
        e.printStackTrace();
        exitprint();
    }

    for (int i = 0; i < N; i++) {

        try {
            InputStream is = url.openStream();

            int ptr = 0;
            StringBuffer buffer = new StringBuffer();

            while ((ptr = is.read()) != -1)
                buffer.append((char)ptr);

        } catch (IOException e) {
            continue;
        }

        return buffer.toString();
    }

    throw new SomeException("Failed to download after " + N + " attepmts");
}

Upvotes: 13

Kevin
Kevin

Reputation: 25269

Write a wrapper function around it and allow the connect exception to propogate out. Then you can loop calling your existing function while you receive connect exception upto some max retries.

This is better than embedding a for loop in your existing function because it logically separates retry logic from mainline code. And it's easier to read and understand as a result.

Upvotes: 1

Related Questions