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.

Implementation:SeleniumHQ Selenium CacheLookup Annotation

From Leeroopedia
Revision as of 11:49, 16 February 2026 by Admin (talk | contribs) (Auto-imported from implementations/SeleniumHQ_Selenium_CacheLookup_Annotation.md)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Knowledge Sources
Domains Test_Design, Performance, Browser_Automation
Last Updated 2026-02-11 00:00 GMT

Overview

Concrete tool for enabling element caching on PageFactory-managed WebElement fields provided by the Selenium Support library.

Description

@CacheLookup is a marker annotation (no parameters) applied to WebElement or List<WebElement> fields alongside @FindBy. It is retained at runtime (@Retention(RetentionPolicy.RUNTIME)) and targets fields only (@Target(ElementType.FIELD)). When DefaultElementLocatorFactory creates a DefaultElementLocator for a field, the Annotations helper class checks for the presence of @CacheLookup via field.isAnnotationPresent(CacheLookup.class) and sets the shouldCache flag accordingly. The DefaultElementLocator then stores resolved elements in its cachedElement or cachedElementList instance variables after the first successful lookup.

Usage

Add @CacheLookup to @FindBy-annotated fields for static elements that do not change after page load. Omit it for dynamic elements that may be added, removed, or replaced in the DOM.

Code Reference

Source Location

  • Repository: Selenium
  • File: java/src/org/openqa/selenium/support/CacheLookup.java (L29-31)
  • File: java/src/org/openqa/selenium/support/pagefactory/DefaultElementLocator.java (L32-104)

Signature

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CacheLookup {
    // Marker annotation -- no elements
}

The caching is implemented in DefaultElementLocator:

public class DefaultElementLocator implements ElementLocator {
    private final SearchContext searchContext;
    private final boolean shouldCache;
    private final By by;
    private WebElement cachedElement;
    private List<WebElement> cachedElementList;

    public DefaultElementLocator(SearchContext searchContext, Field field) {
        this(searchContext, new Annotations(field));
    }

    public DefaultElementLocator(SearchContext searchContext, AbstractAnnotations annotations) {
        this.searchContext = searchContext;
        this.shouldCache = annotations.isLookupCached();
        this.by = annotations.buildBy();
    }

    @Override
    public WebElement findElement() {
        if (cachedElement != null && shouldCache()) {
            return cachedElement;
        }
        WebElement element = searchContext.findElement(by);
        if (shouldCache()) {
            cachedElement = element;
        }
        return element;
    }

    @Override
    public List<WebElement> findElements() {
        if (cachedElementList != null && shouldCache()) {
            return cachedElementList;
        }
        List<WebElement> elements = searchContext.findElements(by);
        if (shouldCache()) {
            cachedElementList = elements;
        }
        return elements;
    }

    protected boolean shouldCache() {
        return shouldCache;
    }
}

Import

import org.openqa.selenium.support.CacheLookup;

I/O Contract

Inputs

Name Type Required Description
(none) - - Marker annotation with no parameters

Outputs

Name Type Description
cached proxy behavior WebElement proxy Proxy backed by DefaultElementLocator that caches the resolved element after first lookup; subsequent calls return the cached reference without querying the DOM

Usage Examples

Static vs Dynamic Elements

import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.CacheLookup;
import org.openqa.selenium.support.PageFactory;

public class HomePage {
    private WebDriver driver;

    // Static element -- safe to cache; never changes after page load
    @FindBy(id = "main-nav")
    @CacheLookup
    private WebElement navigation;

    // Static element -- safe to cache
    @FindBy(css = "header h1")
    @CacheLookup
    private WebElement pageTitle;

    // Dynamic element -- do NOT cache; appears after AJAX call
    @FindBy(css = ".notification-badge")
    private WebElement notificationBadge;

    // Dynamic element -- do NOT cache; content updates via JavaScript
    @FindBy(id = "live-feed")
    private WebElement liveFeed;

    public HomePage(WebDriver driver) {
        this.driver = driver;
        PageFactory.initElements(driver, this);
    }

    public String getPageTitle() {
        return pageTitle.getText();  // Uses cached element reference
    }

    public String getNotificationCount() {
        return notificationBadge.getText();  // Re-queries DOM every call
    }
}

Caching with List<WebElement>

import java.util.List;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.CacheLookup;

public class NavigationPage {
    // Static list -- the nav links are always present
    @FindBy(css = "#main-nav a")
    @CacheLookup
    private List<WebElement> navLinks;

    public int getNavLinkCount() {
        return navLinks.size();  // Uses cached list after first access
    }
}

Related Pages

Implements Principle

Page Connections

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