Reputation: 547
I have several questions about best use of exceptions in Java.
Consider the code below:
private String doHttpGetRequest(String url) throws IOException {
...
}
private Photo processJson(String json) throws JSON Exception{
...
}
private Photo getPhoto() throws IOException, JSON Exception {
String url = "http://...";
String response = doHttpGetRequest(url);
Photo photo = processJson(response);
photo.downloadImage();
return photo;
}
public static void main(String args[]) {
Photo p = null;
try {
p = getPhoto();
} catch( JSONException j ) {
// Re-try a few times, then display user alert
} catch( IOException e ) {
// Re-try a few times, then display user alert
}
if( p!=null)
// now display photo
}
This code is for an android app where the connection may not be very reliable, so I would like to re-try the getPhoto() method a few times to see if it will work, then fail and alert the user.
My questions:
I am opening an InputStream in doHttpGetRequest() and that method is throwing an IOException. How do I close the InputStream if it has thrown the exception? Without a finally block within the method that would allow me to close resources, i'm confused.
In main(), I'm only interested in whether getPhoto() works or does not work. Would I be better to surround statements inside getPhoto() with a try/catch block and catch the JSONException, throwing a new IOException when it is caught? This would lead to only having to catch one kind of exception in main(), leading to simpler code and not having duplicate functionality.
If p.getPhoto() throws an exception, I want to re-try it (possibly twice) and then display a user alert if this fails. Is there a common programming structure to doing this?
Upvotes: 0
Views: 305
Reputation: 41510
You should still use try-finally block so you are able to close the resources. The block is used like this:
InputStream is;
try {
is = openStream(); //This is a sample code, which
//Do something with the stream
} finally {
if (is != null) is.close();
}
This way if an exception is thrown, the stream will be closed anyway, and the exception will be handled elsewhere.
I suggest you creating your own exception (say, PhotoReadingException) and throw it from getPhoto(), but setting its cause to the original exception via the initCause(Throwable cause)
method.
Certainly, you can use a loop and a variable which shows if the operation was successful.
Photo p = null;
Exception ex = null;
for (int tries = 0; tries < MAX_TRIES; tries++) {
try {
p = getPhoto();
break;
} catch (PhotoReadingException photoException) {
ex = photoException;
}
}
if (ex != null) reportException(ex);
Upvotes: 0
Reputation: 10187
doHttpGetRequest()
should be in charge of closing the inputstream. Finally-block there would be suitable for closing (why don't you want finally block?).
Do you have to pass any exceptions to the main method. You could surround doHttpGetRequest(url)
with try{}
and surround processJson
with another (I quess this one doesn't benefit from retries). This would make the main()
method cleaner.
If you go with my suggestion on 2. you could do the retrying like this:
String response = null;
for (int i = 0; i < RETRY_COUNT && response == null; i++){
try {
response = doHttpGetRequest(url);
} catch (IOException e){
// Possibly log the error here
}
}
if (response == null) return null;
EDIT: Bugfix
Upvotes: 1
Reputation: 18340
You can catch the exception, clean up and re-throw it. Why are you avoiding using finally
block? It looks like it would fit there very well.
It will probably be more code than handling those two exception separately.
Put it in a for
loop, continue
if there was an exception and break
if not.
Upvotes: 0