14

The javadoc example

  try {
    someMethodThatCouldThrowAnything();
  } catch (IKnowWhatToDoWithThisException e) {
    handle(e);
  } catch (Throwable t) {
    Throwables.propagateIfInstanceOf(t, IOException.class);
    Throwables.propagateIfInstanceOf(t, SQLException.class);
    throw Throwables.propagate(t);
  }

is not very concrete. How would a real program look like? I don't really understand the purpose of the methods Throwables.propagateIfInstanceOf(Throwable, Class), propagate(), propagateIfPossible(). When do I use them?

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
Tony Merrit
  • 171
  • 2
  • 6

3 Answers3

17

The purpose of these methods is to provide a convenient way to deal with checked exceptions.

Throwables.propagate() is a shorthand for the common idiom of retrowing checked exception wrapped into unchecked one (to avoid declaring it in method's throws clause).

Throwables.propagateIfInstanceOf() is used to retrow checked exceptions as is if their types are declared in throws clause of the method.

In other words, the code in question

public void doSomething() 
    throws IOException, SQLException {

    try {
        someMethodThatCouldThrowAnything();
    } catch (IKnowWhatToDoWithThisException e) {
        handle(e);
    } catch (Throwable t) {
        Throwables.propagateIfInstanceOf(t, IOException.class);
        Throwables.propagateIfInstanceOf(t, SQLException.class);
        throw Throwables.propagate(t);
    }  
}

is a shorthand for the following code:

public void doSomething() 
    throws IOException, SQLException {

    try {
        someMethodThatCouldThrowAnything();
    } catch (IKnowWhatToDoWithThisException e) {
        handle(e);
    } catch (SQLException ex) {
        throw ex;
    } catch (IOException ex) {
        throw ex;
    } catch (Throwable t) {
        throw new RuntimeException(t);
    }  
}

See also:

Community
  • 1
  • 1
axtavt
  • 239,438
  • 41
  • 511
  • 482
  • 5
    The second version of the method you wrote isn't equivalent... you'd need to add two more `catch` blocks that just rethrow the exception... one for `RuntimeException` and one for `Error`. `Throwables.propagate` only wraps the throwable in a `RuntimeException` if it isn't already an unchecked exception. – ColinD Feb 23 '11 at 14:37
  • I still don't unterstand. Why do I want to catch an exception if I want to propagate it anyway? I can do: public void doSomething() throws IOException, SQLException { try { someMethodThatCouldThrowAnything(); } catch (IKnowWhatToDoWithThisException e) { handle(e); } }. This is not a real example ... – Tony Merrit Feb 25 '11 at 01:55
  • 1
    @Jeny: You can't do so is ` someMethodThatCouldThrowAnything()` can throw some checked exceptions other than `IOException` and `SQLException`. – axtavt Feb 25 '11 at 09:19
  • True, then we wrap it in a RuntimeException and not re-thow as-is. That’s a different usecase and solely depends on Throwables.propagate(t) but it doesn’t explain a scenario without this behavior. Or do we always end blocks with propagate()? And is the whole idea ONLY to re-throw everything we can as-is and the rest in a RE and nothing else? Then I start to understand… – Tony Merrit Feb 25 '11 at 23:30
2

I have gone through the documentation of the Guava Throwables and I haven't found them really useful. Using throw new RuntimeException(e) is simpler to comprehend than Throwables.propagate(), in the scenario where you want to throw an unchecked exception wrapping a checked exception.

Dhiraj
  • 550
  • 6
  • 14
  • You don't have to check whatever your throwable is a specific checked exception, a runtime one or an error. It prevents for too many throwable encapsulation. It's not unusual to see kilometers of wrapped RuntimeException which leads to a very long stack traces to go through. And finally see that the only last has value. – LoganMzz Aug 17 '15 at 09:02
0

One scenario I can provide for anyone who'll find this useful is if you have a method wrapping any exceptions thrown, then this can be used to unwrap/cast the cause into specific exception.

Example: the get method in Guava's LoadingCache wraps all checked exceptions into ExecutionException. The documentation states that the exception can be inspected using getCause().

Here Throwables.propagateIfInstanceOf can be used to throw specific exceptions for the calling method to handle, if we know that cache.get() will throw those exceptions (maybe specific to LoadingCache, but if value is misisng, the cache tries to load a value which can throw checked exceptions).

public String getCacheValue(String key) throws SQLException{
  try{
       return cache.get(key);
  }catch(ExecutedException ex){
       Throwables.propagateIfInstanceOf(ex.getCause(), SQLException.class);
       Throwables.propagate(ex);
  }
}
afrin216
  • 2,295
  • 1
  • 14
  • 17