5

Let's say I have a few methods that access the File System, and I want them to be a bit robust, I want to throw errors so the user can react:

  • If the file doesn't have read / write rights, I want to inform him/her.
  • If the file does not exist, I want to prompt him/her to chose another one.

And so forth.

Thing is, the exceptions are cluttering the code a bit:

  • FileNotFoundException: quite necessary, the file was not found, try again or give up.

  • IOException: This is usually when the file can't be read for whatever reason.
    It was there, but now it's not, you don't have access rights any more, something went horribly wrong. Generally this is a stopping point, but still the user could choose another file or something, I'd rather not crash the app.

  • InvalidPathException: Either the developer, or the user tried to give a bad path (like including an illegal character in the file name, again, the app should not crash because of this.

In my case I'd say all these exceptions are important because IOE captures FNFE, but they get resolved differently, and while FNFE and Invalid Path are similar, I still have to throw them separately, but at least catch them together.

My question is

When exceptions start piling up, the code starts to get ugly, I'm guessing there's no work around for this?

Kalec
  • 210
  • 2
  • 11
  • What version of Java are you working with? –  Sep 28 '15 at 11:15
  • 1.8.0.45 or something like that – Kalec Sep 28 '15 at 11:18
  • You can multi-catch with Java 7 and later. I have a bit of example with it in http://programmers.stackexchange.com/a/263900/40980 . Relevant docs: https://docs.oracle.com/javase/8/docs/technotes/guides/language/catch-multiple.html –  Sep 28 '15 at 11:22
  • Oh, multi-catch looks kinda great. This was just a small example, but I do have situations where 3 exceptions could be caught by the same thing. This sorta answers the question I guess. – Kalec Sep 28 '15 at 11:26
  • Just noticed you are the same OP as in [this related question](http://programmers.stackexchange.com/questions/297298/proper-propagation-handling-of-exceptions). – Spotted Sep 28 '15 at 11:36
  • @Spotted I just can't decide. I wish I knew a good book on this stuff, or an online training, or anything really. – Kalec Sep 28 '15 at 11:41
  • 1
    @Kalec there is sadly no universal answer/book/stuff and the debate around exceptions (checked, unchecked, single throw, multi throw, etc.) is endless. :-/ – Spotted Sep 28 '15 at 11:49
  • @Kalec in the answer that I linked, ***carefully*** mouse over the word 'great' and look at the links. There are a large number of philosophies for handling exceptions - all of them are somewhat right and all of them are somewhat flawed. –  Sep 28 '15 at 12:57

2 Answers2

5

Since the flow should be the same with the 3 kinds of exceptions:

  • The user choose a file
  • If the file couldn't be openend (either because the file doesn't exist, is locked, invalid path, ...), prompt him with a custom message
  • Allow the user to retry the operation

I suggest to create a custom class inheriting from Exception. In this exception you should wrap:

  • the original exception (IOE, FNFE, IPE) to preserve the stacktrace
  • a custom message that could be displayed to the user (or a key to a i18n string if you need)

Example:

public final class FileException extends Exception {
    public FileException(String message, Throwable cause) {
        super(message, cause);
    }
}

The most important step in your code is to throw a FE like this:

try {
    //some operation that can throw an FNFE
}
catch(FileNotFoundException e) {
    throw new FileException("The file doesn't exist !", e);
}
Spotted
  • 1,680
  • 10
  • 18
  • AHA! this makes so much sense. So instead of throwing four different exceptions, I just throw my custom exception. Because most of these exceptions (not all, but most) are handled in the same manner! – Kalec Sep 28 '15 at 11:54
3

Confine the crud necessitated by multiple exceptions to the smallest possible scope, and then wrap it into your own exception type that preserves all the original information.

To elaborate: say you have to deal with FileNotFoundException, PermissionsException, ReadOnlyFileSystemException and invalidpathException, and all of these don't have a common super type (or you don't want to dilute the information that much by catching plain IOException). What you should do is write a method that catches all of these different exceptions and rethrows a self-written PreferencesException in every case, just annotated with the orignal error information if needed. That way, every other method in your code base only has to deal with that exception type (or possibly with no type at all if your new exception type isn't a checked exception).

Kilian Foth
  • 107,706
  • 45
  • 295
  • 310
  • On the surface this sounds amazing, however I am not skilled enough to figure out how I could "intercept" these exceptions into my very own exception. I can't see how to separate program logic from a method that wold catch all of these. Unless ... no, I have to give this some serous thought. – Kalec Sep 28 '15 at 11:53