8

How does one re-throw the target exception of an InvocationTargetException. I have a method which uses reflection to call the invoke() method within one of my classes. However, if there is an Exception thrown within my code, I am not concerned about the InvocationTargetException and only want the target exception. Here is an example:

public static Object executeViewComponent(String name, Component c,
        HttpServletRequest request) throws Exception {

    try {
        return c.getClass()
                .getMethod(c.getMetaData().getMethod(), HttpServletRequest.class)
                .invoke(c, request);
    } catch (InvocationTargetException e) {
        // throw the target exception here
    }
}

The primary problem I am facing is that calling throw e.getCause(); doesn't throw an Exception but rather throws a Throwable. Perhaps I am approaching this incorrectly?

Vincent Catalano
  • 2,259
  • 4
  • 22
  • 29

5 Answers5

20
catch (InvocationTargetException e) {
    if (e.getCause() instanceof Exception) {
        throw (Exception) e.getCause();
    }
    else {
        // decide what you want to do. The cause is probably an error, or it's null.
    }
}
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • How can you have a `null` cause for an InvocationTargetException? – Peter Lawrey Apr 18 '12 at 17:26
  • I don't think it'll ever be the cause when this exception is thrown by Method.invoke(), but InvocationTargetException has a constructor allowing a null target, so in other situations, it might be null. I don't know for sure, from the Method.invoke API doc, if an Error is wrapped inside an InvocationTargetException of thrown as is. – JB Nizet Apr 18 '12 at 17:28
  • This work great! I didn't realize that I could cast the cause to an Exception and throw it. Thanks! – Vincent Catalano Apr 18 '12 at 18:51
  • Be careful, sometime getCause() is empty and the exception is in getTargetException() – kaiser Nov 21 '18 at 18:40
2

Exception#getCause returns a Throwable. If you want the compiler to think you are throwing an Exception then you probably need to cast it.

throw (Exception) e.getCause();
Tim Bender
  • 20,112
  • 2
  • 49
  • 58
1

The below is verbose, but I like to avoid reflection and casting. I don't think (but am not sure) that Java 7's multi catch syntax would be useful.

public static Object executeViewComponent(String name, Component c,
        HttpServletRequest request) throw KnownException_1 , KnownException_2 , ... , KnownException_n {

    try {
        return c.getClass()
                .getMethod(c.getMetaData().getMethod(), HttpServletRequest.class)
                .invoke(c, request);
    }
    catch ( InvocationTargetException cause )
    {
          assert cause . getCause ( ) != null : "Null Cause" ;
          try
          {
               throw cause . getCause ( ) ;
          }
          catch ( KnownException_1 c )
          {
                throw c
          }
          catch ( KnownException_2 c )
          {
                throw c
          }
          ...
          catch ( KnownException_n c )
          {
                throw c
          }
          catch ( RuntimeException c )
          {
                throw c ;
          }
          catch ( Error c )
          {
                throw c ;
          }
          catch ( Throwable c )
          {
                assert false : "Unknown Cause" ;
          }
    }
}
emory
  • 10,725
  • 2
  • 30
  • 58
0

You can rethrow any exception you caught before by using the throw keyword and the corresponding object you caught:

catch (XXXException e)
{
       throw e;
}
Stephan
  • 1,639
  • 3
  • 15
  • 26
0

You can rethrow the cause without declaring it explicitly.

public static Object executeViewComponent(String name, Component c,
        HttpServletRequest request) throw /* known exceptions */ {

    try {
        return c.getClass()
                .getMethod(c.getMetaData().getMethod(), HttpServletRequest.class)
                .invoke(c, request);
    } catch (InvocationTargetException e) {
        // rethrow any exception.
        Thread.currentThread().stop(e.getCause());
    }
}
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • it works, but it's dangerous. stop() method has been deprecated for a good reason. This is from stop() API docs: Deprecated This method is inherently unsafe. See stop() for details. An additional danger of this method is that it may be used to generate exceptions that the target thread is unprepared to handle (including checked exceptions that the thread could not possibly throw, were it not for this method). For more information, see Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?. – dgt Nov 20 '13 at 14:55