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
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.