[ 
https://issues.apache.org/jira/browse/WW-3530?focusedWorklogId=1032154&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1032154
 ]

ASF GitHub Bot logged work on WW-3530:
--------------------------------------

                Author: ASF GitHub Bot
            Created on: 25/Jul/26 10:08
            Start Date: 25/Jul/26 10:08
    Worklog Time Spent: 10m 
      Work Description: lukaszlenart opened a new pull request, #1811:
URL: https://github.com/apache/struts/pull/1811

   Fixes [WW-3530](https://issues.apache.org/jira/browse/WW-3530)
   
   ## Problem
   
   Two visitor field validators declared on the same field with different 
`context`
   params (e.g. `basic` and `additional`) collide in the validator cache under
   **wildcard / named-pattern actions**: both produce the same cache key, so the
   first context's validators are returned for both and the second context's
   validators are silently dropped.
   
   Originally reported in 2010 (v2.2.1) when the cache key omitted `context`
   entirely. WW-2996 / WW-3753 / WW-4536 later reworked the key so `context` is
   included for normal actions — fixing the report for non-wildcard actions. The
   defect still reproduces for wildcard actions, where the key intentionally
   substitutes the action config name for `context`.
   
   ## Root cause
   
   `AnnotationActionValidatorManager.buildValidatorKey` substitutes the action's
   config name + method for `context` whenever the **current action** is a
   wildcard/named-pattern action. That substitution is designed for the action's
   own class (where `context` is the volatile URL-derived action name that 
WW-2996
   must not key on). But it was applied too broadly — it also fired when 
validating
   a **visited object** under a visitor validator, whose `context` is a stable,
   explicit param, and wrongly discarded it.
   
   ## Fix
   
   Narrow the substitution to the case it was designed for: apply the 
config-name
   key only when the class being validated is the action's own class
   (`clazz.equals(invocation.getAction().getClass())`). For any other class (a
   visited object), key on `context` — matching `DefaultActionValidatorManager`.
   
   The request-validation hot path (`ValidationInterceptor` →
   `getValidators(action.getClass(), …)`) always validates the live action
   instance's own class, so WW-2996's single-cache-entry-per-wildcard-action
   behavior is fully preserved. The cache-key change only affects cache 
*reuse*; it
   never changes *which* validators load (`buildValidatorConfigs` receives 
`context`
   directly).
   
   ## Tests
   
   - New unit tests in `AnnotationActionValidatorManagerTest`:
     - visited class under a wildcard action → distinct keys per context (the
       failing-before / passing-after case)
     - action's own class under a wildcard action → key ignores context (WW-2996
       behavior pinned)
   - Regression: full `AnnotationActionValidatorManagerTest` (14/14) and
     `VisitorFieldValidatorTest` / `VisitorFieldValidatorModelTest` /
     `DefaultActionValidatorManagerTest` (23/23) pass.
   - **Draft note:** the full `core` module suite has not yet been run in this
     branch — to be completed before marking ready for review.
   
   ## Known limitations (follow-up ticket to be filed)
   
   Both need an explicit visitor signal threaded through the manager API to fix
   cleanly, and are memory-only (correct validators still load):
   
   - **Default-context visitor under a wildcard action:** a visitor validator 
with
     no explicit `context` defaults to the resolved action name, which is 
volatile
     under a wildcard action — so the visited-class key moves from stable
     (`configName|method`) to volatile, causing bounded WW-2996-style cache 
growth.
     Disappears when the visitor declares an explicit `context`.
   - **`<s:form>` client-side JS-validation render path:** resolves the action
     class by name rather than from the live action instance, so for a
     cross-action or proxied form the action's own top-level lookup falls to the
     `context` branch under a wildcard action (extra cache entries, correctness
     unaffected).
   
   Design spec and implementation plan are included under `docs/superpowers/`.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   




Issue Time Tracking
-------------------

            Worklog Id:     (was: 1032154)
    Remaining Estimate: 0h
            Time Spent: 10m

> Invalid cache key in AnnotationActionValidationManager.buildValidatorKey  
> when using visitor field validators
> -------------------------------------------------------------------------------------------------------------
>
>                 Key: WW-3530
>                 URL: https://issues.apache.org/jira/browse/WW-3530
>             Project: Struts 2
>          Issue Type: Bug
>          Components: XML Validators
>    Affects Versions: 2.2.1
>            Reporter: Johnny Yu
>            Assignee: Lukasz Lenart
>            Priority: Major
>             Fix For: 7.3.0
>
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> Error scenerio:
> MyAction-validation.xml:
> <validators>
>       <field name="myField"> <!-- MyClass -->
>               <field-validator type="visitor">
>                       <param name="context">basic</param>
>                       <param name="appendPrefix">true</param>
>                       <message/>
>               </field-validator>
>       </field>
>       <field name="myField">
>               <field-validator type="visitor">
>                       <param name="context">additional</param>
>                       <param name="appendPrefix">true</param>
>                       <message/>
>               </field-validator>
>       </field>
> </validators>
> In this case, validators in MyClass-basic-validation.xml will be executed two 
> times, but validators in MyClass-additional-validation.xml will just ignored.
> The problem is caused by 
> AnnotationActionValidationManager.buildValidatorKey(Class) which returns the 
> same cache key for the validator cache.
> The current cache key is created by:
> StringBuilder sb = new StringBuilder(clazz.getName());
> sb.append("/");
> sb.append(proxy.getConfig().getName());
> sb.append("|");
> sb.append(proxy.getMethod());
> The context is not a part of the cache key. Therefore, the two visitor 
> validator will just get the same cache key. 



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to