fix(java): place bean-validation @Valid on the type argument instead of the container (HV000271) - #24176
fix(java): place bean-validation @Valid on the type argument instead of the container (HV000271)#24176twonky4 wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
2 issues found across 579 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="samples/openapi3/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/model/ArrayOfArrayOfNumberOnly.java">
<violation number="1" location="samples/openapi3/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/model/ArrayOfArrayOfNumberOnly.java:50">
P3: Unused `jakarta.validation.Valid` import remains after the only `@Valid` annotation in the class was removed.</violation>
</file>
<file name="samples/client/petstore/java/rest-assured/src/main/java/org/openapitools/client/model/ArrayOfNumberOnly.java">
<violation number="1" location="samples/client/petstore/java/rest-assured/src/main/java/org/openapitools/client/model/ArrayOfNumberOnly.java:64">
P3: `javax.validation.Valid` import is unused after the only @Valid annotation was removed from the getter. This leaves stale generated code that can trigger lint/checkstyle failures.</violation>
</file>
Note: This PR contains a large number of files. cubic only reviews up to 200 files per PR, so some files may not have been reviewed. cubic prioritizes the most important files to review.
Re-trigger cubic
| @@ -47,7 +47,7 @@ public ArrayOfArrayOfNumberOnly addArrayArrayNumberItem(List<BigDecimal> arrayAr | |||
| * Get arrayArrayNumber | |||
There was a problem hiding this comment.
P3: Unused jakarta.validation.Valid import remains after the only @Valid annotation in the class was removed.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/openapi3/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/model/ArrayOfArrayOfNumberOnly.java, line 50:
<comment>Unused `jakarta.validation.Valid` import remains after the only `@Valid` annotation in the class was removed.</comment>
<file context>
@@ -47,7 +47,7 @@ public ArrayOfArrayOfNumberOnly addArrayArrayNumberItem(List<BigDecimal> arrayAr
* @return arrayArrayNumber
*/
- @Valid
+
@Schema(name = "ArrayArrayNumber", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
@JsonProperty("ArrayArrayNumber")
</file context>
| */ | ||
| @javax.annotation.Nullable | ||
| @Valid | ||
|
|
There was a problem hiding this comment.
P3: javax.validation.Valid import is unused after the only @Valid annotation was removed from the getter. This leaves stale generated code that can trigger lint/checkstyle failures.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/rest-assured/src/main/java/org/openapitools/client/model/ArrayOfNumberOnly.java, line 64:
<comment>`javax.validation.Valid` import is unused after the only @Valid annotation was removed from the getter. This leaves stale generated code that can trigger lint/checkstyle failures.</comment>
<file context>
@@ -61,7 +61,6 @@ public ArrayOfNumberOnly addArrayNumberItem(BigDecimal arrayNumberItem) {
*/
@javax.annotation.Nullable
- @Valid
public List<BigDecimal> getArrayNumber() {
</file context>
4691ca2 to
fd351f8
Compare
|
A note to save reviewers some time. On the automated review flagging that dropping the parameter-level
|
|
https://github.com/OpenAPITools/openapi-generator/actions/runs/28539637986/job/84609826940?pr=24176 should be fixed in the latest master please merge the latest into your branch and resolve the merge conflicts when you've time |
fd351f8 to
81f2a3b
Compare
|
@wing328 rebased and conflicts solved. |
81f2a3b to
0d1b1d1
Compare
|
Rebased onto the latest master again and resolved the conflicts (only JavaSpring/beanValidation.mustache, due to the recent @NotNull→notNull partial refactor). All GitHub Actions checks are green, including "Samples up-to-date". The only red checks are the CircleCI node1 (Perl) and node2 (cpp-restsdk) shards, which are unrelated to this Java-only change — the PR touches no Perl/C++ files, and those shards run only Perl/C++ integration tests; looks like flaky infra, a re-run should clear them. Ready for review/merge. @JFCote thanks for the offer to help! |
dd9af54 to
ee93f53
Compare
There was a problem hiding this comment.
10 issues found across 597 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="modules/openapi-generator/src/main/resources/JavaJaxRS/cxf/bodyParams.mustache">
<violation number="1" location="modules/openapi-generator/src/main/resources/JavaJaxRS/cxf/bodyParams.mustache:1">
P2: For `jaxrs-cxf-client` map body parameters, this guard removes the only `@Valid` because `JavaCXFClientCodegen` leaves map-value type annotations disabled. Override `useBeanValidationOnMapValueType()` in `JavaCXFClientCodegen` or retain container-level `@Valid` for this generator so map-value validation is not lost.</violation>
</file>
<file name="samples/client/petstore/java/jersey3/src/main/java/org/openapitools/client/model/ArrayTest.java">
<violation number="1" location="samples/client/petstore/java/jersey3/src/main/java/org/openapitools/client/model/ArrayTest.java:113">
P2: Dropping the container-level @Valid from the nested-container property getArrayArrayOfModel() (type List<List<@Valid ReadOnlyFirst>>) breaks cascaded element validation. In Bean Validation 2.0 a cascade must be declared at each container level, so validating the innermost ReadOnlyFirst elements requires List<@Valid List<@Valid ReadOnlyFirst>>. The current output has @Valid only on the innermost type argument, so the validator never descends into the inner Lists and the ReadOnlyFirst elements are no longer validated. This contradicts the PR's claim that element validation is preserved. The generator's getTypeDeclarationWithBeanValidation/getBeanValidation returns no annotation for the intermediate array type, so the fix must be in the generator: place @Valid on the intermediate container type argument (and regenerate the sample) when an array/set element is itself a container.</violation>
</file>
<file name="samples/client/petstore/java/jersey3-jackson3/src/main/java/org/openapitools/client/model/ArrayTest.java">
<violation number="1" location="samples/client/petstore/java/jersey3-jackson3/src/main/java/org/openapitools/client/model/ArrayTest.java:112">
P2: For the nested container `arrayArrayOfModel` (`List<List<@Valid ReadOnlyFirst>>`), removing the getter's `@Valid` drops element validation: the outer list is now neither getter-annotated nor type-argument-`@Valid`, so Bean Validation never cascades into the inner lists and the innermost `@Valid ReadOnlyFirst` is never reached. To preserve cascading HV000271-style, `@Valid` must appear on every nesting level, i.e. `List<@Valid List<@Valid ReadOnlyFirst>>`. The generator only annotates the deepest element type, so this regression hits all nested-container models in the migrated generators.</violation>
</file>
<file name="samples/openapi3/client/petstore/spring-cloud-spring-pageable/src/main/java/org/openapitools/api/UserApi.java">
<violation number="1" location="samples/openapi3/client/petstore/spring-cloud-spring-pageable/src/main/java/org/openapitools/api/UserApi.java:85">
P1: For a Spring @RequestBody, validation is triggered by @Valid/@Validated on the parameter itself: RequestResponseBodyMethodProcessor.validateIfApplicable scans only parameter.getParameterAnnotations() and never sees the type-use @Valid inside List<@Valid User>. Removing @Valid from the container therefore disables validation of the body entirely, so the list elements are not validated — contradicting the PR claim that element validation is preserved. Keep the parameter-level @Valid on @RequestBody (rely on the type-argument @Valid for the cascade) so Spring still validates the body.</violation>
</file>
<file name="samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/api/UserApi.java">
<violation number="1" location="samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/api/UserApi.java:58">
P1: Removing the parameter-level @Valid from `@RequestBody List<@Valid User>` disables body validation in Spring MVC. Spring only validates a @RequestBody when the parameter itself is annotated @Valid/@Validated; the type-argument @Valid on the element type is not a trigger and is never evaluated because binder.validate() is never called. The previous `@Valid @RequestBody List<@Valid User>` validated each element, so this change silently drops element validation for container request bodies (invalid elements now pass through). Keep the parameter @Valid (it is Spring's validation trigger, not the deprecated container-level @Valid) and retain the type-argument @Valid to fix HV000271: `@Valid @RequestBody List<@Valid User> user`.</violation>
</file>
<file name="samples/openapi3/client/petstore/spring-cloud/src/main/java/org/openapitools/api/UserApi.java">
<violation number="1" location="samples/openapi3/client/petstore/spring-cloud/src/main/java/org/openapitools/api/UserApi.java:95">
P1: Removing the parameter-level @Valid from a container @RequestBody disables Spring's automatic request-body validation. Spring's RequestResponseBodyMethodProcessor.validateIfApplicable only scans the parameter's declaration annotations (@Valid/@Validated) to decide whether to call binder.validate(); the @Valid on the List type argument is a type-use annotation that is never examined, so binder.validate() is never invoked and neither the container nor its elements get validated. This contradicts the PR's claim that element validation is preserved via the type-argument @Valid, and it affects every server-side method the shared JavaSpring bodyParams template generates (a list/map @RequestBody now silently skips validation).</violation>
</file>
<file name="samples/client/petstore/spring-cloud-tags/src/main/java/org/openapitools/api/UserController.java">
<violation number="1" location="samples/client/petstore/spring-cloud-tags/src/main/java/org/openapitools/api/UserController.java:85">
P2: Removing the parameter-level `@Valid` on `@RequestBody List<@Valid User>` disables Spring MVC's built-in request-body validation trigger (`RequestResponseBodyMethodProcessor` only acts on a parameter-declared `@Valid`/`@Validated`; it does not see the type-use `@Valid User`). Element validation now depends entirely on the `@Validated` method-validation AOP path, which requires `spring-boot-starter-validation` and a proxied controller whose interface `@Validated` is recognized. That path is present in the standard generated setup, but in any integration where method validation isn't active, the list body silently becomes fully unvalidated (no binding-validation fallback and no compile-time signal). Worth confirming/documenting this contract, e.g. by asserting in the generated server that `@Validated` + MethodValidationPostProcessor are actually in effect for container `@RequestBody`/`@RequestParam` params.</violation>
</file>
<file name="samples/openapi3/client/petstore/spring-stubs-skip-default-interface/src/main/java/org/openapitools/api/UserApi.java">
<violation number="1" location="samples/openapi3/client/petstore/spring-stubs-skip-default-interface/src/main/java/org/openapitools/api/UserApi.java:95">
P1: Removing the container-level @Valid leaves `@RequestBody List<@Valid User> user` with no validation trigger. Spring MVC only validates a @RequestBody when @Valid/@Validated is on the parameter itself; the type-use @Valid inside `List<@Valid User>` is a container element constraint processed during validation, not a trigger. On the standard data-binding path these list bodies are now deserialized without validating any User element, so element validation is not preserved as the PR claims. Keep a parameter-level validation trigger (for example `@Valid @RequestBody List<@Valid User>`) or verify via a runtime test that element validation still fires.</violation>
</file>
<file name="samples/openapi3/server/petstore/springboot/src/main/java/org/openapitools/api/UserApi.java">
<violation number="1" location="samples/openapi3/server/petstore/springboot/src/main/java/org/openapitools/api/UserApi.java:106">
P1: For container @RequestBody/@RequestParam/@RequestPart, removing the parameter-level @Valid leaves only the type-use `@Valid` inside `List<@Valid User>`. Spring MVC's RequestResponseBodyMethodProcessor decides whether to validate from the parameter itself (`@Valid`/`@Validated` on the parameter), not from a type-argument annotation, so element validation is silently dropped for every generated controller in the Spring family. Keep `@Valid` on the parameter and put the cascading `@Valid` on the type argument (as in `@Valid @RequestBody List<@Valid User>`); the parameter-level `@Valid` is distinct from a container-type annotation, so it does not reintroduce HV000271. Reactive params are unaffected since the template retains `@Valid` there.</violation>
</file>
<file name="samples/openapi3/client/petstore/spring-cloud-oas3-fakeapi/src/main/java/org/openapitools/api/UserApi.java">
<violation number="1" location="samples/openapi3/client/petstore/spring-cloud-oas3-fakeapi/src/main/java/org/openapitools/api/UserApi.java:89">
P1: Removing the container-level @Valid disables request-body validation in Spring MVC. Spring triggers body validation only when the method parameter itself is annotated with @Valid/@Validated (validateIfApplicable reads the parameter annotations); the class-level @Validated here does not apply to @RequestBody. So `@RequestBody List<@Valid User>` is never validated, and the type-argument @Valid on the elements is never evaluated either — the advertised backward-compatible element validation is lost. Keep @Valid on the container for request-body params: `@Valid @RequestBody List<@Valid User>`.</violation>
</file>
Note: This PR contains a large number of files. cubic selects up to 200 of the highest-priority eligible files for this review, so some files may not have been reviewed.
Re-trigger cubic
| ) | ||
| ResponseEntity<Void> createUsersWithArrayInput( | ||
| @Parameter(name = "body", description = "List of user object", required = true) @Valid @RequestBody List<@Valid User> body | ||
| @Parameter(name = "body", description = "List of user object", required = true) @RequestBody List<@Valid User> body |
There was a problem hiding this comment.
P1: For a Spring @RequestBody, validation is triggered by @Valid/@validated on the parameter itself: RequestResponseBodyMethodProcessor.validateIfApplicable scans only parameter.getParameterAnnotations() and never sees the type-use @Valid inside List<@Valid User>. Removing @Valid from the container therefore disables validation of the body entirely, so the list elements are not validated — contradicting the PR claim that element validation is preserved. Keep the parameter-level @Valid on @RequestBody (rely on the type-argument @Valid for the cascade) so Spring still validates the body.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/openapi3/client/petstore/spring-cloud-spring-pageable/src/main/java/org/openapitools/api/UserApi.java, line 85:
<comment>For a Spring @RequestBody, validation is triggered by @Valid/@Validated on the parameter itself: RequestResponseBodyMethodProcessor.validateIfApplicable scans only parameter.getParameterAnnotations() and never sees the type-use @Valid inside List<@Valid User>. Removing @Valid from the container therefore disables validation of the body entirely, so the list elements are not validated — contradicting the PR claim that element validation is preserved. Keep the parameter-level @Valid on @RequestBody (rely on the type-argument @Valid for the cascade) so Spring still validates the body.</comment>
<file context>
@@ -82,7 +82,7 @@ ResponseEntity<Void> createUser(
)
ResponseEntity<Void> createUsersWithArrayInput(
- @Parameter(name = "body", description = "List of user object", required = true) @Valid @RequestBody List<@Valid User> body
+ @Parameter(name = "body", description = "List of user object", required = true) @RequestBody List<@Valid User> body
);
</file context>
| ) | ||
| ResponseEntity<Void> createUsersWithArrayInput( | ||
| @Parameter(name = "User", description = "List of user object", required = true) @Valid @RequestBody List<@Valid User> user | ||
| @Parameter(name = "User", description = "List of user object", required = true) @RequestBody List<@Valid User> user |
There was a problem hiding this comment.
P1: Removing the container-level @Valid disables request-body validation in Spring MVC. Spring triggers body validation only when the method parameter itself is annotated with @Valid/@validated (validateIfApplicable reads the parameter annotations); the class-level @validated here does not apply to @RequestBody. So @RequestBody List<@Valid User> is never validated, and the type-argument @Valid on the elements is never evaluated either — the advertised backward-compatible element validation is lost. Keep @Valid on the container for request-body params: @Valid @RequestBody List<@Valid User>.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/openapi3/client/petstore/spring-cloud-oas3-fakeapi/src/main/java/org/openapitools/api/UserApi.java, line 89:
<comment>Removing the container-level @Valid disables request-body validation in Spring MVC. Spring triggers body validation only when the method parameter itself is annotated with @Valid/@Validated (validateIfApplicable reads the parameter annotations); the class-level @Validated here does not apply to @RequestBody. So `@RequestBody List<@Valid User>` is never validated, and the type-argument @Valid on the elements is never evaluated either — the advertised backward-compatible element validation is lost. Keep @Valid on the container for request-body params: `@Valid @RequestBody List<@Valid User>`.</comment>
<file context>
@@ -86,7 +86,7 @@ ResponseEntity<Void> createUser(
)
ResponseEntity<Void> createUsersWithArrayInput(
- @Parameter(name = "User", description = "List of user object", required = true) @Valid @RequestBody List<@Valid User> user
+ @Parameter(name = "User", description = "List of user object", required = true) @RequestBody List<@Valid User> user
);
</file context>
| ) | ||
| ResponseEntity<Void> createUsersWithArrayInput( | ||
| @Valid @RequestBody List<@Valid User> user | ||
| @RequestBody List<@Valid User> user |
There was a problem hiding this comment.
P1: Removing the parameter-level @Valid from @RequestBody List<@Valid User> disables body validation in Spring MVC. Spring only validates a @RequestBody when the parameter itself is annotated @Valid/@validated; the type-argument @Valid on the element type is not a trigger and is never evaluated because binder.validate() is never called. The previous @Valid @RequestBody List<@Valid User> validated each element, so this change silently drops element validation for container request bodies (invalid elements now pass through). Keep the parameter @Valid (it is Spring's validation trigger, not the deprecated container-level @Valid) and retain the type-argument @Valid to fix HV000271: @Valid @RequestBody List<@Valid User> user.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/api/UserApi.java, line 58:
<comment>Removing the parameter-level @Valid from `@RequestBody List<@Valid User>` disables body validation in Spring MVC. Spring only validates a @RequestBody when the parameter itself is annotated @Valid/@Validated; the type-argument @Valid on the element type is not a trigger and is never evaluated because binder.validate() is never called. The previous `@Valid @RequestBody List<@Valid User>` validated each element, so this change silently drops element validation for container request bodies (invalid elements now pass through). Keep the parameter @Valid (it is Spring's validation trigger, not the deprecated container-level @Valid) and retain the type-argument @Valid to fix HV000271: `@Valid @RequestBody List<@Valid User> user`.</comment>
<file context>
@@ -55,7 +55,7 @@ ResponseEntity<Void> createUser(
)
ResponseEntity<Void> createUsersWithArrayInput(
- @Valid @RequestBody List<@Valid User> user
+ @RequestBody List<@Valid User> user
);
</file context>
| @RequestBody List<@Valid User> user | |
| @Valid @RequestBody List<@Valid User> user |
| ) | ||
| ResponseEntity<Void> createUsersWithArrayInput( | ||
| @Parameter(name = "User", description = "List of user object", required = true) @Valid @RequestBody List<@Valid User> user | ||
| @Parameter(name = "User", description = "List of user object", required = true) @RequestBody List<@Valid User> user |
There was a problem hiding this comment.
P1: Removing the parameter-level @Valid from a container @RequestBody disables Spring's automatic request-body validation. Spring's RequestResponseBodyMethodProcessor.validateIfApplicable only scans the parameter's declaration annotations (@Valid/@validated) to decide whether to call binder.validate(); the @Valid on the List type argument is a type-use annotation that is never examined, so binder.validate() is never invoked and neither the container nor its elements get validated. This contradicts the PR's claim that element validation is preserved via the type-argument @Valid, and it affects every server-side method the shared JavaSpring bodyParams template generates (a list/map @RequestBody now silently skips validation).
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/openapi3/client/petstore/spring-cloud/src/main/java/org/openapitools/api/UserApi.java, line 95:
<comment>Removing the parameter-level @Valid from a container @RequestBody disables Spring's automatic request-body validation. Spring's RequestResponseBodyMethodProcessor.validateIfApplicable only scans the parameter's declaration annotations (@Valid/@Validated) to decide whether to call binder.validate(); the @Valid on the List type argument is a type-use annotation that is never examined, so binder.validate() is never invoked and neither the container nor its elements get validated. This contradicts the PR's claim that element validation is preserved via the type-argument @Valid, and it affects every server-side method the shared JavaSpring bodyParams template generates (a list/map @RequestBody now silently skips validation).</comment>
<file context>
@@ -92,7 +92,7 @@ ResponseEntity<Void> createUser(
)
ResponseEntity<Void> createUsersWithArrayInput(
- @Parameter(name = "User", description = "List of user object", required = true) @Valid @RequestBody List<@Valid User> user
+ @Parameter(name = "User", description = "List of user object", required = true) @RequestBody List<@Valid User> user
);
</file context>
| @Parameter(name = "User", description = "List of user object", required = true) @RequestBody List<@Valid User> user | |
| @Parameter(name = "User", description = "List of user object", required = true) @Valid @RequestBody List<@Valid User> user |
| ) | ||
| ResponseEntity<Void> createUsersWithArrayInput( | ||
| @Parameter(name = "User", description = "List of user object", required = true) @Valid @RequestBody List<@Valid User> user | ||
| @Parameter(name = "User", description = "List of user object", required = true) @RequestBody List<@Valid User> user |
There was a problem hiding this comment.
P1: Removing the container-level @Valid leaves @RequestBody List<@Valid User> user with no validation trigger. Spring MVC only validates a @RequestBody when @Valid/@validated is on the parameter itself; the type-use @Valid inside List<@Valid User> is a container element constraint processed during validation, not a trigger. On the standard data-binding path these list bodies are now deserialized without validating any User element, so element validation is not preserved as the PR claims. Keep a parameter-level validation trigger (for example @Valid @RequestBody List<@Valid User>) or verify via a runtime test that element validation still fires.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/openapi3/client/petstore/spring-stubs-skip-default-interface/src/main/java/org/openapitools/api/UserApi.java, line 95:
<comment>Removing the container-level @Valid leaves `@RequestBody List<@Valid User> user` with no validation trigger. Spring MVC only validates a @RequestBody when @Valid/@Validated is on the parameter itself; the type-use @Valid inside `List<@Valid User>` is a container element constraint processed during validation, not a trigger. On the standard data-binding path these list bodies are now deserialized without validating any User element, so element validation is not preserved as the PR claims. Keep a parameter-level validation trigger (for example `@Valid @RequestBody List<@Valid User>`) or verify via a runtime test that element validation still fires.</comment>
<file context>
@@ -92,7 +92,7 @@ ResponseEntity<Void> createUser(
)
ResponseEntity<Void> createUsersWithArrayInput(
- @Parameter(name = "User", description = "List of user object", required = true) @Valid @RequestBody List<@Valid User> user
+ @Parameter(name = "User", description = "List of user object", required = true) @RequestBody List<@Valid User> user
) throws Exception;
</file context>
| @Parameter(name = "User", description = "List of user object", required = true) @RequestBody List<@Valid User> user | |
| @Parameter(name = "User", description = "List of user object", required = true) @Valid @RequestBody List<@Valid User> user |
| * @return arrayArrayOfInteger | ||
| */ | ||
| @jakarta.annotation.Nullable | ||
| @Valid |
There was a problem hiding this comment.
P2: Dropping the container-level @Valid from the nested-container property getArrayArrayOfModel() (type List<List<@Valid ReadOnlyFirst>>) breaks cascaded element validation. In Bean Validation 2.0 a cascade must be declared at each container level, so validating the innermost ReadOnlyFirst elements requires List<@Valid List<@Valid ReadOnlyFirst>>. The current output has @Valid only on the innermost type argument, so the validator never descends into the inner Lists and the ReadOnlyFirst elements are no longer validated. This contradicts the PR's claim that element validation is preserved. The generator's getTypeDeclarationWithBeanValidation/getBeanValidation returns no annotation for the intermediate array type, so the fix must be in the generator: place @Valid on the intermediate container type argument (and regenerate the sample) when an array/set element is itself a container.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/jersey3/src/main/java/org/openapitools/client/model/ArrayTest.java, line 113:
<comment>Dropping the container-level @Valid from the nested-container property getArrayArrayOfModel() (type List<List<@Valid ReadOnlyFirst>>) breaks cascaded element validation. In Bean Validation 2.0 a cascade must be declared at each container level, so validating the innermost ReadOnlyFirst elements requires List<@Valid List<@Valid ReadOnlyFirst>>. The current output has @Valid only on the innermost type argument, so the validator never descends into the inner Lists and the ReadOnlyFirst elements are no longer validated. This contradicts the PR's claim that element validation is preserved. The generator's getTypeDeclarationWithBeanValidation/getBeanValidation returns no annotation for the intermediate array type, so the fix must be in the generator: place @Valid on the intermediate container type argument (and regenerate the sample) when an array/set element is itself a container.</comment>
<file context>
@@ -110,7 +110,6 @@ public ArrayTest addArrayArrayOfIntegerItem(List<Long> arrayArrayOfIntegerItem)
*/
@jakarta.annotation.Nullable
- @Valid
@JsonProperty(value = JSON_PROPERTY_ARRAY_ARRAY_OF_INTEGER, required = false)
@JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
</file context>
| * @return arrayArrayOfInteger | ||
| */ | ||
| @jakarta.annotation.Nullable | ||
| @Valid |
There was a problem hiding this comment.
P2: For the nested container arrayArrayOfModel (List<List<@Valid ReadOnlyFirst>>), removing the getter's @Valid drops element validation: the outer list is now neither getter-annotated nor type-argument-@Valid, so Bean Validation never cascades into the inner lists and the innermost @Valid ReadOnlyFirst is never reached. To preserve cascading HV000271-style, @Valid must appear on every nesting level, i.e. List<@Valid List<@Valid ReadOnlyFirst>>. The generator only annotates the deepest element type, so this regression hits all nested-container models in the migrated generators.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/jersey3-jackson3/src/main/java/org/openapitools/client/model/ArrayTest.java, line 112:
<comment>For the nested container `arrayArrayOfModel` (`List<List<@Valid ReadOnlyFirst>>`), removing the getter's `@Valid` drops element validation: the outer list is now neither getter-annotated nor type-argument-`@Valid`, so Bean Validation never cascades into the inner lists and the innermost `@Valid ReadOnlyFirst` is never reached. To preserve cascading HV000271-style, `@Valid` must appear on every nesting level, i.e. `List<@Valid List<@Valid ReadOnlyFirst>>`. The generator only annotates the deepest element type, so this regression hits all nested-container models in the migrated generators.</comment>
<file context>
@@ -109,7 +109,6 @@ public ArrayTest addArrayArrayOfIntegerItem(List<Long> arrayArrayOfIntegerItem)
*/
@jakarta.annotation.Nullable
- @Valid
@JsonProperty(value = JSON_PROPERTY_ARRAY_ARRAY_OF_INTEGER, required = false)
@JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
</file context>
| ) | ||
| ResponseEntity<Void> createUsersWithArrayInput( | ||
| @Parameter(name = "body", description = "List of user object", required = true) @Valid @RequestBody List<@Valid User> body | ||
| @Parameter(name = "body", description = "List of user object", required = true) @RequestBody List<@Valid User> body |
There was a problem hiding this comment.
P2: Removing the parameter-level @Valid on @RequestBody List<@Valid User> disables Spring MVC's built-in request-body validation trigger (RequestResponseBodyMethodProcessor only acts on a parameter-declared @Valid/@Validated; it does not see the type-use @Valid User). Element validation now depends entirely on the @Validated method-validation AOP path, which requires spring-boot-starter-validation and a proxied controller whose interface @Validated is recognized. That path is present in the standard generated setup, but in any integration where method validation isn't active, the list body silently becomes fully unvalidated (no binding-validation fallback and no compile-time signal). Worth confirming/documenting this contract, e.g. by asserting in the generated server that @Validated + MethodValidationPostProcessor are actually in effect for container @RequestBody/@RequestParam params.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/spring-cloud-tags/src/main/java/org/openapitools/api/UserController.java, line 85:
<comment>Removing the parameter-level `@Valid` on `@RequestBody List<@Valid User>` disables Spring MVC's built-in request-body validation trigger (`RequestResponseBodyMethodProcessor` only acts on a parameter-declared `@Valid`/`@Validated`; it does not see the type-use `@Valid User`). Element validation now depends entirely on the `@Validated` method-validation AOP path, which requires `spring-boot-starter-validation` and a proxied controller whose interface `@Validated` is recognized. That path is present in the standard generated setup, but in any integration where method validation isn't active, the list body silently becomes fully unvalidated (no binding-validation fallback and no compile-time signal). Worth confirming/documenting this contract, e.g. by asserting in the generated server that `@Validated` + MethodValidationPostProcessor are actually in effect for container `@RequestBody`/`@RequestParam` params.</comment>
<file context>
@@ -82,7 +82,7 @@ ResponseEntity<Void> createUser(
)
ResponseEntity<Void> createUsersWithArrayInput(
- @Parameter(name = "body", description = "List of user object", required = true) @Valid @RequestBody List<@Valid User> body
+ @Parameter(name = "body", description = "List of user object", required = true) @RequestBody List<@Valid User> body
);
</file context>
ee93f53 to
36bf484
Compare
There was a problem hiding this comment.
No issues found across 597 files
Note: This PR contains a large number of files. cubic selects up to 200 of the highest-priority eligible files for this review, so some files may not have been reviewed.
Re-trigger cubic
36bf484 to
3dbc3f6
Compare
There was a problem hiding this comment.
No issues found across 598 files
Note: This PR contains a large number of files. cubic selects up to 200 of the highest-priority eligible files for this review, so some files may not have been reviewed.
Re-trigger cubic
…of the container (HV000271)
Hibernate Validator 9.1+ (bundled with Spring Boot 4) logs HV000271 ("Using
@Valid on a container is deprecated. You should apply the annotation on the
type argument(s)") for every @Valid-annotated List/Set/Map — on both model
properties and API parameters.
This relocates @Valid from the container to its type argument — the
Bean-Validation-2.0 form (List<@Valid T>, Map<String, @Valid V>) — which
cascades identically but is not deprecated. Backward-compatible: element
validation is preserved, never dropped; single-object @Valid is untouched.
Verified on Spring Boot 3.3 (Spring 6.1) and 4.1 (Spring 7): a container
parameter carrying only the type-argument @Valid still triggers element
validation via method validation, with no HV000271.
Scope (Java family): spring, java client, JAX-RS (jersey, resteasy(+eap),
cxf(+extended/cdi), spec), java-camel, java-msf4j.
Models (property/getter): the container @Valid is moved to the type argument.
Map values are gated behind a new
AbstractJavaCodegen#useBeanValidationOnMapValueType() (default false; overridden
true in Spring/JavaClient/JAX-RS) so untouched generators don't silently gain
map-value validation. Arrays/sets already injected the type-argument form.
oneOf/anyOf/allOf model elements now also receive the type-argument @Valid
(List<@Valid ShapeOneOf>), so their element validation is preserved rather than
dropped; a oneOf of constants (an enum) stays without @Valid.
Parameters (@RequestBody/@RequestParam/@RequestPart): the redundant
container-level @Valid is dropped for container parameters; element validation
is driven by the type-argument @Valid. Single-object parameters keep @Valid.
An Optional-wrapped scalar parameter (useOptional, e.g. Optional<Integer>) no
longer emits a parameter-level @Valid either — Hibernate Validator treats
Optional as a container, so it was the same HV000271 with nothing to cascade
into. Reactive Mono/Flux bodies are intentionally untouched (not Jakarta
containers, so no HV000271).
Regenerated all affected samples and added/updated codegen tests in
SpringCodegenTest, JavaClientCodegenTest, JavaJAXRSSpecServerCodegenTest and
JavaValidationArrayPrimitivesTest.
3dbc3f6 to
3bfada1
Compare
There was a problem hiding this comment.
No issues found across 599 files
Note: This PR contains a large number of files. cubic selects up to 200 of the highest-priority eligible files for this review, so some files may not have been reviewed.
Re-trigger cubic
| @org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") | ||
| ResponseEntity<List<Pet>> findPetsByStatus( | ||
| @NotNull @Parameter(name = "status", description = "Status values that need to be considered for filter", required = true, in = ParameterIn.QUERY) @Valid @RequestParam(value = "status", required = true) List<String> status, | ||
| @NotNull @Parameter(name = "status", description = "Status values that need to be considered for filter", required = true, in = ParameterIn.QUERY) @RequestParam(value = "status", required = true) List<String> status, |
There was a problem hiding this comment.
According to:
https://docs.hibernate.org/validator/9.1/whats-new/en-US/html_single/#_deprecating_the_use_of_valid_at_the_container_level
| @NotNull @Parameter(name = "status", description = "Status values that need to be considered for filter", required = true, in = ParameterIn.QUERY) @RequestParam(value = "status", required = true) List<String> status, | |
| @NotNull @Parameter(name = "status", description = "Status values that need to be considered for filter", required = true, in = ParameterIn.QUERY) @RequestParam(value = "status", required = true) List<@Valid String> status, |
Of course it may not a target for a String but it's important for an Object, in my case:
Before have
ResponseEntity<ValuedAggregatedPositionReadDto> getAggregatedPosition(
@NotNull @Size(min = 1) @Valid @RequestParam(value = "accountIds", required = true)
List<ShiftRawId> accountIds,
With this templates the @Valid is removed.
ResponseEntity<ValuedAggregatedPositionReadDto> getAggregatedPosition(
@NotNull @Size(min = 1) @RequestParam(value = "accountIds", required = true)
List<ShiftRawId> accountIds,
But I think we should have:
ResponseEntity<ValuedAggregatedPositionReadDto> getAggregatedPosition(
@NotNull @Size(min = 1) @RequestParam(value = "accountIds", required = true)
List<@Valid ShiftRawId> accountIds,
There was a problem hiding this comment.
Without it My objects ShiftRawId are never validated.
There was a problem hiding this comment.
You're right that a list of objects must keep element validation, and that's exactly what the PR does: List<@Valid X> for object models and, since a recent commit on this branch, also for oneOf/anyOf/allOf models.
If your ShiftRawId is a oneOf/composed type, that's the gap you hit: the deprecated container-level @Valid was dropped but the type-argument @Valid wasn't yet added for composed models. It is now. For example, a List<ShiftRawId> query parameter generates:
@NotNull @RequestParam(value = "accountIds", required = true) List<@Valid ShiftRawId> accountIdsCould you re-test on the latest commit? For List<String> (the status example in this hunk) there's intentionally no @Valid, since String isn't a cascade target.
Fixes Hibernate Validator HV000271 ("Using
@Validon a container is deprecated. You should apply the annotation on the type argument(s)") across the Java generator family. HV 9.1+ (bundled with Spring Boot 4) logs this at WARN for every@Valid-annotatedList/Set/Map— on both model properties and API parameters.The fix relocates
@Validfrom the container to its type argument — the Bean-Validation-2.0 form (List<@Valid T>,Map<String, @Valid V>) — which cascades identically but is not deprecated. Backward-compatible: element validation is preserved, never dropped.Scope (Java family):
spring,javaclient, JAX-RS (jersey,resteasy(+eap),cxf(+extended/cdi),spec),java-camel.@Validis moved to the type argument. Map values are gated behind a newAbstractJavaCodegen#useBeanValidationOnMapValueType()(defaultfalse; overriddentruein Spring/JavaClient/JAX-RS) so untouched generators don't silently gain map-value validation. Arrays/sets already injected the type-argument form.@RequestBody/@RequestParam/@RequestPart): the redundant container-level@Validis dropped for container parameters; element validation is driven by the type-argument@Valid. Single-object parameters keep their@Valid. ReactiveMono/Fluxbodies are intentionally untouched — they are not Jakarta containers and do not trigger HV000271.The
microprofileclientbodyParamschange is a consistency change with no sample impact (those samples don't enable bean validation).Tests: added
SpringCodegenTest#beanValidationOnContainerTypeArgument_issue23614and#beanValidationOnContainerParameter_issue23614,JavaClientCodegenTest#testBeanValidationOnContainerTypeArgument_issue23614, updatedJavaJAXRSSpecServerCodegenTest; the reactive test now also asserts the parameter-level@Validis retained.Fixes #23614
PR checklist
Commit all changed files.
This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
These must match the expectations made by your contribution.
You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example
./bin/generate-samples.sh bin/configs/java*.IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
Summary by cubic
Stops Hibernate Validator HV000271 by moving bean validation from containers to their type arguments without changing cascade behavior. Old:
@ValidonList/Set/Mapcontainers. New:List<@Valid T>,Map<String, @Valid V>. Single-object parameters stay@Valid; reactiveMono/Fluxkeep parameter-level@Valid.@Valid; place it on array/set elements and composed-schema (oneOf/anyOf/allOf) elements except enums. Map values use type-argument validation gated byAbstractJavaCodegen#useBeanValidationOnMapValueType()(default false; overridden true inSpringCodegen,JavaClientCodegen,AbstractJavaJAXRSServerCodegen).@Validon@RequestBody,@RequestParam,@RequestPartfor containers, and onOptional-wrapped scalars; keep for other non-containers. Reactive bodies retain parameter-level@Validand add type-argument validation insideMono/Flux.@Valid, verified on Spring Boot 3.3 and 4.1.java-camel, andmicroprofiletemplates; added/updated tests and regenerated samples.Written for commit 3bfada1. Summary will update on new commits.