2

It's generally a good practice to not handle runtime exceptions.

I have this scenario :

 /**boolean returns false if the method execution fails, so that an error can be shown to user*/ boolean saveData() { try { //Some database calls that throw only Runtime exceptions } catch(Exception e) { //Log the exception and return false return false; } return true; } 

So from the Servlet calling it will get a boolean value. If it's false, we show a message 'Save Not sucessful'. Is this okay or is there a better way of doing it ?

4
  • Why not let your caller method(client) to handle the exception rather than saveData Commented Dec 2, 2013 at 12:41
  • Because they are runtime exceptions. We don't really know in advance what kind of exceptions the framework throws. Commented Dec 2, 2013 at 12:43
  • IMO you have to log exception at top level, in the client exception and also handle the exception at that level. Commented Dec 2, 2013 at 12:46
  • 1
    what you're doing there is a bad design on several levels. There are sometimes reasons for catching runtime exceptions, but generally these should be prevented every way possible and then, if you are catching runtime exceptions, catch them to be logged or transformed to a different kind of exception. Commented Dec 2, 2013 at 14:15

7 Answers 7

5

Is it okay to handle Runtime exceptions?

As long as you can do something intelligent at that point, yes. This 'never catch run-time exceptions' is pure nonsense. You'll probably want to log them and do other things, as well.

Sign up to request clarification or add additional context in comments.

Comments

5

It's generally a good practice to not handle runtime exceptions.

This sentence implies a false premise: the question is not whether, but when to catch runtime exceptions.

At some point in your code you should definitely have a "catch-all" exception handler. This point is called the exception barrier, and it is high enough in the call stack to encompass a complete unit of work (basically, the scope of one database transaction).

This should be your governing principle:

  • if an exception must cause the current unit of work to be aborted (rolled back), then do not catch that exception until the exception barrier;

  • if an exception is of local character only, and its appearance only means taking a different route to the handling of the request, then do catch and handle it early.

Note that the above doesn't use the fruitless checked/unchecked distinction. Most modern frameworks completely avoid checked exceptions and go out of their way to shield the programmer from such exceptions being thrown from lower-level code.

In practice, more than 90% of all exceptions are of the first, aborting kind. This is what is meant by the term "unrecoverable"—it means you can't continue what you are doing right now, but the server can stay up and process all other requests. I see many people confusing this with "the JVM is about to die", but exceptions which have that meaning are exceedingly rare and usually there is no special handling code for them.

Lastly, note that the "catch-all" handler should catch not only RuntimeExceptions but also Errors because you want every exception logged the same way. If you let an exception escape your application code, there is no knowing what behavior it will cause. Note that there are some common errors, like StackOverflow and OutOfMemory, which can in principle cause unrecoverable damage and therefore rightfully belong to the Error hierarchy, yet in most real-life cases do no damage beyond aborting the current request. You definitely do not want to shut down your service at the first sight of such an error.

9 Comments

The checked/unchecked distinction is "almost" a good thing; it would be a good thing code that calls a method which is declared as throwing a checked exception could declaratively specify that it is not expected to throw such an exception [even if the calling method is declared as throwing that same exception], and any such exception it does throw should be considered "unexpected" and re-thrown wrapped in an unchecked exception. If foo(), which throws (checked) BarException calls moo(), and moo(), despite being declared as throwing BarException, isn't expected to...
...have conditions arise which would result in it being thrown, then a BarException which gets thrown from within moo() should probably not be caught by code which wants to catch any BarExceptions thrown by foo. BTW, are you being facetious when calling OutOfMemory "innocuous"?
I was thinking in the same direction---some mechanism whereby you can opt out of being molested by checked exceptions---but autowrapping of checked exceptions doesn't seem like the right way to me. Wrapping itself is kind of a hack already: what it should be about is adapting the callee's exception to the caller's API, but this applies to checked and unchecked exceptions alike. I really don't see what danger lies behind exceptions being unchecked---after all, a bug concerning an uhnandled exception is the very easiest bug to fix.
@supercat As for OOME, I wasn't facetious. Although it certainly is true that there are unrecoverable OOME's, most of them are of the benign, recoverable variety, and the unwinding of the call stack causes the essential GC roots to be freed.
My Java experience is limited, but if an OOME occurs how certain can one be that cleanups performed by using-with-resources have actually been performed, and that once the stack is unwound any pools of "emergency memory" space will be restocked?
|
3

No, catching a general Exception will mask any other problems you don't want to catch. Better catching specific exceptions making it harder for unexpected ones to go missing.

Comments

1

I guess your question has two aspects: 1) Handling RuntimeExceptionas the heading suggested and 2) handling generic Exception these are two different things.

The Javadoc of RuntimeExcepton list a bunch of its subclasses (NullPointerException..etc). If you look carefully, these are nothing but the programming errors and instead of handling them in catch block, should be corrected the the code itself so that they do not occur.

