Java Exception Handling

Java Exception Handling – InvocationTargetException

Moving along through our in-depth Java Exception Handling series, today we’ll take a closer look at the java.lang.reflect.InvocationTargetException. The java.lang.reflect.InvocationTargetException is thrown when working with the reflection API while attempting to invoke a method that throws an underlying exception itself.

In this article we’ll explore the InvocationTargetException in more detail by looking at where it resides in the Java Exception Hierarchy. We’ll also dig into a few functional reflection code samples that will illustrate how java.lang.reflect.InvocationTargetExceptions are typically thrown, showing how you might handle them in your own code, so let’s get crackin’!

The Technical Rundown

When Should You Use It?

Since the InvocationTargetException deals with reflection, let’s briefly talk a bit about that practice and why explicitly invoking a method via reflection might be useful. In the most basic sense, reflection allows the JVM and your underlying code to inspect classes, methods, interfaces, and the like during runtime, without having directly called or identified those objects during compilation. This powerful capability means that your code can find classes and invoke methods that it wasn’t originally designed to handle out of the box.

To illustrate how invocation in Java works we have a few basic examples. To keep things simple, we’ll start with the full working code sample below, after which we’ll break it down in more detail to see what’s really going on:

As briefly mentioned in the introduction, an InvocationTargetException is automatically generated by reflection-related objects, and wraps (or attaches) itself to the underlying, actual exception type that caused the problem. This occurs when calling the java.lang.reflect.Method.invoke() method, where that invocation target method throws an exception.

To illustrate the issue we’ve got a basic Book class with a few property getter/setter methods, along with a some extraneous methods (getTagline() and throwException()) that we’ll explicitly call in the rest of our code:

The invokeGetTaglineMethod() method shows a basic, working example of using Java reflection to invoke() a class instance method (Book.getTagline(), in this case).

The comments explain most everything that we’re doing, but the basic idea is that we starting by creating a Book instance object of book. We then need to instantiate a Class<?> object, so we get a reflection of io.airbrake.Book, from which we can retrieve the declared getTagline() method. Using that Method instance of getTagline() we’re able to invoke() the method. Since this is an instance method, we need to pass an instance of the object as the first argument, so this is where we use the book object that was created at the beginning.

Executing this code results in the book object output, followed by the output from calling getTagline.invoke(book), as expected:

Now that we’ve seen how invocation works, let’s try invoking a different Book instance method, specifically the Book.throwException() method. As its name suggests, Book.throwException() merely throws an Exception, using the passed String argument for the message:

To test this we’ll execute the invokeThrowExceptionMethod() method, which performs almost exactly the same code as our previous example, except the calls to getDeclaredMethod() and invoke() differ slightly since we’re also passing arguments to the invoked method:

Since the Book.throwException() method we’re invoking explicitly throws an error, our expectation is that executing the above code will result in a java.lang.reflect.InvocationTargetException being thrown. Sure enough, that’s exactly what happens:

Normally we’d only catch the parent InvocationTargetException in this scenario, which indicates the it was "Caused by: java.lang.Exception ...". However, a Throwable object implements the getCause() method, which returns the causal exception (if applicable). In the case of a InvocationTargetException instance, the cause is always the underlying exception object that occurred inside the invoked method, so checking for a cause when catching such exceptions is a good idea.

The Airbrake-Java library provides real-time error monitoring and automatic exception reporting for all your Java-based projects. Tight integration with Airbrake’s state of the art web dashboard ensures that Airbrake-Java gives you round-the-clock status updates on your application’s health and error rates. Airbrake-Java easily integrates with all the latest Java frameworks and platforms like Spring, Maven, log4j, Struts, Kotlin, Grails, Groovy, and many more. Plus, Airbrake-Java allows you to easily customize exception parameters and gives you full, configurable filter capabilities so you only gather the errors that matter most.

Check out all the amazing features Airbrake-Java has to offer and see for yourself why so many of the world’s best engineering teams are using Airbrake to revolutionize their exception handling practices!