Vadzim Vadzim - 3 months ago 13
Java Question

Guava cache and preserving checked exceptions

I'm refactoring some code to use guava Cache.

Initial code:

public Post getPost(Integer key) throws SQLException, IOException {
return PostsDB.findPostByID(key);
}


In order not to break something I need to preserve any thrown exception as is, without wrapping it.

Current solution appears somewhat ugly:

public Post getPost(final Integer key) throws SQLException, IOException {
try {
return cache.get(key, new Callable<Post>() {
@Override
public Post call() throws Exception {
return PostsDB.findPostByID(key);
}
});
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof SQLException) {
throw (SQLException) cause;
} else if (cause instanceof IOException) {
throw (IOException) cause;
} else if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
} else {
throw new IllegalStateException(e);
}
}
}


Is there any possible way to make it nicer?

Answer

Just after writing the question started thinking about utility method powered with generics. Then remembered something about Throwables. And yes, it's already there! )

So the solution is:

public Post getPost(final Integer key) throws SQLException, IOException {
    try {
        return cache.get(key, new Callable<Post>() {
            @Override
            public Post call() throws Exception {
                return PostsDB.findPostByID(key);
            }
        });
    } catch (ExecutionException e) {
        Throwables.propagateIfPossible(
            e.getCause(), SQLException.class, IOException.class);
        throw new IllegalStateException(e);
    } catch (UncheckedExecutionException e) {
        Throwables.propagate(e.getCause());
        throw new IllegalStateException(e);
    }
}

Very nice!

See also ThrowablesExplained.