This is an automated email from the ASF dual-hosted git repository. lukaszlenart pushed a commit to branch docs/WW-5626-struts-parameter-depth in repository https://gitbox.apache.org/repos/asf/struts-site.git
commit 39984cf84db87efe864a0def46ee254cb0d96854 Author: Lukasz Lenart <[email protected]> AuthorDate: Wed Jul 1 07:03:30 2026 +0200 WW-5626 docs: clarify @StrutsParameter depth for collections 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 | 50 +++++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/source/core-developers/struts-parameter-annotation.md b/source/core-developers/struts-parameter-annotation.md index 95bb0d414..f49c147a0 100644 --- a/source/core-developers/struts-parameter-annotation.md +++ b/source/core-developers/struts-parameter-annotation.md @@ -34,10 +34,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 +121,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
