6

I'm having difficulties understanding how to handle unchecked exceptions.

If the method doesn't declare the exception and I am not forced to handle it, how do I even know the method throws an exception?

Unchecked exceptions are for programming errors, as I have read, so to avoid a NullPointerException, I would introduce a null check. Or for an ArrayIndexOutOfBoundsException I would check how I access the array.

But when I don't know that a method throws a custom unchecked exception, how am I supposed to handle this?

And how do you propagate exceptions from the data layer to the user interface? Those must be checked exceptions, right?

I would let the data layer throw checked DataLayerExceptions and then have a try-catch-block in the presenter class (given I am using MVP) and then in the catch-block set the error message on the view...

Or can this be done using unchecked exceptions?

EDIT

Thanks for the replies so far.

Here is a concrete example I am faced with.

I am getting started with Spring and in a book I saw a UserRepository class that uses a JDBCTemplate to retrieve data from the database. The UserRepositoty contains a method somewhat like this:

@Override
public List<User> findAll() {
    String sql = "select id, username, email, password from p_user";
    return new ArrayList<>(jdbcTemplate.query(sql, rowMapper));
}

Now, the query method of the jdbcTemplate throws a DataAccessException, which is a runtime exception.

I knwo this, because I looked at the method signature.

Now, how would I handle this exception? Surely, the user needs some type of feedback that something went wrong. And surely, I would log the exception.

But where would I catch this exception?

Should I catch it right there and then rethrow my own unchecked exception? Or should I declare a throws DataAccessException on the findAll method and then deal with the exception in the calling class (which may be a service or presenter of some sort)?

Or should I make sure that the conditions under which the exception is thrown can never occur (in case those are even controllable by me)?

user3813234
  • 1,580
  • 1
  • 29
  • 44
  • 1
    *throws a custom unchecked exception, how am I supposed to handle this?* You don't. If it's an unchecked exception, the caller is not generally expected to recover. – Elliott Frisch Apr 19 '17 at 11:18
  • You just leave it alone because you can't do anything with it, or you catch `RuntimeException` to handle this custom unchecked exception if you don't know what it is yet. – glee8e Apr 19 '17 at 11:19
  • If you want to catch any type of exceptions, you can add a catch (RuntimeException e) block or even the most generic Exception type. – airos Apr 19 '17 at 11:20
  • Did you see http://stackoverflow.com/questions/6115896/java-checked-vs-unchecked-exception-explanation?rq=1? –  Apr 19 '17 at 11:23
  • @GhostCat beside the fact that it's really hard to decide, I edited my question and I'm gonna wait a little, maybe somebody responds to my edit. – user3813234 Apr 25 '17 at 10:33
  • Perfectly fine. It is just a common practice of mine ... when I encounter old answers on questions that are not accepted, and try to figure if "accept forgotten" or "still waiting" or "answer not good enough". Because in the later case; I might be able to do something about that. – GhostCat Apr 25 '17 at 10:37

3 Answers3

9

I'm having difficulties understanding how to handle unchecked exceptions.

The how is easy. You handle them just like a checked exception. You use a try / catch. (To catch them all, catch RuntimeException, or catch Exception if you want checked exceptions as well. But beware of catching Error or Throwable, and of catching more exceptions than you expect or you can actually handle..)

What you really are asking is how to know when they will be thrown. That is more difficult.

  • As you observed, some unchecked exceptions are thrown by the language itself. In theory, it is possible to write code so that this won't happen. In practice: 1) people make mistakes, 2) too many defensive checks are onerous ... and pointless.

  • Other unchecked exceptions are explicitly declared as being thrown, or are documented as being thrown in a method or constructor's javadocs. (In fact, I would say that a well designed API should document the unchecked exceptions that it expects to throw or propagate.)

  • In the problem cases, you won't know about it until you see the exception at runtime.

The last case illustrates the need for thorough and repeatable testing as part of your development cycle.


But when I don't know that a method throws a custom unchecked exception, how am I supposed to handle this?

In general, you don't.

Any unexpected exception should be treated as a bug. You find either it in test or in production. You fix it. If you have fixed it properly the unexpected exception doesn't recur ... or it is now expected and your code handles it.

