fix(java): place bean-validation @Valid on the type argument instead of the container (HV000271)

Merged
TW
1mo ago
+2632-1780

Fixes Hibernate Validator HV000271 ("Using @Valid on 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-annotated List/Set/Map — on both model properties and API parameters.

The fix 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.

Scope (Java family): spring, java client, JAX-RS (jersey, resteasy(+eap), cxf(+extended/cdi), spec), java-camel.

  • 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.
  • 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 their @Valid. Reactive Mono/Flux bodies are intentionally untouched — they are not Jakarta containers and do not trigger HV000271.

The microprofile client bodyParams change is a consistency change with no sample impact (those samples don't enable bean validation).

Tests: added SpringCodegenTest#beanValidationOnContainerTypeArgument_issue23614 and #beanValidationOnContainerParameter_issue23614, JavaClientCodegenTest#testBeanValidationOnContainerTypeArgument_issue23614, updated JavaJAXRSSpecServerCodegenTest; the reactive test now also asserts the parameter-level @Valid is retained.

Fixes #23614

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    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.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.
    • Java: @bbdouglas @sreeshas @jfiala @lukoyanov @cbornet @jeff9finger @karismann @Zomzog @lwlee2608 @martin-mfg
    • Java Spring: @cachescrubber @welshm @MelleD @atextor @manedev79 @javisst @borsch @banlevente

Summary by cubic

Fixes Hibernate Validator HV000271 by moving @Valid from containers to their type arguments across the Java generator family (spring, java client, JAX-RS, java-camel), so generated code no longer logs the deprecated container-level @Valid warning while preserving element cascade behavior.

Models

  • Element @Valid moves from the container to array/set and composed-schema (oneOf/anyOf/allOf) type arguments, except enums.
  • Map values use type-argument validation, gated by AbstractJavaCodegen#useBeanValidationOnMapValueType() and enabled in SpringCodegen, JavaClientCodegen, and AbstractJavaJAXRSServerCodegen.

Parameters

  • @RequestBody, @RequestParam, and @RequestPart drop the container-level @Valid; single-object and reactive Mono/Flux parameters keep it, and Optional-wrapped scalars drop it.