Skip to content

WW-5768 Make struts.ui.theme and struts.ui.templateDir scopable per package - #2008

Merged
lukaszlenart merged 2 commits into
mainfrom
WW-5768-scopable-ui-theme
Oct 12, 2026
Merged

lukaszlenart merged 2 commits into
mainfrom
WW-5768-scopable-ui-theme

Conversation

@lukaszlenart

@lukaszlenart lukaszlenart commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Fixes 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:

<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 WW-5769 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

🤖 Generated with Claude Code

…able per package

A package can now override the default UI theme and template directory with
<scoped-constant>, and child packages inherit it through extends. Only the last
fallback in UIBean.getTheme()/getTemplateDir() changes: it asks the
ScopedConstantProvider, which returns the package override or the global
constant. The tag attribute, the enclosing form and the request/session/
application attributes keep their precedence.

setDefaultUITheme/setDefaultTemplateDir and their fields are no longer read and
are deprecated for removal. Components built without the container now need a
ScopedConstantProvider, the same way they already need a CspNonceReader; the
javatemplates tests set a stub.

The empty-registry validation test now loads only the bootstrap beans, because
StrutsDefaultConfigurationProvider registers the UI names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…elds

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
B Maintainability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@lukaszlenart
lukaszlenart merged commit 65a8f86 into main Oct 12, 2026
15 of 16 checks passed
@lukaszlenart
lukaszlenart deleted the WW-5768-scopable-ui-theme branch October 12, 2026 19:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant