Skip to content

[🐛 Bug]: [java] PageFactory.initElements overrides final fields #14474

Closed as not planned
@mk868

Description

@mk868

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:
image

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_

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-needs-triagingA Selenium member will evaluate this soon!C-javaJava BindingsI-defectSomething is not working as intended

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions