This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/struts-site.git


The following commit(s) were added to refs/heads/main by this push:
     new 807f7bd88 docs: document ModelDriven parameter binding and 
authorization (#319)
807f7bd88 is described below

commit 807f7bd8867831dca5b277cf8c7d487508a81a49
Author: Lukasz Lenart <[email protected]>
AuthorDate: Wed Jul 29 09:42:38 2026 +0200

    docs: document ModelDriven parameter binding and authorization (#319)
    
    * docs: document ModelDriven parameter binding and authorization
    
    An action implementing ModelDriven makes its model the target of
    @StrutsParameter authorization, so the model's members are bindable
    without the annotation. This holds on every input channel — request
    parameters, JSON bodies and REST bodies — since they all resolve the
    authorization target through the same authorizer.
    
    Document it on the @StrutsParameter page (canonical), with short notes
    and cross-links from the Model Driven Interceptor and REST plugin pages,
    plus guidance to shape a model as a request DTO rather than a domain or
    persistence entity.
    
    Co-Authored-By: Claude Opus 5 <[email protected]>
    
    * Adds ToC
    
    * docs: correct version attribution for ModelDriven exemption
    
    @StrutsParameter was introduced in 6.4.0; the ModelDriven exemption
    arrived separately in 7.0.0. The previous wording conflated the two and
    read as though the annotation itself were a 7.0.0 feature.
    
    Co-Authored-By: Claude Opus 5 <[email protected]>
    
    * docs: drop 6.x reference from ModelDriven authorization note
    
    @StrutsParameter enforcement is supported from Struts 7.0.0; 6.x is not
    a version the annotation's behavior should be characterised against.
    
    Co-Authored-By: Claude Opus 5 <[email protected]>
    
    * docs: add ModelDriven binding note to the Model Driven page
    
    The conceptual Model Driven page is the likelier landing spot for
    someone learning the feature, but said only that Struts populates the
    model's fields — with no mention that this lifts the @StrutsParameter
    requirement, and no DTO guidance. Adds the same short note and
    cross-link the other pages carry.
    
    Also corrects the interface's package: it is org.apache.struts2
    .ModelDriven in 7.x, not com.opensymphony.xwork2.ModelDriven.
    
    Co-Authored-By: Claude Opus 5 <[email protected]>
    
    ---------
    
    Co-authored-by: Claude Opus 5 <[email protected]>
---
 source/core-developers/logging-interceptor.md      |  4 +++
 .../core-developers/message-store-interceptor.md   |  4 +++
 source/core-developers/model-driven-interceptor.md | 10 +++++++
 source/core-developers/model-driven.md             | 12 +++++++-
 .../core-developers/struts-parameter-annotation.md | 35 ++++++++++++++++++++++
 source/plugins/rest/index.md                       |  7 +++++
 6 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/source/core-developers/logging-interceptor.md 
b/source/core-developers/logging-interceptor.md
index d551a72a0..9aa5d2937 100644
--- a/source/core-developers/logging-interceptor.md
+++ b/source/core-developers/logging-interceptor.md
@@ -7,6 +7,10 @@ parent:
 ---
 
 # Logging Interceptor
+{:.no_toc}
+
+* Will be replaced with the ToC, excluding a header
+{:toc}
 
 This interceptor logs the start and end of the execution an action (in 
English-only, not internationalized).
 
diff --git a/source/core-developers/message-store-interceptor.md 
b/source/core-developers/message-store-interceptor.md
index 7b4ba6ff8..6ee14adff 100644
--- a/source/core-developers/message-store-interceptor.md
+++ b/source/core-developers/message-store-interceptor.md
@@ -7,6 +7,10 @@ parent:
 ---
 
 # Message Store Interceptor
+{:.no_toc}
+
+* Will be replaced with the ToC, excluding a header
+{:toc}
 
 An interceptor to store a `ValidationAware` action's messages / errors and 
field errors into HTTP Session, such that it 
 will be retrievable at a later stage. This allows the action's message / 
errors and field errors to be available longer 
diff --git a/source/core-developers/model-driven-interceptor.md 
b/source/core-developers/model-driven-interceptor.md
index be88020a0..a2f309b0b 100644
--- a/source/core-developers/model-driven-interceptor.md
+++ b/source/core-developers/model-driven-interceptor.md
@@ -7,6 +7,10 @@ parent:
 ---
 
 # Model Driven Interceptor
+{:.no_toc}
+
+* Will be replaced with the ToC, excluding a header
+{:toc}
 
 Watches for `ModelDriven` actions and adds the action's model on to the value 
stack.
 
@@ -26,6 +30,12 @@ In the implementation of `getModel`, acquire an instance of 
a business object an
 On the page, you can address any JavaBean properties on the business object as 
if they were coded directly on the Action 
 class. The framework pushes the Model object onto the ValueStack.
 
+Pushing the model onto the stack also makes it the target of parameter binding 
and of `@StrutsParameter` authorization:
+the model's members are populated from the request without requiring the 
annotation, on every input channel. Shape the
+model as a request DTO holding only the fields the action intends to accept, 
not as a domain or persistence entity. See
+[StrutsParameter 
Annotation](struts-parameter-annotation.html#modeldriven-actions) for the full 
rules.
+{:.alert .alert-warning}
+
 Many developers use Spring to acquire the business object. With the addition 
of a `setModel` method, the business logic 
 can be injected automatically.
 
diff --git a/source/core-developers/model-driven.md 
b/source/core-developers/model-driven.md
index 01319e012..28fcf53bc 100644
--- a/source/core-developers/model-driven.md
+++ b/source/core-developers/model-driven.md
@@ -7,16 +7,26 @@ parent:
 ---
 
 # Model Driven
+{:.no_toc}
+
+* Will be replaced with the ToC, excluding a header
+{:toc}
 
 Struts 2 does not have "forms" like Struts 1 did. In Struts 2 request 
parameters are bound directly to fields 
 in the actions class, and this class is placed on top of the stack when the 
action is executed.
 
-If an action class implements the interface 
`com.opensymphony.xwork2.ModelDriven` then it needs to return an object 
+If an action class implements the interface `org.apache.struts2.ModelDriven` 
then it needs to return an object 
 from the `getModel()` method. Struts will then populate the fields of this 
object with the request parameters,
 and this object will be placed on top of the stack once the action is 
executed. Validation will also be performed
 on this model object, instead of the action. Please read about 
[VisitorFieldValidator Annotation](visitor-field-validator-annotation)
 which can help you validate model's fields.
 
+The model is also the target of `@StrutsParameter` authorization: its members 
are populated from the request without
+requiring the annotation, on every input channel. Shape the model as a request 
DTO holding only the fields the action
+intends to accept, not as a domain or persistence entity. See
+[StrutsParameter 
Annotation](struts-parameter-annotation.html#modeldriven-actions) for the full 
rules.
+{:.alert .alert-warning}
+
 ## Interceptor
 
 To use `ModelDriven` actions, make sure that the [Model Driven 
Interceptor](model-driven-interceptor) is applied 
diff --git a/source/core-developers/struts-parameter-annotation.md 
b/source/core-developers/struts-parameter-annotation.md
index 33d5dfdc6..97e3c37ff 100644
--- a/source/core-developers/struts-parameter-annotation.md
+++ b/source/core-developers/struts-parameter-annotation.md
@@ -29,6 +29,41 @@ channel that can populate an action from request data:
 - [JSON](../../plugins/json) and [REST](../../plugins/rest) plugins — 
per-property
   authorization performed during deserialization, so unauthorized fields are 
never set.
 
+## ModelDriven actions
+
+When an action implements `ModelDriven` and the [Model Driven
+Interceptor](model-driven-interceptor.html) has pushed the model onto the value
+stack, the **model** — not the action — is the authorization target, and the
+model's members are exempt from the annotation requirement. The whole model is
+bindable, including its nested properties, whether or not any of its fields or
+accessors carry `@StrutsParameter`.
+
+This follows from what the interface declares: returning an object from
+`getModel()` designates that object as the request surface. The model has
+been the authorization target since Struts 7.0.0.
+
+The exemption holds on **every** input channel listed above — request
+parameters, JSON bodies and REST bodies alike — because they all resolve the
+authorization target the same way. It is not a JSON- or REST-specific behavior.
+
+The exemption is narrowly scoped. It applies only when the action itself
+implements `ModelDriven` *and* the object being populated is its model rather
+than the action. A root object configured elsewhere — for example the JSON
+interceptor's `root` expression on an action that does not implement
+`ModelDriven` — is not exempt, and each member it binds still requires
+`@StrutsParameter`.
+
+The exemption lifts the annotation requirement only. The other parameter-name
+checks — accepted and excluded name patterns, and `ParameterNameAware` — still
+apply to a model's parameters as they do to an action's.
+
+Because the entire model is bindable, a `ModelDriven` model should be a request
+DTO carrying only the fields the action intends to accept from a request, never
+a domain or persistence entity. If you need member-level control over what is
+bindable, use action properties annotated with `@StrutsParameter` rather than
+`ModelDriven`.
+{:.alert .alert-warning}
+
 ## Usage
 
 The placement of the `@StrutsParameter` annotation is crucial and depends on 
how you want to populate your action properties.
diff --git a/source/plugins/rest/index.md b/source/plugins/rest/index.md
index 004d21c34..ba7790930 100644
--- a/source/plugins/rest/index.md
+++ b/source/plugins/rest/index.md
@@ -245,6 +245,13 @@ public class OrdersController implements 
ModelDriven<Order> {
 In this example, the `ModelDriven` interface is used to ensure that only my 
model, the Order object in this case, is 
 returned to the client, otherwise, the whole `OrdersController` object would 
be serialized.
 
+`ModelDriven` also determines what is bindable *from* the request body: the 
model is the target of `@StrutsParameter` 
+authorization, so all of `Order` can be populated from an incoming request 
without the annotation. Shape such a model as 
+a request contract carrying only the fields the controller intends to accept, 
rather than as a domain or persistence 
+entity — see 
[`@StrutsParameter`](../../core-developers/struts-parameter-annotation.html#modeldriven-actions)
 for the 
+full rules.
+{:.alert .alert-warning}
+
 Where's ActionSupport? Normally, you extend ActionSupport when writing Struts 
2 actions. In these case, our controller 
 doesn't do that. Why, you ask? ActionSupport provides a bunch of important 
functionality to our actions, including support 
 for i18n and validation. All of this functionality, in the RESTful case, is 
provided by the default interceptor stack 

Reply via email to