I think the e-mail example is the best defense of checked exceptions. You have something that can go wrong and is transient, so the existence of a checked exception makes you think about it. If everything was a Runtime exception, your application would just blow up for trivial reasons and no one would think about it.
Anyway, if for your project, the general answer is throw it up to the top, then wrapping in a Runtime Exception is perfectly valid. A couple of things to think about:
Insist on Exception Chaining. The only reason to not do this is if you are serializing the exception, then things could get interesting with some exceptions containing non-serializable members. That doesn't seem to be the case, so don't allow exception swallowing. Use initCause if you have to. Here is a little helper method in our project:
public static <T extends Throwable> T initCause(T newException, Throwable cause) {
return (T) newException.initCause(cause);
}
This helps people avoid the need to cast the exceptions.
I prefer avoiding unnecessary chaining of RuntimeException and Error Throwables that inevitably happen when there are many different Checked Exceptions on a method and the developer just catches Exception, so I recommend a static method that does something like this:
public static void throwRuntimeExceptionFromThrowable(Throwable e) {
if (e == null) {
return;
} else if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else if (e instanceof Error) {
throw (Error) e;
} else {
throw new RuntimeException(e.getMessage(), e);
}
}
There are two options with this. One is to make it void (as this code does), which has the upside of the caller never forgetting to throw the result. The downside is if you have something like this:
public Object someMethod() {
try {
return getTheObject();
} catch (Exception e) {
throwRuntimeExceptionFromThrowable(e);
}
}
The compiler won't like you. You will have to return after the catch, and declare a variable before the try.
The other option is to return the Exception as a RuntimeException (just throw the Error) and have the caller do the throw. The compiler is happier, but the caller may forget to do it, and call the method without a throw in front of it, and then the exception gets swallowed.