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

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

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

   Fixes [WW-3784](https://issues.apache.org/jira/browse/WW-3784)
   
   ## Problem
   
   Wildcard action patterns are matched **first-match-wins, in insertion 
order** (`AbstractMatcher.match()` iterates `compiledPatterns` and breaks on 
the first hit). In XML you control precedence by physically ordering mappings 
(specific before general). Annotation-based configs (Convention plugin 
`@Action` wildcards) have **no ordering guarantee** — registration order comes 
from `Set<Class<?>>` class-scan order, which is arbitrary and non-deterministic 
across JVMs/classloaders. So when two annotated wildcard patterns genuinely 
overlap, the general one can be evaluated first and shadow the specific one, 
leaving the specific action unreachable.
   
   ## Solution
   
   Order each Convention-built package's wildcard action patterns 
**most-specific-first**, so first-match-wins does the right thing — without 
touching XML or core matchers.
   
   - **`ActionNameSpecificityComparator`** (convention) — a 
`Comparator<String>` ranking action-name patterns by: (1) fewer wildcard 
tokens, (2) more literal characters, (3) fewer path-spanning `**` tokens, (4) 
natural order (deterministic tiebreak). Matcher-agnostic: recognises both 
`*`/`**` (`WildcardHelper`) and `{var}` (`NamedVariablePatternMatcher`).
   - **`PackageConfig.Builder.reorderActionConfigs(Comparator<String>)`** 
(core) — a neutral, generic helper that re-inserts the action-config 
`LinkedHashMap` in comparator order. Core does not depend on the plugin; XML 
providers never call it.
   - **`PackageBasedActionConfigBuilder`** — applies the comparator to every 
package in `buildConfiguration(...)`, after `buildIndexActions(...)` and before 
registration.
   
   **Scope:** annotation-sourced configs only. XML keeps its explicit 
file-order semantics untouched. No config flag — always on for Convention 
(safe, since the prior order was non-deterministic). A welcome side effect is 
that Convention action ordering is now **deterministic**.
   
   ## Known limitations (documented in the design spec)
   
   - Ordering is **per-package**. Convention places all actions of a namespace 
into one package, so the common case is covered; competing wildcards spread 
across different convention packages sharing a namespace remain in 
package-registration order.
   - The comparator's primary key (fewer wildcard tokens) can rank a broad `**` 
(one token) ahead of a narrower `*/*` (two tokens). Accepted as a known 
limitation and noted for a possible future refinement.
   
   ## Testing
   
   - `ActionNameSpecificityComparatorTest` — ranking rules incl. the ticket 
case, `*` vs `**`, `{var}`, literals, shuffle-invariance, and the alphabetical 
tiebreak.
   - `PackageConfigBuilderReorderTest` (core) — the reorder helper genuinely 
re-sorts by the supplied comparator.
   - `PackageBasedActionConfigBuilderReorderTest` — the wiring orders 
general-before-specific input into specific-first output.
   - Full suites green: `core` 3053/0, `plugins/convention` 51/0; apache-rat 
clean.
   
   Design and plan: `docs/superpowers/specs/2026-07-26-WW-3784-...-design.md`, 
`docs/superpowers/plans/2026-07-26-WW-3784-...md`.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   




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

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

> Greedy and non-greedy matching behaviour should work in action methods using 
> annotated wildcards 
> -------------------------------------------------------------------------------------------------
>
>                 Key: WW-3784
>                 URL: https://issues.apache.org/jira/browse/WW-3784
>             Project: Struts 2
>          Issue Type: Bug
>          Components: Core Actions
>    Affects Versions: 2.3.1.2
>         Environment: Win XP, Linux / JDK 7 (Oracle)
>            Reporter: Mo Be
>            Assignee: Lukasz Lenart
>            Priority: Major
>             Fix For: 7.3.0
>
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> {code:java}
> @Namespace("/do")
> public class CRUDAction {
>     /* [1] specific wildcard */
>     @Override @Action(value="some/usefull/{stuff}",results={@Result(location 
> = "result.jsp")})
>     public String execute() throws Exception {...}
>     /* [2] less specific wildcard */
>     @Override @Action(value="some/{stuff}", results={@Result(location 
> ="result.jsp")})
>     public String input() throws Exception {...} 
> }
> {code}
> Currently pattern [2] due to greedy natching catches every 
> "/do/some/\{stuff}" AND "/do/some/usefull/\{stuff}" event.
> For instance while calling /do/some/eating or /do/some/usefull/sleeping will 
> both end in [2] where stuff becomes "eating" or "usefull/sleep" respectively, 
> [1] is left behind with nothing to do.
> The expected matching behaviour should always be from more specific to less 
> specific.
> I.e. [2] should never fire before [1]. So that /do/some/usefull/sleeping 
> would correctly map to [1] with stuff==sleeping and /do/some/eating correctly 
> maps to [2] with stuff==eating.
> Using xml one can achieve the correct matching order by re-ordering the 
> action definitions (most specific action mapping comes first) 
>    



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

Reply via email to