Skip to content

WW-5716 Bound the per-locale definition caches in the Tiles plugin - #1902

Open
lukaszlenart wants to merge 1 commit into
mainfrom
WW-5716
Open

WW-5716 Bound the per-locale definition caches in the Tiles plugin#1902
lukaszlenart wants to merge 1 commit into
mainfrom
WW-5716

Conversation

@lukaszlenart

Copy link
Copy Markdown
Member

The Tiles definition caches are keyed by the resolved Locale, which by default derives from the request. Two maps grew without limit and were never reduced for the lifetime of the web application:

  • CachingLocaleUrlDefinitionDAO#locale2definitionMap — populated on each cache miss, only cleared under the (default-off) checkRefresh path.
  • AbstractPatternDefinitionResolver#localePatternPaths — populated via computeIfAbsent per locale key, never swept.

The TilesContainer holding the DAO lives in application scope, so both maps persisted for the application lifetime, and the number of distinct keys was bounded only by the number of distinct locales encountered.

Change

  • Bound locale2definitionMap with an insertion-order LinkedHashMap capped at maxCachedLocales (default 1000, configurable via setMaxCachedLocales). Insertion-order (not access-order) keeps the existing unsynchronized getDefinitions read unchanged.
  • On eviction the DAO removes the same key from the pattern resolver through the new PatternDefinitionResolver#removePatternPaths, keeping both maps in lockstep — the resolver's keys are always a subset of the DAO's, since a pattern-paths entry is stored right before every locale2definitionMap put.
  • localePatternPaths becomes a ConcurrentHashMap, as the DAO now removes keys off the request thread.

Eviction only re-incurs a load on next access; it never changes rendering. Both concrete resolvers (BasicPatternDefinitionResolver, PrefixedPatternDefinitionResolver) inherit the new behaviour from AbstractPatternDefinitionResolver.

Tests cover the bound and that both maps evict together; the full struts2-tiles-plugin module suite passes (547 tests).

Fixes WW-5716

🤖 Generated with Claude Code

The Tiles definition caches are keyed by the resolved Locale, which by
default derives from the request. Both CachingLocaleUrlDefinitionDAO's
locale2definitionMap and AbstractPatternDefinitionResolver's
localePatternPaths grew without limit and were never reduced for the
lifetime of the web application.

Bound locale2definitionMap with an insertion-order LinkedHashMap capped
at maxCachedLocales (default 1000, configurable via setMaxCachedLocales).
On eviction the DAO removes the same key from the pattern resolver via
the new PatternDefinitionResolver#removePatternPaths, keeping both maps
in lockstep (the resolver's keys are always a subset of the DAO's).
localePatternPaths becomes a ConcurrentHashMap since the DAO now removes
keys off the request thread. Eviction only re-incurs a load, never
changes rendering.

Fixes https://issues.apache.org/jira/browse/WW-5716

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015huuB72yvZygWEXKUYDAou
@sonarqubecloud

sonarqubecloud Bot commented Sep 4, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant