Re-throw an InvocationTargetException target exception
Asked Answered
D

5

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?

Dash answered 18/4, 2012 at 17:17 Comment(0)
G
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.
    }
}
Geopolitics answered 18/4, 2012 at 17:23 Comment(4)
How can you have a null cause for an InvocationTargetException?Crain
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.Geopolitics
This work great! I didn't realize that I could cast the cause to an Exception and throw it. Thanks!Dash
Be careful, sometime getCause() is empty and the exception is in getTargetException()Bernardina
K
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();
Kado answered 18/4, 2012 at 17:21 Comment(0)
G
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" ;
          }
    }
}
Gerthagerti answered 18/4, 2012 at 18:15 Comment(0)
J
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;
}
Jehovist answered 18/4, 2012 at 17:20 Comment(3)
The OP wants the cause of the InvocationTargetExceptionKado
This just throws the same Exception. I want to "eat" the InvocationTargetException and only throw the target Exception.Dash
then you have to do: throw (Exception) e.getCause(); (like Tim Bender said)Jehovist
C
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());
    }
}
Crain answered 18/4, 2012 at 17:25 Comment(1)
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?.Hanshansard

© 2022 - 2024 — McMap. All rights reserved.