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

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

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

   Fixes [WW-5768](https://issues.apache.org/jira/browse/WW-5768)
   
   ## Summary
   
   This is the first adopter of package-scoped constants (WW-3476). A package 
can now override the default UI theme and template directory, and child 
packages inherit the override through `extends`:
   
   ```xml
   <package name="admin" extends="struts-default" namespace="/admin">
       <scoped-constant name="struts.ui.theme" value="css_xhtml"/>
       <scoped-constant name="struts.ui.templateDir" value="admin-template"/>
   </package>
   ```
   
   - `StrutsUiScopableConstants` registers the two names in `struts-beans.xml`, 
and in `StrutsDefaultConfigurationProvider` for the test harness.
   - `UIBean.getTheme()` / `getTemplateDir()` change only their last fallback 
step. It now calls `ScopedConstantProvider.getValue(...)`, which returns the 
package override or the global constant.
     - The tag attribute, the enclosing form (theme only) and the 
request/session/application attribute keep their precedence.
     - With no action invocation, for example a JSP rendered directly, the 
global constant is used, as before.
   
   ## Compatibility
   
   - `setDefaultUITheme` / `setDefaultTemplateDir` and the `defaultUITheme` / 
`defaultTemplateDir` fields are no longer injected or read. They are marked 
`@Deprecated(since = "7.5.0", forRemoval = true)`, and their removal is tracked 
in a separate ticket for 8.0.0.
   - `UIBean` now requires an injected `ScopedConstantProvider`, the same way 
it already requires a `CspNonceReader`. Components created by the container 
(JSP, FreeMarker and Velocity tags) are unaffected. Code that builds components 
by hand without `container.inject(...)` must set one: the javatemplates tests 
now call `setScopedConstantProvider(name -> null)` next to their existing 
`setCspNonceReader(...)`.
   - When no override exists, each `getTheme()` / `getTemplateDir()` call now 
performs a container lookup of the global constant instead of reading a field.
   - A `<scoped-constant>` with an empty value yields an empty theme. This 
matches the provider's existing contract (`testEmptyOverrideIsReturnedAsIs`).
   
   ## Tests
   
   - New `UIBeanScopedConstantsTest` loads `struts-default.xml` (and therefore 
`struts-beans.xml`). It covers:
     - the override is used when the tag sets no attribute;
     - a child package inherits the override;
     - the global value is used with no override and with no invocation;
     - the tag attribute, the form's theme and a request attribute each still 
win over the override.
   - A mutation that put the package value first in `getTheme()` made the form 
and request-attribute tests fail, so those tests do exercise the ordering.
   - `ScopedConstantsValidationTest`:
     - New: a `<scoped-constant name="struts.ui.theme">`, which was rejected 
before this change, now loads.
     - The "Scopable constants" message now lists the UI names.
     - The "no constants are scopable" case now loads only the bootstrap beans, 
because the default harness always registers the UI names.
   - `UIBeanTest` injects the provider or stubs it, instead of calling the 
deprecated setter.
   
   Results:
   - `core`: 3456 tests, 0 failures.
   - All plugin modules pass, including javatemplates (80), json (177) and 
tiles (565).
   - The showcase integration tests were not run.
   
   ## Follow-up
   
   - struts-site: list these two constants as scopable in 
`core-developers/package-configuration.md` (apache/struts-site#351), and 
mention the override on the themes and templates page.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   




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

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

> Make struts.ui.theme and struts.ui.templateDir scopable per package
> -------------------------------------------------------------------
>
>                 Key: WW-5768
>                 URL: https://issues.apache.org/jira/browse/WW-5768
>             Project: Struts 2
>          Issue Type: Improvement
>          Components: Core Tags
>            Reporter: Lukasz Lenart
>            Priority: Major
>             Fix For: 7.5.0
>
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> The first adopter of package-scoped constants 
> ([WW-3476|https://issues.apache.org/jira/browse/WW-3476]). That change 
> shipped the mechanism only, and no constant is scopable yet, so any 
> {{<scoped-constant>}} currently fails at startup.
> h2. Goal
> Allow a package to override the default UI theme and template directory:
> {code:xml}<package name="admin" extends="struts-default" namespace="/admin">
>     <scoped-constant name="struts.ui.theme" value="css_xhtml"/>
>     <scoped-constant name="struts.ui.templateDir" value="admin-template"/>
>     ...
> </package>
> {code}
> Child packages inherit the override through {{extends}}. Today the same 
> effect needs a {{theme}} attribute on every tag, or an interceptor that puts 
> {{theme}} into the request scope.
> h2. Why these two constants
> {{UIBean.getTheme()}} and {{UIBean.getTemplateDir()}} resolve their values 
> when a tag renders, inside the result, so the action invocation and its 
> package are known. The injected global value is only the last step of an 
> existing chain:
> # the tag attribute
> # the enclosing form (theme only)
> # the request / session / application {{theme}} / {{templateDir}} attribute
> # the injected {{defaultUITheme}} / {{defaultTemplateDir}}
> Only step 4 changes. Everything users rely on today keeps its precedence.
> h2. Proposed change
> * Register a {{ScopableConstants}} bean in {{struts-beans.xml}} (for example 
> {{StrutsUiScopableConstants}}) that returns {{struts.ui.theme}} and 
> {{struts.ui.templateDir}}.
> * Inject {{ScopedConstantProvider}} into {{UIBean}}, and in step 4 use 
> {{scopedConstantProvider.getValue(...)}} instead of the injected field. The 
> provider already falls back to the global constant when there is no 
> invocation (a JSP rendered without an action) or no override.
> * Register the bean in {{StrutsDefaultConfigurationProvider}} too, for the 
> test harness.
> h2. Tests
> * A package override is used when the tag has no {{theme}} / {{templateDir}}.
> * The tag attribute, the enclosing form's theme, and a request-scope 
> {{theme}} attribute still win over the override.
> * A child package inherits the parent's override.
> * With no invocation, or no override, the global constant is used.
> * The previously rejected {{<scoped-constant name="struts.ui.theme">}} now 
> loads, and an unrelated name is still rejected at startup.
> h2. Docs
> Update the struts-site page for scoped constants 
> ({{package-configuration.md}}, see struts-site PR #351) to list these two as 
> the scopable constants, and mention the override in the themes and templates 
> page.
> h2. Out of scope
> * {{struts.ui.theme.expansion.token}} and {{struts.ui.staticContentPath}}
> * {{struts.convention.result.path}}: it is read at startup by 
> {{DefaultResultMapBuilder}}, when there is no invocation, so it needs a 
> lookup by package name. That is a separate ticket.



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

Reply via email to