Retry timeout connection in Java

I have a method (below) that pulls and returns the source of a webpage as a String. Everything works fine and dandy, but when the connection time ends, the program throws an exception and exits. Is there a better way to do this to let him try the timeout again, or is there a way to do this as part of 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(); } 
+8
java
source share
5 answers

Here's a refactoring of your code, which should retry loading N times. They have not tested it, but it should push you 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"); } 
+7
source share

Write a wrapper function around it and allow the exception to connect. Then you can loop over your existing function until you get a connection exception up to a few max attempts.

This is better than embedding the for loop in an existing function, because it logically separates the retry logic from the main code. And it is easier to read and understand the result.

+1
source share

You can put all this in a while :

 while (true) { try { ... } catch (IOException e) { continue; } return buffer.toString(); } 

The return will take you out of the loop. You can also track the number of attempts and stop after 5-10, for courtesy, but this is the main form.

Edit

Best comment based version:

 int retries = 10; for (int i = 0 ; i < retries ; i++) { try { ... } catch (IOException e) { continue; } return buffer.toString(); } 
+1
source share

Instead

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

you can try setting a longer timeout, and you can still handle the 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 } 
+1
source share

I think AOP and Java annotations are a good option. I would recommend using the reading mechanism from jcabi-aspects :

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

All Articles