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

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

                Author: ASF GitHub Bot
            Created on: 11/Oct/26 08:29
            Start Date: 11/Oct/26 08:29
    Worklog Time Spent: 10m 
      Work Description: lukaszlenart commented on code in PR #351:
URL: https://github.com/apache/struts-site/pull/351#discussion_r4240877003


##########
source/core-developers/package-configuration.md:
##########
@@ -80,3 +80,100 @@ The optional `abstract` attribute creates a base package 
that can omit the actio
   </package>
 </struts>
 ```
+
+## 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
+the child package wins.
+
+The element requires the [struts-7.5.dtd](../dtds/struts-7.5.dtd) and must 
come before any other child of
+`<package>`:
+
+```xml
+<!DOCTYPE struts PUBLIC
+    "-//Apache Software Foundation//DTD Struts Configuration 7.5//EN"
+    "https://struts.apache.org/dtds/struts-7.5.dtd";>
+<struts>
+  <package name="admin" extends="struts-default" namespace="/admin">
+    <scoped-constant name="some.scopable.constant" value="x"/>
+    ...
+  </package>
+</struts>
+```
+
+| Attribute | Required | Description                               |
+|-----------|----------|-------------------------------------------|
+| name      | **yes**  | the name of a scopable constant           |
+| value     | **yes**  | the value used for actions of the package |
+
+Scoped constants are not a way to override an arbitrary constant per package. 
Constants are injected into
+framework components once, at startup, so a package value only takes effect 
where a component explicitly reads
+it per request. Such a component declares the constants it reads as 
_scopable_, and only those can appear
+in `<scoped-constant>`.
+
+{:.alert .alert-warning}
+Struts core does not declare any constant as scopable yet. A 
`<scoped-constant>` only works with a constant
+declared scopable by a plugin or by your own application code.
+
+The configuration is validated at startup, and loading fails when:
+
+- a package declares a constant that nothing has declared scopable. This also 
applies to abstract packages.
+  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)
+is not supported.
+
+### Making a constant scopable
+
+A component makes a constant scopable in two steps. First, register a bean 
that implements
+`org.apache.struts2.config.ScopableConstants` and returns the constant names. 
You can register more than one
+such bean. The scopable set is the union of all of them.
+
+```java
+public class MyScopableConstants implements ScopableConstants {
+    @Override
+    public Set<String> getNames() {
+        return Set.of("myplugin.theme");
+    }
+}
+```
+
+```xml
+<bean type="org.apache.struts2.config.ScopableConstants" name="myplugin"
+      class="com.example.MyScopableConstants"/>
+```
+
+Second, read the value per request through 
`org.apache.struts2.config.ScopedConstantProvider`, not through
+an `@Inject`-ed constant:
+
+```java
+private ScopedConstantProvider scopedConstantProvider;
+
+@Inject

Review Comment:
   Done in 1d215b5e7. 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`.



##########
source/core-developers/package-configuration.md:
##########
@@ -80,3 +80,100 @@ The optional `abstract` attribute creates a base package 
that can omit the actio
   </package>
 </struts>
 ```
+
+## 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

Review Comment:
   Done in 1d215b5e7. 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.



##########
source/core-developers/package-configuration.md:
##########
@@ -80,3 +80,100 @@ The optional `abstract` attribute creates a base package 
that can omit the actio
   </package>
 </struts>
 ```
+
+## 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
+the child package wins.
+
+The element requires the [struts-7.5.dtd](../dtds/struts-7.5.dtd) and must 
come before any other child of
+`<package>`:
+
+```xml
+<!DOCTYPE struts PUBLIC
+    "-//Apache Software Foundation//DTD Struts Configuration 7.5//EN"
+    "https://struts.apache.org/dtds/struts-7.5.dtd";>
+<struts>
+  <package name="admin" extends="struts-default" namespace="/admin">
+    <scoped-constant name="some.scopable.constant" value="x"/>
+    ...
+  </package>
+</struts>
+```
+
+| Attribute | Required | Description                               |
+|-----------|----------|-------------------------------------------|
+| name      | **yes**  | the name of a scopable constant           |
+| value     | **yes**  | the value used for actions of the package |
+
+Scoped constants are not a way to override an arbitrary constant per package. 
Constants are injected into
+framework components once, at startup, so a package value only takes effect 
where a component explicitly reads
+it per request. Such a component declares the constants it reads as 
_scopable_, and only those can appear
+in `<scoped-constant>`.
+
+{:.alert .alert-warning}
+Struts core does not declare any constant as scopable yet. A 
`<scoped-constant>` only works with a constant
+declared scopable by a plugin or by your own application code.
+
+The configuration is validated at startup, and loading fails when:
+
+- a package declares a constant that nothing has declared scopable. This also 
applies to abstract packages.
+  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)

Review Comment:
   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.



##########
source/core-developers/package-configuration.md:
##########
@@ -80,3 +80,100 @@ The optional `abstract` attribute creates a base package 
that can omit the actio
   </package>
 </struts>
 ```
