UndeclaredThrowableException thrown by IndexOutOfBoundsException

Nathan Merrill picture Nathan Merrill · Oct 30, 2013 · Viewed 29.9k times · Source

I am using the decorator pattern for a List<WebElement>.Part of this decoration entails using a proxy.

When I call get(index) with an index that is out of bounds, it throws an IndexOutOfBounds exception, which is then caught by the proxy, and wrapped with an UndeclaredThrowableException.

My understanding is that it should only do this if its a checked exception. IndexOutOfBounds is an unchecked exception, so why is it getting wrapped?

It still gets wrapped even if I add throws IndexOutOfBounds to my invoke function.

Here's my code:

@SuppressWarnings("unchecked")
public WebElementList findWebElementList(final By by){
    return new WebElementList(
            (List<WebElement>) Proxy.newProxyInstance(this.getClass().getClassLoader(),
                    new Class<?>[] { List.class }, new InvocationHandler() {
        // Lazy initialized instance of WebElement
        private List<WebElement> webElements;

        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            if (webElements == null) {
                webElements = findElements(by);
            }
            return method.invoke(webElements, args);
        }
    }), driver);
}

Here's part of my stacktrace:

java.lang.reflect.UndeclaredThrowableException
at com.sun.proxy.$Proxy30.get(Unknown Source)
at org.lds.ldsp.enhancements.WebElementList.get(WebElementList.java:29)
...
Caused by: java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.rangeCheck(ArrayList.java:604)
at java.util.ArrayList.get(ArrayList.java:382)
... 41 more

Answer

Zorg picture Zorg · Aug 19, 2015

Vic Jang is right. You need to wrap the invocation in try-catch and rethrow the inner exception.

try {
  return method.invoke(webElements, args);
} catch (InvocationTargetException ite) {
  throw ite.getCause();
}

The reason is that "Method.invoke" wraps in InvocationTargetException those exceptions which are thrown in the method's code.

java.lang.reflect.Method:

Throws:
...
InvocationTargetException - if the underlying method throws an exception.

java.lang.reflect.InvocationTargetException:

InvocationTargetException is a checked exception that wraps an exception thrown by an invoked method or constructor.

The proxy object's class doesn't have InvocationTargetException declared among its "throws". That leads to UndeclaredThrowableException.