Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Principle:SeleniumHQ Selenium PageFactory Initialization

From Leeroopedia
Knowledge Sources
Domains Test_Design, Design_Patterns, Reflection
Last Updated 2026-02-11 00:00 GMT

Overview

Runtime mechanism for scanning Page Object class fields, converting locator annotations to By objects, and replacing fields with lazy-loading WebElement proxies.

Description

PageFactory initialization is the bridge between declarative annotations and executable element lookups. When PageFactory.initElements() is called, it uses Java reflection to scan all declared fields of the Page Object class and its entire superclass hierarchy up to Object.class. For each field, DefaultFieldDecorator checks whether the field type is assignable to WebElement or is a List<WebElement> with a @FindBy, @FindAll, or @FindBys annotation. If so, it creates an ElementLocator via DefaultElementLocatorFactory, then uses LocatingElementHandler or LocatingElementListHandler to create a JDK dynamic proxy (via java.lang.reflect.Proxy) that intercepts method calls and performs the actual DOM lookup lazily.

Usage

Call PageFactory.initElements(driver, pageObject) immediately after creating a Page Object instance, typically in the constructor. The static factory method PageFactory.initElements(driver, PageClass.class) can create and initialize in one step -- it first attempts to find a constructor taking WebDriver, then falls back to a no-arg constructor. A third overload accepts an ElementLocatorFactory for custom locator strategies, and a fourth accepts a FieldDecorator for fully custom field decoration.

Theoretical Basis

# Pseudocode: PageFactory.initElements(FieldDecorator, Object)
1. proxyIn = page.getClass()
2. While proxyIn != Object.class:
   a. fields = proxyIn.getDeclaredFields()
   b. For each field in fields:
      i.   value = decorator.decorate(classLoader, field)
      ii.  If value != null:
           - field.setAccessible(true)
           - field.set(page, value)
   c. proxyIn = proxyIn.getSuperclass()

The DefaultFieldDecorator.decorate() method performs the following:

# DefaultFieldDecorator.decorate(classLoader, field)
1. If field type is not WebElement and not decoratable List -> return null
2. locator = factory.createLocator(field)   // DefaultElementLocator
3. If locator is null -> return null
4. If field type is WebElement:
   a. handler = new LocatingElementHandler(locator)
   b. return Proxy.newProxyInstance(loader, [WebElement, WrapsElement, Locatable], handler)
5. If field type is List:
   a. handler = new LocatingElementListHandler(locator)
   b. return Proxy.newProxyInstance(loader, [List], handler)

The instantiatePage() method for the class-based overload:

# PageFactory.instantiatePage(searchContext, pageClass)
1. Try: constructor = pageClass.getConstructor(WebDriver.class)
         return constructor.newInstance(searchContext)
2. Catch NoSuchMethodException:
         return pageClass.getDeclaredConstructor().newInstance()

Related Pages

Implemented By

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment