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)
The standard Runnable interface looks like this:
public interface Runnable
{
   public void run();
}
where run() can't throw a checked exception.
So if I want to have a Runnable which is used to wrap tasks which throw checked exceptions, and I intend to have the thing that calls Runnable.run() handle those exceptions, rather than in Runnable.run() itself, I have to wrap the exception in an unchecked exception.
So for a while I was using:
Runnable r = new Runnable {
   @Override public void run()
   {
       try {
          doNastyStuff();
       }
       catch (NastyException e)
       {
          throw new RuntimeException(e);
       }
   }      
};
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:
/**
 * 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);
    }
}
and then I can do this:
/* 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());
}
and it seems to work great.
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.
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
throw new WrappedException(e);
or
throw Exceptions.wrap(e);
or
Exceptions.rethrow(e);
I just looked around in Guava and found Throwables which has Throwables.propagate() that looks similar, but it just wraps checked exceptions in a RuntimeException, rather than a special subclass of RuntimeException.
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.
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.
If I have an IllegalArgumentException that wraps a NastyException, the IllegalArgumentException does generally add informational value.
So in my top code that does error logging, I'd have to do something like this:
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();
}
The philosophy feels right for me, but the implementation feels bad. Is there a better way to handle wrapped exceptions?
related questions:
 
     
     
    