And the corollary is that if you do catch and handle an unexpected exception, it is a really bad idea for your code to pretend that nothing bad has happened. At the very least, the exception needs to be logged so that the programmer has something to work with to find the root cause.


And how do you propagate exceptions from the data layer to the user interface?

Generally, it is a bad idea to show exceptions (especially stacktraces!) to users. Normally, you catch them, log them ... together with the stacktrace ... and then tell the user: "Something bad happened: please report this to XXX with the following extra information".

Those must be checked exceptions, right?

Modulo the above ... No. They don't have to be checked exceptions.


I would let the data layer throw checked DataLayerExceptions and then have a try-catch-block in the presenter class (given I am using MVP) and then in the catch-block set the error message on the view.

You could do that. Modulo the point about showing exceptions to users.

Clearly, if you are going to take this approach, you need to be able to distinguish between the anticipated exceptions that you can explain to the user, handle and "carry on" versus the unanticipated exceptions that cannot be explained and cannot be recovered from. You may have some scheme in mind for doing that ...


Bottom line, there is no simple formula or "best practice" that will solve this problem for you. It requires thought and design ... and care ... and TESTING.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
2

When you write small "learning" applications; then it is absolutely fine to just let unchecked exceptions "bubble up" to the main method; and even have that stack trace printed to you on the command line.

In a "real world" application; you would at some level ensure that something catches such exceptions; to do things like:

  • present a meaningful error message to the user
  • create some sort of log entry for later debugging
  • decide whether the application can continue; or should "crash" (probably something that rarely do in the real world)

In other words: one important non-functional requirement of "real world" applications is robustness. You don't want that a missing null-check somewhere tears down your whole application. Thus you need to make sure that your application can continue to function in such situations. (and please note: I am not saying that such things are easy to implement).

Beyond that: you can use your own checked exception; but the big disadvantage there: they mess up your method signatures. But this is a highly opinionated discussion (and although certain important people claim "the war checked vs. unchecked is over; and unchecked won"); official documentation by Oracle still suggests that checked exceptions have their place in the real world.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Thhanks for your reply! How would you then deal with this in a real world complex application? – user3813234 Apr 19 '17 at 11:39
  • 1
    In ways that can't be broken down into a single answer. If I would be able to do that; I would have done so ;-) The essence is basically: this is a wide topic; and you can spend endless hours doing research; and endless hours of project work to deal with it ... – GhostCat Apr 19 '17 at 11:41
1

You should generally not catch out-of-the-blue, completely unexpected RuntimeExceptions. It would be ugly (your code would be full of try-catch statements), and there is no universally graceful way to recover from them.

Many of those RuntimeExceptions will be thrown due to programming errors, that you should fix as you are testing your application. Fixing the underlying error that causes, say, a NullPointerException beats any kind of catching-and-fixing that the calling code can possibly do.

Sometimes, APIs will throw RuntimeExceptions (read their documentation) that you are expected to catch. For example, parameter checking may result in IllegalArgumentException being thrown. In those cases, it may make sense to catch these specific exceptions and handle them gracefully (for instance, by re-throwing them as a custom checked exception; remember to use the cause parameter when re-throwing). In the case of those IllegalArguments, you could then mark the user's input as invalid and requesting that it be fixed. Good APIs will extensively describe what gets thrown when. Read the case against checked exceptions to understand why any API programmer would ever want to throw unchecked instead of checked exceptions.

However, as found in Ghostcat's (great) answer, if the application is going to have users (beyond a programming exercise), then the implicit catch-everything-and-show-stacktraces in main() should definitely be avoided. They are meaningless to non-developers, and do not provide enough context to actual developers unless they know what was going on before they were thrown. It is then good practice to

  • log any otherwise-uncaught exceptions so that you can later figure out what happened. You should already be using logging to help you figure out what was going on before the exception was thrown.

  • provide useful feedback to users that trigger them, so that they can do something about it. Notice that "useful" depends on the user; for an e-commerce web application, only developers would consider exception details useful; while buyers would be better served with a friendly-looking, low-on-details error message, essentially asking them to retry later.

It is a bad idea to, instead of the above two points, wrap all unchecked exceptions with a custom checked exception. It fixes nothing: you would still need to take the above two steps to try to fix things later.

Community
  • 1
  • 1
tucuxi
  • 17,561
  • 2
  • 43
  • 74