Hi Jerome, 

> >             } catch (InvocationTargetException e) {
> >                 if (e.getCause() instanceof Error) {
> >                     throw (Error) e.getCause();
> >                 } else {
> >                     getLogger() [...]
> >                 }
> I spoke too fast, we should also consider RuntimeExceptions:
>   catch(InvocationTargetException e){
>     if (e.getCause() instanceof Error 
>       || e.getCause() instanceof RuntimeException) {
>                       throw (Error) e.getCause();
>     }
>    getLogger()....
>   }

This solution doesn't work because if the cause is a RuntimeException, we can't
cast it to an Error (doh!). And if we rethrow it as a RuntimeException, it'll
get caught by the catch(Exception e) block of the enclosing try block.
So, the solution is to throw a RuntimeException from the inner try blok, and let
it bubble up from the outer try block:

public Resource createResource(Request request, Response response) {
  Resource result = null;

  try {
     ...
    try {

    } catch(InvocationTargetException e){
        if (e.getCause() instanceof Error){
          throw (Error) e.getCause();
        }
        if ( e.getCause() instanceof RuntimeException) {
           throw (RuntimeException) e.getCause();
        }
        getLogger()...

    }                        
   } catch (RuntimeException e){
     // Let unchecked exceptions bubble up
     throw e;
   } 
   }catch (Exception e) {
     getLogger()...
   }
 }

    return result;
 }


In short: we make sure we let all unchecked exceptions (errors & runtime) flow
through the method, while all checked ones (Exceptions that are not runtime) are
trapped and logged. We should also document the fact that Resource constructors
should never throw checked exceptions.

-Vincent.

Reply via email to