lukaszlenart opened a new pull request, #1808:
URL: https://github.com/apache/struts/pull/1808

   Fixes [WW-5540](https://issues.apache.org/jira/browse/WW-5540)
   
   ## What
   
   Caches the class- and package-hierarchy traversal performed by
   `StrutsLocalizedTextProvider.findText(Class, …)`, so repeated lookups for 
the same
   `(classloader, class name, key, locale)` collapse to a single 
`ConcurrentHashMap`
   lookup instead of re-walking the class → interface → superclass → `*.package`
   hierarchy on every call. This path backs every UI tag label and validation 
message
   rendered per request; missing keys were especially costly (full hierarchy 
walk +
   swallowed `MissingResourceException` per level, repeated every request).
   
   ## How
   
   - **Raw / format split** — resolution of the raw message pattern is 
separated from
     rendering. Only the **raw pattern** (or a `NOT_FOUND` identity sentinel) 
is cached;
     OGNL `translateVariables` and `MessageFormat` argument substitution still 
run **per
     call**, so dynamic `${…}` messages and per-call args remain correct.
   - **Two caches** in `AbstractLocalizedTextProvider` (`classHierarchyCache`,
     `packageHierarchyCache`), keyed on the classloader hash + **class name 
(String)** —
     never a `Class` object, so no classloader pinning.
   - **Invalidation** wired into `reloadBundles`, `clearBundle`, and
     `clearMissingBundlesCache`; the reload check is hoisted to the top of 
`findText` so
     devMode/`struts.i18n.reload=true` clears the caches before they are read.
   - `getMessage` / `findMessage` are retained as `@Deprecated` delegators for
     descendant classes.
   
   ## Behavior
   
   Behavior-preserving: lookup order, dynamic-message evaluation, argument 
formatting,
   and devMode/reload semantics are unchanged. The one documented, accepted 
divergence is
   a pathological case where the same key is redefined at multiple levels of a 
single class
   hierarchy and the shallowest match formats to the literal string `"null"`. 
Caches are
   unbounded, consistent with the existing `bundlesMap` / `missingBundles`. See 
the design
   spec under `docs/superpowers/specs/` for details.
   
   ## Testing
   
   `mvn test -DskipAssembly -pl core -Dtest=StrutsLocalizedTextProviderTest` → 
33/33 green
   (11 new tests covering raw-only caching, per-call formatting/OGNL, miss 
caching, the
   null-format fall-through, and cache invalidation at all three clear sites). 
Broader
   localized-text slice: 54/54 green.
   
   ## Follow-up
   
   A separate, deferred cleanup (replacing the `null`-overloaded control flow 
with an
   explicit result type) is drafted under `docs/superpowers/followups/` and not 
yet filed.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to