Overview
Concrete tool for initializing Page Object fields with lazy-loading element proxies provided by the Selenium Support library.
Description
PageFactory.initElements() scans a Page Object class via reflection, processes @FindBy, @FindAll, and @FindBys annotations using AbstractFindByBuilder implementations, and replaces annotated fields with JDK dynamic proxies created by DefaultFieldDecorator. Four overloads exist: (1) class-based -- creates an instance via a WebDriver constructor or no-arg constructor and initializes it, (2) instance-based with SearchContext -- initializes fields on an existing object using DefaultElementLocatorFactory, (3) factory-based with ElementLocatorFactory -- uses a custom locator factory wrapped in DefaultFieldDecorator, and (4) decorator-based with FieldDecorator -- provides full control over the decoration strategy. The reflection scan walks the entire class hierarchy from the page class up to (but not including) Object.class.
Usage
Call in Page Object constructors or test setup methods. The class-based overload is convenient for creating and initializing in one step. The instance-based overload is the most common, typically called as PageFactory.initElements(driver, this) inside a Page Object constructor.
Code Reference
Source Location
- Repository: Selenium
- File: java/src/org/openqa/selenium/support/PageFactory.java (L34-133)
- File: java/src/org/openqa/selenium/support/pagefactory/DefaultFieldDecorator.java (L41-113)
- File: java/src/org/openqa/selenium/support/pagefactory/DefaultElementLocatorFactory.java (L23-34)
- File: java/src/org/openqa/selenium/support/AbstractFindByBuilder.java (L25-121)
Signature
public class PageFactory {
// Create new instance and initialize fields
public static <T> T initElements(SearchContext searchContext, Class<T> pageClassToProxy);
// Initialize existing instance fields (most common usage)
public static void initElements(SearchContext searchContext, Object page);
// Initialize with custom locator factory
public static void initElements(ElementLocatorFactory factory, Object page);
// Initialize with custom decorator (most flexible)
public static void initElements(FieldDecorator decorator, Object page);
}
Import
import org.openqa.selenium.support.PageFactory;
I/O Contract
Inputs
| Name |
Type |
Required |
Description
|
| searchContext |
SearchContext |
Yes (overloads 1, 2) |
WebDriver or WebElement to scope element searches
|
| pageClassToProxy |
Class<T> |
Yes (overload 1) |
Page Object class to instantiate; must have a WebDriver constructor or no-arg constructor
|
| page |
Object |
Yes (overloads 2, 3, 4) |
Existing Page Object instance whose fields will be proxied
|
| factory |
ElementLocatorFactory |
Yes (overload 3) |
Custom element locator creation strategy
|
| decorator |
FieldDecorator |
Yes (overload 4) |
Custom field decoration strategy
|
Outputs
| Name |
Type |
Description
|
| pageObject |
T |
Initialized Page Object with proxied WebElement and List<WebElement> fields (overload 1 only; overloads 2-4 return void and modify the object in-place)
|
Exceptions
| Exception |
Condition
|
| RuntimeException |
Wrapping ReflectiveOperationException if class cannot be instantiated (overload 1)
|
| RuntimeException |
Wrapping IllegalAccessException if a field cannot be set
|
| IllegalArgumentException |
From AbstractFindByBuilder if annotation has conflicting locator strategies
|
Usage Examples
Class-Based Initialization
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.PageFactory;
// Create and initialize in one step
// Tries WebDriver constructor first, then no-arg constructor
LoginPage loginPage = PageFactory.initElements(driver, LoginPage.class);
loginPage.login("user", "pass");
Instance-Based Initialization
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class LoginPage {
private WebDriver driver;
@FindBy(id = "username")
private WebElement usernameField;
@FindBy(id = "password")
private WebElement passwordField;
@FindBy(css = "button[type='submit']")
private WebElement submitButton;
public LoginPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public void login(String user, String pass) {
usernameField.clear();
usernameField.sendKeys(user);
passwordField.clear();
passwordField.sendKeys(pass);
submitButton.click();
}
}
Superclass Field Initialization
// PageFactory walks the entire class hierarchy
public abstract class BasePage {
@FindBy(id = "nav-menu")
protected WebElement navigationMenu;
@FindBy(css = ".footer")
protected WebElement footer;
}
public class DashboardPage extends BasePage {
@FindBy(id = "dashboard-content")
private WebElement content;
public DashboardPage(WebDriver driver) {
// This initializes fields in both DashboardPage AND BasePage
PageFactory.initElements(driver, this);
}
}
Related Pages
Implements Principle
Page Connections
Double-click a node to navigate. Hold to expand connections.