Handling generic Exception is generally referred as a poor practice and rightly so because it hides the specific exceptions which might need different handling.

But in case similar to yours, if there is a Servlet giving a call to method there has to be a graceful way to tell the user that there was some problem with the application while processing the request instead if showing the stacktrace.

So what you are doing could be one way of handling and as a good practice keep track of errors/exceptions in the log and correct any RuntimeExceptions

1 Comment

Many exception types that are used by various classes derive from RuntimeException because there's no other nice way in Java to identify exceptions which some overrides of a method may be expected to throw, and which other overrides never will, and which some callers will expect to handle directly and others will not. Code which wants to catch such exceptions should preferably catch those it expects, rather than every RuntimeException, but the fact that such exceptions derive from RuntimeException shouldn't dissuade one from catching them.
1

boolean returns false if the method execution fails, so that an error can be shown to user

This is a clear reason for the method to throw an exception. It is why the exception mechanism exists in the first place. Best practice is to use exceptions for these types of circumstances, not boolean signals.

Anytime you follow this kind of pattern, you suffer in several ways

  • The caller cannot be sure what really happened. Was there a communication failure? Was the data corrupted? There is no way to tell when you return a simple "FAILED" signal.
  • Because the caller cannot know what happened, you take away options for the caller. Maybe the caller could do something in certain error cases.
  • You increase the potential for data errors. Again, since the caller cannot know why it failed, the caller may make assumptions about why it failed and continue in cases when the entire program should halt. If the program continues, it may decide to process invalid data when it really should stop.

I highly recommend reading the sections on exception handling in Effective Java. Basically, if you can't do anything meaningful with an Exception in your method, you should allow it to pass up the stack. In the worst case scenario, the API you reference throws a generic checked exception, giving you one of three choices (EDIT: Changed to void return type because the boolean return type no longer has any meaning -- you either succeed or throw an exception)

-Create your own.

 // "MyFatalException" would be a checked Exception public void saveData() throws MyFatalException{ try{ // ... do stuff that throws Exception }catch(Exception e){ throw new MyFatalException("Unable to save Data due to a general exception"+ " thrown by foo.bar()", e); } } 

-Throw an existing type (my preference is for subclasses of RuntimeException)

public void saveData() throws IllegalStateException{ try{ // ... do stuff that throws Exception }catch(Exception e){ throw new IllegalStateException("Unable to save Data due to a general exception"+ " thrown by foo.bar()", e); } 

-Declare to throw a generic Exception and let it pass up (I do NOT recommend this, but you'll see many developers who do this)

 public void saveData() throws Exception{ // no try/catch needed. Just make the call } 

1 Comment

Your last choice demonstrates how checked exceptions result in leaky abstractions---you had to change the interface of your method just because the code you call internally throws some checked exceptions. And that's not all---now all the callers of your method must change their interface. It's like the poison pill.
0

The general concept is that frameworks or APIs would throw a RuntimeException only in situations when the error is not recoverable in code. e.g: your Db is down, or your server socket is down and things like that. Though its not bad to catch such exceptions but whats actually thoughtful is what do you intend to do after catching them. e.g: people prefer to catch DB level connection problems and errors which are runtime exception subclasses and show error pages on their websites. Checked exceptions are usually for code level situational cases and catching them and handling is what code is expected to do.

12 Comments

All modern frameworks go out of their way to shield the programmer from the drudgery of handling checked exceptions.
@Marko no they do not. they just provide a way so that we dont have to handle non recoverable situational based runtime errors and exceptions. Am not sure what you mean by "handling checked exceptions" in your comment.
You said an unchecked exception is non-recoverable, whereas Spring, Hibernate, and many others specifically turn JDK's checked exceptions into unchecked ones. Therefore you claim that they turn recoverable into unrecoverable errors.
actually what i meant was the intent of throwing unchecked exception by such frameworks is that they are non recoverable. The point i was making is that non recoverable situations are indicated in majority by unchecked exceptions. hibernate and spring are two big examples. spring's exception translator has this as one of its primary purposes.
When it comes to state-of-the art frameworks, this is the truth: checked exceptions do not even exist. For almost a whole decade they have been categorized as a failure of language design, causing boilerplate code, leaky abstractions, errors resulting from broken exception handling patterns, and so on.
|
0

In case you try something like this, since you don't want your users to error page you can do this, provided you caught all other exceptions before this.

boolean saveData() { try { //Some database calls that throw only Runtime exceptions }catch(db_Connectivity_Exception e){ //exception like credentials invalid }catch(db_table_Exception e){ //table desc. changed } catch(Exception e) { //Log the exception and return false //Since you are going to log your error I hope is not harmfu return false; } return true; } 

Still this is not best practice

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.