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.
I don't have enough reputation to comment. Your problem seems very similar to this one
You can look at the solution there and see if that works.
In short, you need to wrap your method.invoke
into try{}
, catch
the exception, and throw
it again.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With