Skip to content

WW-3476 docs: document package-scoped constants - #351

Merged
lukaszlenart merged 3 commits into
mainfrom
WW-3476-scoped-constants
Oct 11, 2026
Merged

lukaszlenart merged 3 commits into
mainfrom
WW-3476-scoped-constants

Conversation

@lukaszlenart

@lukaszlenart lukaszlenart commented Oct 11, 2026 •

Copy link
Copy Markdown
Member

Refers to WW-3476 and apache/struts#2005 (merged, fix version 7.5.0)

Documents the <scoped-constant> element added in 7.5.0, which lets a package override selected constants for its own actions. Packages that extends it inherit the override.

  • core-developers/package-configuration.md: a new "Scoped constants" section. It covers the element and its DTD, inheritance, the startup errors (a name nothing has declared scopable, or a duplicate name), and the lack of ${...} substitution. A "Making a constant scopable" part is for component authors: register a ScopableConstants bean and read values through ScopedConstantProvider. It also covers which constants can never be scoped (PrefixBasedActionMapper handles per-URL mappers) and warns against making security switches scopable.
  • core-developers/constant-configuration.md: a link to the new section.
  • plugins/plugins-architecture.md: a struts.scopedConstantProvider row in the Extension Points table.
  • dtds/struts-7.5.dtd: copied from apache/struts main. Publishing it is the follow-up listed in WW-3476 Add package-scoped constants struts#2005.
  • dtds/struts-6.5.dtd: this file was never published, so https://struts.apache.org/dtds/struts-6.5.dtd, the system id in the 6.5 DOCTYPE, returns 404. The copy is from apache/struts main and is identical to the STRUTS_6_12_0 tag.

The section states that Struts core does not declare any constant as scopable yet, as of apache/struts#2005. If a scopable constant (UI theme, i18n, Convention result path) lands before 7.5.0, that warning needs updating.

Verified with a local jekyll build: the new anchors resolve, both alerts render, and both DTDs are published under _site/dtds/.

🤖 Generated with Claude Code

lukaszlenart and others added 2 commits October 11, 2026 10:20
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@lukaszlenart lukaszlenart left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked against apache/struts main (WW-3476, merged as fd60b2073):

  • dtds/struts-7.5.dtd and dtds/struts-6.5.dtd are byte-identical to core/src/main/resources/ on main; 6.5 also matches the STRUTS_6_12_0 tag. https://struts.apache.org/dtds/struts-6.5.dtd currently returns 404, so publishing it fixes a real gap.
  • These behaviour claims match the code:
    • the child package's override wins;
    • <scoped-constant> must come first in <package>;
    • abstract packages are validated, and the error lists the scopable names;
    • a duplicate name fails;
    • getValue falls back to the global value, returns null when that is unset, and throws IllegalArgumentException for a name that is not scopable;
    • the injected global value is never changed.
  • The note that ${...} is not substituted is accurate for the current code (XmlDocConfigurationProvider.loadScopedConstants stores the raw attribute).
  • The anchors action-mapper#prefixbasedactionmapper, constant-configuration#value-substitution and plugins-architecture#extension-points all resolve.
  • The extension-point row has the right property, scope and interface.

A few suggestions are inline. Nothing blocks the PR.

```java
private ScopedConstantProvider scopedConstantProvider;

@Inject

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest showing the imports here, at least import org.apache.struts2.inject.Inject;. Readers tend to reach for jakarta.inject.Inject / javax.inject.Inject, which the Struts container ignores, so the setter would silently never be called. Adding the ScopableConstants / ScopedConstantProvider imports to the two snippets would help too.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 1d215b5. Both snippets now show their imports, including org.apache.struts2.inject.Inject. An info note under the snippets explains that the container ignores jakarta.inject.Inject / javax.inject.Inject.

## Scoped constants

Since Struts 7.5.0 a package can override selected [constants](constant-configuration) for its own actions with
the `<scoped-constant>` element. Packages that `extends` it inherit the override, and an override declared in

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two small additions could go here:

  • With several parents (extends="a,b"), the first listed parent wins on a conflict, the same rule as result types.
  • Packages built by the Convention plugin get overrides only by inheriting them from their XML parent package (@ParentPackage).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 1d215b5. Both points are added. I checked the first-parent rule against the code: PackageConfig.Builder.addParent inserts at index 0, so the first package in extends is merged last and wins. For Convention I also mentioned struts.convention.default.parent.package, since it is the fallback when @ParentPackage is missing.

The error message lists the scopable constants that are available.
- a package declares the same constant more than once.

Values are used as they are. Unlike in `<constant>`, `${...}` [value substitution](constant-configuration#value-substitution)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accurate for the current code. Filed WW-5767 to apply the same load-time value substitution as <constant> (environment variables and system properties). That is not the per-request evaluation WW-3476 ruled out. If it lands before 7.5.0, this sentence goes away.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving this as is for now. If WW-5767 lands before 7.5.0, the sentence will be replaced with a link to value substitution.

`struts.enable.DynamicMethodInvocation` or `struts.devMode`. Otherwise a single package can relax a setting
meant to protect the whole application.

The default `ScopedConstantProvider` implementation can be replaced with the `struts.scopedConstantProvider`

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This currently holds for XML and properties configuration only. Java-based configuration cannot set struts.scopedConstantProvider yet, because ConstantConfig has no mapping for it (WW-5766, 7.5.0). Either add a short note, or update this when WW-5766 ships.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 1d215b5. Added a note that the provider can be replaced only from XML or properties configuration for now. It will be removed when WW-5766 ships.

@lukaszlenart
lukaszlenart marked this pull request as ready for review October 11, 2026 08:26
@asf-ci

asf-ci commented Oct 11, 2026

Copy link
Copy Markdown

Staged site is ready at https://struts.staged.apache.org/

1 similar comment
@asf-ci

asf-ci commented Oct 11, 2026

Copy link
Copy Markdown

Staged site is ready at https://struts.staged.apache.org/

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

asf-ci commented Oct 11, 2026

Copy link
Copy Markdown

Staged site is ready at https://struts.staged.apache.org/

@lukaszlenart
lukaszlenart merged commit 31a0006 into main Oct 11, 2026
1 check passed
@lukaszlenart
lukaszlenart deleted the WW-3476-scoped-constants branch October 11, 2026 14:24
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.

2 participants