Lukasz Lenart created WW-5768:
---------------------------------
Summary: 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
Fix For: 7.5.0
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)