I have following pointcut and the given advice in AspectJ
@Pointcut("(call(* org.openqa.selenium.WebElement.sendKeys(..)))")
public void onWebElementAction() {
}
@After("onWebElementAction() && target(webelement)")
public void afterWebElementAction(JoinPoint joinPoint, WebElement webelement) {
System.out.println(webelement.getAttribute("name")); //1
WebDriver driver = ((WrapsDriver) webelement).getWrappedDriver(); //2
//DO SOMETHING HERE
}
While the line 1 is executed without any error. It is on line 2 I get error
java.lang.ClassCastException: com.sun.proxy.$Proxy8 cannot be cast to org.openqa.selenium.internal.WrapsDriver
The casting works in other places without issues. Can someone please help?
While the answer flagged as correct does point out the issue, it doesn't explain the issue nor suggests a solution which does actually exist. Let me begin with giving a bit more of detail around the underlying issue here which is the way the WebElement
could have been instantiated.
On one hand, when a WebElement
gets instantiated as the result of a call to WebDriver#findElement
, the actual RemoteWebElement
object gets constructed at that very moment, however, when a WebElement
gets instantiated via PageFactory#initElements
, the actual concrete class object (RemoteWebElement
) doesn't get created at that point but instead a proxy does.
Here is where the main issue relies. The proxy object does NOT implement the WrapsDriver
interface and that is why the cast exception is thrown, which is perfectly fine. However, if you are curious enough to see how the actual proxy creation is done (at least by the default decorator), you will see that the object instantiated as the proxy does instead implement the WrapsElement
interface which does offer the method getWrappedElement
so, with it, you can extract the underlying WebElement
and then with this, extract the underlying WebDriver
, just as you are trying.
Now, the key here is that any WebElement
instantiated via WebDriver#findElement
does not implement WrapsElement
because it is the actual element and not a proxy so, before you attempt using WrapsElement#getWrappedElement
, you first need to check if the passed WebElement
is actually a proxy or not.
You can achieve this with reflection, i.e.
if(WrapsElement.class.isAssignableFrom(element.getClass()))
webDriver = ((WrapsDriver)((WrapsElement)element).getWrappedElement()).getWrappedDriver();
else
webDriver = ((WrapsDriver)element).getWrappedDriver();
tl;dr
The WebElement
instance you are using was instantiated via PageFactory#initElements
and you first need to extract the underlying WebElement
with WrapsElement#getWrappedElement
and then the WebDriver
from it.
This is a wild guess since I don't see a case where it actually worked. From the exception it seems that the WebElement that is being passed to afterWebElementAction
is initialized via PageFactory
. My guess is that if you pass WebElement derived from driver.findElement(), to afterWebElementAction
, you wouldn't get casting exception. This is how it must be working for you in other cases most likely.
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