Note that there are some explanatory texts on larger screens.

plurals
  1. POjava: standard method of wrapping checked exceptions
    primarykey
    data
    text
    <p>I have a fairly detailed question about the right way to wrap a checked exception, and the way that Guava does it. (Apologies for the length but I want to get my thought process down)</p> <hr> <p>The standard Runnable interface looks like this:</p> <pre><code>public interface Runnable { public void run(); } </code></pre> <p>where <code>run()</code> can't throw a checked exception.</p> <p>So if I want to have a <code>Runnable</code> which is used to wrap tasks which throw checked exceptions, and I intend to have the thing that calls <code>Runnable.run()</code> handle those exceptions, rather than in <code>Runnable.run()</code> itself, I have to wrap the exception in an unchecked exception.</p> <p>So for a while I was using:</p> <pre><code>Runnable r = new Runnable { @Override public void run() { try { doNastyStuff(); } catch (NastyException e) { throw new RuntimeException(e); } } }; </code></pre> <p>and then I can handle RuntimeException in an upper level. Except then I figured, that what I really want is to handle a wrapped exception separately, since I know its semantics are to wrap a checked exception, so I wrote this helper class:</p> <pre><code>/** * Wrapped exception: the purpose of this is just to wrap another exception, * and indicate that it is a wrapped exception */ public class WrappedException extends RuntimeException { /** * @param t any throwable */ public WrappedException(Throwable t) { super(t); } } </code></pre> <p>and then I can do this:</p> <pre><code>/* place that produces the exception */ ... catch (NastyException e) { throw new WrappedException(e); } ... /* upper level code that calls Runnable.run() */ try { ... SomeOtherNastyCode(); r.run(); ... } catch (SomeOtherNastyException e) { logError(e); } catch (WrappedException e) { logError(e.getCause()); } </code></pre> <p>and it seems to work great.</p> <p>But now I'm thinking, well, if I want to use this in a library as well as an application that uses the library, now they both depend on WrappedException, so it should really be in a base library that I can include everywhere.</p> <p>Which makes me think, maybe Guava has a standard WrappedException class somewhere, since I now include Guava as a dependency by default. So I can just do</p> <pre><code>throw new WrappedException(e); </code></pre> <p>or</p> <pre><code>throw Exceptions.wrap(e); </code></pre> <p>or</p> <pre><code>Exceptions.rethrow(e); </code></pre> <p>I just looked around in Guava and found <a href="http://guava-libraries.googlecode.com/svn/tags/release09/javadoc/com/google/common/base/Throwables.html" rel="nofollow noreferrer">Throwables</a> which has <a href="http://guava-libraries.googlecode.com/svn/tags/release09/javadoc/com/google/common/base/Throwables.html#propagate%28java.lang.Throwable%29" rel="nofollow noreferrer"><code>Throwables.propagate()</code></a> that looks similar, but it just wraps checked exceptions in a <code>RuntimeException</code>, rather than a special subclass of RuntimeException.</p> <p>Which approach is better? Should I not be using a special WrappedException as compared with a RuntimeException? My top-level code wants to know the topmost exception that adds informational value. </p> <p>If I have a RuntimeException that wraps a NastyException that wraps a NullPointerException, the wrapping RuntimeException doesn't add informational value, and I don't care about it, so the error I would log would be the NastyException.</p> <p>If I have an IllegalArgumentException that wraps a NastyException, the IllegalArgumentException does generally add informational value.</p> <p>So in my top code that does error logging, I'd have to do something like this:</p> <pre><code>catch (RuntimeException re) { logError(getTheOutermostUsefulException(re)); } /** * heuristics to tease out whether an exception * is wrapped just for the heck of it, or whether * it has informational value */ Throwable getTheOutermostUsefulException(RuntimeException re) { // subclasses of RuntimeException should be used as is if (re.getClass() != RuntimeException) return re; // if a runtime exception has a message, it's probably useful else if (re.getMessage() != null) return re; // if a runtime exception has no cause, it's certainly // going to be more useful than null else if (re.getCause() == null) return re; else return re.getCause(); } </code></pre> <p>The philosophy feels right for me, but the implementation feels bad. Is there a better way to handle wrapped exceptions?</p> <hr> <p>related questions: </p> <ul> <li><a href="https://stackoverflow.com/questions/5090417/how-do-i-use-throwables-propagateifinstanceof-from-google-guava">How do I use Throwables.propagateIfInstanceOf() from Google Guava?</a></li> <li><a href="https://stackoverflow.com/questions/484794/wrapping-a-checked-exception-into-an-unchecked-exception-in-java">Wrapping a checked exception into an unchecked exception in Java?</a></li> </ul>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload