4

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
  • 200

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,690
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
  • 110,899