This snippet from a downloader callable handles HTTP status codes. I need critique on both the style (for
or do-while
loop better here?) and functionality. Should I manage the delay differently? Do I need to handle InterruptedException
specifically?
HttpURLConnection connection = null;
boolean connected=false;
outer:
for(int retry=0;retry<=RETRIES&&!connected;retry++)
{
if(retry>0) {log.warning("retry "+retry+"/"+RETRIES);Thread.sleep(RETRY_DELAY_MS);}
connection = (HttpURLConnection)entries.openConnection();
connection.connect();
switch(connection.getResponseCode())
{
case HttpURLConnection.HTTP_OK: log.fine(entries +" **OK**");connected=true;break; // fine, go on
case HttpURLConnection.HTTP_GATEWAY_TIMEOUT: log.warning(entries+" **gateway timeout**");break;// retry
case HttpURLConnection.HTTP_UNAVAILABLE: System.out.println(entries+ "**unavailable**");break;// retry, server is unstable
default: log.severe(entries+" **unknown response code**.");break outer; // abort
}
}
connection.disconnect();
log.severe("Aborting download of dataset.");
-
1\$\begingroup\$ You got labels? Goto style? \$\endgroup\$fnc12– fnc122016年11月19日 16:35:54 +00:00Commented Nov 19, 2016 at 16:35
-
\$\begingroup\$ @fnc12: I try to refrain using them but sometimes I don't find a better option. That's one of the reasons I put this in code review. \$\endgroup\$Konrad Höffner– Konrad Höffner2019年08月01日 15:05:21 +00:00Commented Aug 1, 2019 at 15:05
3 Answers 3
Readability
Let's reformat your code quickly:
HttpURLConnection connection = null; boolean connected = false; outer: for (int retry = 0; retry <= RETRIES && !connected; retry++) { if (retry > 0) { log.warning("retry " + retry + "/" + RETRIES); Thread.sleep(RETRY_DELAY_MS); } connection = (HttpURLConnection) entries.openConnection(); connection.connect(); switch (connection.getResponseCode()) { case HttpURLConnection.HTTP_OK: log.fine(entries + " **OK**"); connected = true; break; // fine, go on case HttpURLConnection.HTTP_GATEWAY_TIMEOUT: log.warning(entries + " **gateway timeout**"); break;// retry case HttpURLConnection.HTTP_UNAVAILABLE: System.out.println(entries + "**unavailable**"); break;// retry, server is unstable default: log.severe(entries + " **unknown response code**."); break outer; // abort } } connection.disconnect(); log.severe("Aborting download of dataset.");
Fixed:
1-liners are hard to read:
case HttpURLConnection.HTTP_UNAVAILABLE: System.out.println(entries+ "**unavailable**");break;// retry, server is unstable
spacing inside for-loop conditions:
for(int retry=0;retry<=RETRIES&&!connected;retry++)
indentation - 1-space indentation is 'just wrong'TM.
Functionality
Right, how does this code work? There are a few problems I can (now) see in here:
- On HTTP_OK, it
breaks
out of the switch, then it exits the loop (because&& !connected
), and then immediately disconnects and logs a severe error? This can't be right? HTTP_GATEWAY_TIMEOUT
logs a warning.... great, butHTTP_UNAVAILABLE
does aSystem.out.println
The InterruptedException
handling is not shown here. There are articles on how to do this properly. Google up on that.
Suggestion
I recommend a sub-function, with a do-while loop (the following is a quick hack-up - untested):
private static final HttpURLConnection getConnection(URL entries) throws InterruptedException{
int retry = 0;
boolean delay = false;
do {
if (delay) {
Thread.sleep(RETRY_DELAY_MS);
}
HttpURLConnection connection = (HttpURLConnection)entries.openConnection();
switch (connection.getResponseCode()) {
case HttpURLConnection.HTTP_OK:
log.fine(entries + " **OK**");
return connection; // **EXIT POINT** fine, go on
case HttpURLConnection.HTTP_GATEWAY_TIMEOUT:
log.warning(entries + " **gateway timeout**");
break;// retry
case HttpURLConnection.HTTP_UNAVAILABLE:
log.warning(entries + "**unavailable**");
break;// retry, server is unstable
default:
log.severe(entries + " **unknown response code**.");
break; // abort
}
// we did not succeed with connection (or we would have returned the connection).
connection.disconnect();
// retry
retry++;
log.warning("Failed retry " + retry + "/" + RETRIES);
delay = true;
} while (retry < RETRIES);
log.severe("Aborting download of dataset.");
}
-
1\$\begingroup\$ You are right, the last severe log should be conditional on !connected. I didn't even think about creating a subfunction out of it but it is an excellent idea because I need the same functionality elsewhere. The indentation however I changed to fit it into the box, I use tabs normally. \$\endgroup\$Konrad Höffner– Konrad Höffner2014年03月31日 14:33:55 +00:00Commented Mar 31, 2014 at 14:33
-
\$\begingroup\$ @rolfl I also have question on http client which I posted here. Just wanted to see if you can help CR my question. I haven't got any response so thought to check with you since I saw you answered lot of http related questions. \$\endgroup\$user1950349– user19503492016年05月20日 18:42:54 +00:00Commented May 20, 2016 at 18:42
Two things to add:
I'd print that response code here to the log:
log.severe(entries + " **unknown response code**.");
It would help debugging.
Retry seems a good idea first but one of the recent Java Posse episode (#442 Roundup ‘13 - Big Data Bloopers) has an interesting thought: This might not be that you really want. If there's a problem on the other side it might just makes the thing worse and it probably performs a DoS attack.
-
\$\begingroup\$ That's why I double the delay after every retry. I hope that is enough to not create a DoS. \$\endgroup\$Konrad Höffner– Konrad Höffner2014年04月04日 09:02:45 +00:00Commented Apr 4, 2014 at 9:02
Working Solution
public int callAPI() {
return 1;
}
public int retrylogic() throws InterruptedException, IOException{
int retry = 0;
int status = -1;
boolean delay = false;
do {
if (delay) {
Thread.sleep(2000);
}
try {
status = callAPI();
}
catch (Exception e) {
System.out.println("Error occured");
status = -1;
}
finally {
switch (status) {
case 200:
System.out.println(" **OK**");
return status;
default:
System.out.println(" **unknown response code**.");
break;
}
retry++;
System.out.println("Failed retry " + retry + "/" + 3);
delay = true;
}
}while (retry < 3);
return status;
}
-
4\$\begingroup\$ Welcome to Code Review! You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) so that the author and other readers can learn from your thought process. Please read Why are alternative solutions not welcome? \$\endgroup\$2019年08月01日 15:22:19 +00:00Commented Aug 1, 2019 at 15:22