Closed as not planned
Description
What happened?
The PageFactory.initElements(element, this)
method overrides all object's fields, including assigned final fields.
I think this behavior is not correct - final fields should not be changed by reflection.
Even IntelliJ hints that the assigned final fields should not change:
The problem occurs in the selenium-support
artifact
- It is not related to the browser vendor or browser version
Proposed solution:
- The
DefaultFieldDecorator
should ignore final fields when decorating objects. - Additionally: the
DefaultFieldDecorator
should also ignore static fields when decorating objects.
How can we reproduce the issue?
index.html
<div class="card">
<h2>Title 1</h2>
<p>Description 1</p>
</div>
<div class="card">
<h2>Title 2</h2>
<p>Description 2</p>
</div>
<div class="card">
<h2>Title 3</h2>
<p>Description 3</p>
</div>
MainApp.java
import org.openqa.selenium.By;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import java.io.File;
public class MainApp {
public static void main(String[] args) throws InterruptedException {
var options = new FirefoxOptions();
options.setBinary("/snap/firefox/current/usr/lib/firefox/firefox");
var webDriver = new FirefoxDriver(options);
webDriver.get(new File("index.html").toURI().toString());
Thread.sleep(1000);
var cards = webDriver.findElements(By.cssSelector(".card")).stream()
.map(CardComponent::new)
.toList();
for (var card : cards) {
System.out.println("Card title: '" + card.getTitle() + "' description: '" + card.getDescription() + "'");
}
webDriver.close();
}
}
CardComponent.java
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
public class CardComponent extends Component {
@FindBy(css = "h2")
private WebElement title;
@FindBy(css = "p")
private WebElement description;
protected CardComponent(WebElement element) {
super(element);
}
public String getTitle() {
return title.getText();
}
public String getDescription() {
return description.getText();
}
}
Component.java
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.PageFactory;
public abstract class Component {
private final WebElement element;
protected Component(WebElement element) {
this.element = element;
PageFactory.initElements(element, this);
if (this.element != element) {
throw new IllegalStateException("this.element != element");
}
}
}
Relevant log output
Exception in thread "main" java.lang.IllegalStateException: this.element != element
at Component.<init>(Component.java:12)
at CardComponent.<init>(CardComponent.java:12)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575)
at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616)
at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622)
at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627)
at MainApp.main(MainApp.java:20)
### Operating System
Linux, Windows
### Selenium version
java 4.24.0
### What are the browser(s) and version(s) where you see this issue?
Firefox 129.0.2
### What are the browser driver(s) and version(s) where you see this issue?
geckodriver 0.34.0
### Are you using Selenium Grid?
_No response_