+
+## 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
+the child package wins.
+
+The element requires the [struts-7.5.dtd](../dtds/struts-7.5.dtd) and must 
come before any other child of
+`<package>`:
+
+```xml
+<!DOCTYPE struts PUBLIC
+    "-//Apache Software Foundation//DTD Struts Configuration 7.5//EN"
+    "https://struts.apache.org/dtds/struts-7.5.dtd";>
+<struts>
+  <package name="admin" extends="struts-default" namespace="/admin">
+    <scoped-constant name="some.scopable.constant" value="x"/>
+    ...
+  </package>
+</struts>
+```
+
+| Attribute | Required | Description                               |
+|-----------|----------|-------------------------------------------|
+| name      | **yes**  | the name of a scopable constant           |
+| value     | **yes**  | the value used for actions of the package |
+
+Scoped constants are not a way to override an arbitrary constant per package. 
Constants are injected into
+framework components once, at startup, so a package value only takes effect 
where a component explicitly reads
+it per request. Such a component declares the constants it reads as 
_scopable_, and only those can appear
+in `<scoped-constant>`.
+
+{:.alert .alert-warning}
+Struts core does not declare any constant as scopable yet. A 
`<scoped-constant>` only works with a constant
+declared scopable by a plugin or by your own application code.
+
+The configuration is validated at startup, and loading fails when:
+
+- a package declares a constant that nothing has declared scopable. This also 
applies to abstract packages.
+  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)
+is not supported.
+
+### Making a constant scopable
+
+A component makes a constant scopable in two steps. First, register a bean 
that implements
+`org.apache.struts2.config.ScopableConstants` and returns the constant names. 
You can register more than one
+such bean. The scopable set is the union of all of them.
+
+```java
+public class MyScopableConstants implements ScopableConstants {
+    @Override
+    public Set<String> getNames() {
+        return Set.of("myplugin.theme");
+    }
+}
+```
+
+```xml
+<bean type="org.apache.struts2.config.ScopableConstants" name="myplugin"
+      class="com.example.MyScopableConstants"/>
+```
+
+Second, read the value per request through 
`org.apache.struts2.config.ScopedConstantProvider`, not through
+an `@Inject`-ed constant:
+
+```java
+private ScopedConstantProvider scopedConstantProvider;
+
+@Inject
+public void setScopedConstantProvider(ScopedConstantProvider 
scopedConstantProvider) {
+    this.scopedConstantProvider = scopedConstantProvider;
+}
+
+public String getTheme() {
+    return scopedConstantProvider.getValue("myplugin.theme");
+}
+```
+
+`getValue(name)` returns the value for the package of the action being 
executed, taking `extends` into account.
+Outside an action invocation, or when no package in the hierarchy overrides 
the constant, it returns the global
+constant, or `null` when that is not set. It throws `IllegalArgumentException` 
for a name that is not scopable.
+The global value injected elsewhere is never changed.
+
+Some constants can never be scoped, because they are read before the package 
of a request is known, for
+example the [ActionMapper](action-mapper) or the multipart upload limits. To 
use a different mapper per URL space,
+use the [PrefixBasedActionMapper](action-mapper#prefixbasedactionmapper) 
instead.
+
+{:.alert .alert-danger}
+Do not declare security-related constants scopable, such as 
`struts.parameters.requireAnnotations`,
+`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`

Review Comment:
   Done in 1d215b5e7. 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.





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

    Worklog Id:     (was: 1046852)
    Time Spent: 3h 20m  (was: 3h 10m)

> Allow overwriting of constants for each package
> -----------------------------------------------
>
>                 Key: WW-3476
>                 URL: https://issues.apache.org/jira/browse/WW-3476
>             Project: Struts 2
>          Issue Type: New Feature
>          Components: XML Configuration
>    Affects Versions: 2.2.1
>            Reporter: Johannes Geppert
>            Assignee: Lukasz Lenart
>            Priority: Major
>             Fix For: 7.5.0
>
>          Time Spent: 3h 20m
>  Remaining Estimate: 0h
>
> Allow to overwriting of constants for each package.
> So I can specify as example for each package an other ActionMapper, Local or 
> other location for the JSP Files.



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

Reply via email to