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 bfed245a4 WW-5626 docs: clarify @StrutsParameter depth for collections
(#308)
bfed245a4 is described below
commit bfed245a4beb6532aadb78f16b4e3e4a981d17fa
Author: Lukasz Lenart <[email protected]>
AuthorDate: Wed Jul 1 07:49:07 2026 +0200
WW-5626 docs: clarify @StrutsParameter depth for collections (#308)
Explain how the `depth` parameter is counted (each property access or
collection/map index is one level) and correct the collection example to
use `depth = 2` instead of `depth = 1` — indexing into the collection is
itself a level, so reaching an element's property needs depth 2 even for
flat POJOs. Also note that JSON/REST payloads populating collection
elements require the getter to be annotated, not just the setter.
Reported on the user list against 7.2.1 by Markus (flyingfischer.ch).
Co-authored-by: Claude Opus 4.8 <[email protected]>
---
.../core-developers/struts-parameter-annotation.md | 54 +++++++++++++++++++---
1 file changed, 48 insertions(+), 6 deletions(-)
diff --git a/source/core-developers/struts-parameter-annotation.md
b/source/core-developers/struts-parameter-annotation.md
index 95bb0d414..1c2ac830e 100644
--- a/source/core-developers/struts-parameter-annotation.md
+++ b/source/core-developers/struts-parameter-annotation.md
@@ -7,6 +7,10 @@ parent:
---
# StrutsParameter Annotation
+{:.no_toc}
+
+* Will be replaced with the ToC, excluding a header
+{:toc}
`@StrutsParameter` is a security annotation that marks which fields and
methods in your Action class can receive values from user requests.
@@ -34,10 +38,39 @@ The placement of the `@StrutsParameter` annotation is
crucial and depends on how
- Checkboxes (single or multiple values).
- Collections and Maps, when you are populating the whole collection/map
from the request.
-- **On a public getter method:** Place the annotation on a getter method when
you want to allow populating the properties of the object returned by the
getter. The `depth` parameter is used to control how deep the object graph can
be populated. This is typically used for complex objects or collections of
complex objects.
+- **On a public getter method:** Place the annotation on a getter method when
you want to allow populating the properties of the object (or objects) returned
by the getter. The `depth` parameter controls how deep into that object graph
population is allowed — see [Understanding the `depth`
parameter](#understanding-the-depth-parameter) below. This is typically used
for complex objects or collections of complex objects.
- **On a public field:** For simple types, you can place the annotation
directly on the public field as a shorthand for a setter annotation.
+## Understanding the `depth` parameter
+
+When you annotate a getter, `depth` limits how far Struts may traverse the
object
+graph reachable from that getter while applying request parameters. **Each
+navigation step counts as one level** — following a property *or* indexing
into a
+collection or map.
+
+To find the value you need, count the segments after the annotated property in
the
+request expression:
+
+| Request expression | Annotated getter | Steps beyond the getter
| Required `depth` |
+|-------------------------|------------------|--------------------------------|------------------|
+| `user.name` | `getUser()` | `.name`
| `1` |
+| `user.address.city` | `getUser()` | `.address` → `.city`
| `2` |
+| `users[0].name` | `getUsers()` | `[0]` → `.name`
| `2` |
+
+The key point for collections and maps: **indexing into the collection is
itself a
+level.** Reaching a property of a collection element therefore always costs
one more
+level than reaching the same property on a plain object. This holds even when
the
+element type is a flat POJO with only simple fields — populating
`contents[0].title`
+still needs `depth = 2` (one level to reach the element, one more to reach its
+property), not `depth = 1`.
+
+In the annotation's own terms, `depth` is *the number of periods or brackets
that
+may appear in the parameter name*. The default is `depth = 0`, which permits
only
+setters and fields directly on the action class. Reaching a property of a
returned
+object needs `depth = 1` or more; reaching a property of an object held in a
+collection or map needs `depth = 2` or more.
+
## Examples
### Simple field
@@ -92,21 +125,30 @@ public class MyAction {
}
```
-#### Populating properties of objects within a collection
-
-When populating properties of objects that are already in a collection,
annotate the getter.
+When populating properties of objects that are already in a collection,
annotate the
+getter. Because reaching an element's property requires indexing into the
collection
+*and then* following the property, this needs `depth = 2` (see
+[Understanding the `depth` parameter](#understanding-the-depth-parameter)).
```java
public class MyAction {
private List<User> users; // assume this is initialized in the constructor
or elsewhere
- @StrutsParameter(depth = 1)
+ @StrutsParameter(depth = 2)
public List<User> getUsers() {
return users;
}
// ...
}
```
-This allows requests like `users[0].name=John`.
+This allows requests like `users[0].name=John`. Note that `depth = 2` is
required
+even when `User` is a flat object with only simple properties — the extra
level pays
+for indexing into the collection, not for nesting within the element.
+
+The same rule applies to JSON and REST payloads: a body such as
+`{"users":[{"name":"John"}]}` populates `users[0].name`, so the `getUsers()`
getter
+must be annotated with `depth = 2` for the nested value to be accepted.
Annotating
+only the setter is not enough — the JSON/REST authorization checks the getter
when
+descending into the collection's elements.
### Complex object