Skip to content

[REQ] Possibilty of annoted type arguments with bean Validation for Java Collections #23705

Description

@juniorjrjl

I need to annoted a type argument to apply bean validation for each Collection elements ( List, Set)

// constraint violation when some element is null
  @Valid
  private List<@jakarta.validation.constraints.NotNull Stubb> sample= new ArrayList<>();

but a property x-field-extra-annotation only mark a property. ex.:

// constraint violation when my list is null
  @Valid
  @jakarta.validation.constraints.NotNull
  private List<Stubb> sample = new ArrayList<>();

for solve a problem I think about create a new one ( ex.: x-inner-validation) for use like this:

        sample:
          type: array
          items:
            x-inner-validation: '@jakarta.validation.constraints.NotNull'
            allOf:
              - $ref: '#/components/schemas/Stubb'

I try to edit a pojo.mustache ( JavaSpring/Pojo.mustache) follow my attempt:

property:

{{#isContainer}}
  {{#useBeanValidation}}@Valid{{/useBeanValidation}}
  {{#openApiNullable}}
  private {{>nullableAnnotation}}{{#isNullable}}{{>nullableDataTypeBeanValidation}} {{name}} = JsonNullable.<{{{items.vendorExtensions.x-inner-validation}}}{{{datatypeWithEnum}}}>undefined();{{/isNullable}}{{^required}}{{^isNullable}}{{>nullableDataTypeBeanValidation}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};{{/isNullable}}{{/required}}{{#required}}{{^isNullable}}{{>nullableDataTypeBeanValidation}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};{{/isNullable}}{{/required}}
  {{/openApiNullable}}
  {{^openApiNullable}}
  private {{>nullableAnnotation}}{{#isSet}}Set{{/isSet}}{{^isSet}}List{{/isSet}}<{{{items.vendorExtensions.x-inner-validation}}} {{{items.datatypeWithEnum}}}> {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{^defaultValue}} = new {{#isSet}}LinkedHashSet{{/isSet}}{{^isSet}}ArrayList{{/isSet}}<>(){{/defaultValue}};
  {{/openApiNullable}}
  {{/isContainer}}
  {{^isContainer}}

getter:

  public {{>nullableAnnotation}}{{#isContainer}}{{#isSet}}Set{{/isSet}}{{^isSet}}List{{/isSet}}<{{{items.vendorExtensions.x-inner-validation}}} {{{items.datatypeWithEnum}}}>{{/isContainer}}{{^isContainer}}{{>nullableDataTypeBeanValidation}}{{/isContainer}} {{getter}}() {
  return {{name}};

setter

{{#jackson}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{>jackson_annotations}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{/jackson}}
  public void {{setter}}({{>nullableAnnotation}}{{#isContainer}}{{#isSet}}Set{{/isSet}}{{^isSet}}List{{/isSet}}<{{{items.vendorExtensions.x-inner-validation}}} {{{items.datatypeWithEnum}}}>{{/isContainer}}{{^isContainer}}{{>nullableDataType}}{{/isContainer}} {{name}}) {
  this.{{name}} = {{name}};

this config is breaking when I try to use a Set instead of List, but I paste here to try to help a develop a new config. Thank you

Activity

  1. added a commit that references this issue on May 6, 2026
    71ebeb2
  2. juniorjrjl commented on May 12, 2026

    @juniorjrjl
    Author

    Nice ! I think this issue could be usefull for another projects too. Any other projects how use Bean Validation. ex.: Kotlin and Spring, I don't know if have another options how use use Bean validation in another plugins.

    Sorry for say this just now, because I start tu use recently this project in my work and I don't know another modules

  3. lcf2014 commented on Jul 24, 2026

    @lcf2014

    Following issue

  4. jpfinne commented on Sep 29, 2026

    @jpfinne
    Contributor

    @juniorjrjl I have another option. See #25049

    I think the main goal is to generate @NotNull like in List<@NotNull String>.

    It can be done for all Lists with additionalItemsAnnotations=@NotNull. (there is already a import on jakarta.validation.constraints.* if BeanValidation is enabled)
    For a specific list, use the standard x-field-extra-annotation: @NotNull inside the items.

  5. juniorjrjl commented on Sep 29, 2026

    @juniorjrjl
    Author

    @jpfinne nice and thank you

  6. jpfinne commented on Sep 29, 2026

    @jpfinne
    Contributor

    @adraarda23 what do you think?

  7. adraarda23 commented on Oct 1, 2026

    @adraarda23

    @jpfinne
    Your approach is better than mine. Having it in AbstractJavaCodegen covers every Java generator, and reusing the existing x-field-extra-annotation is the easier path: a new extension would be one more thing to document, learn and maintain. Happy for #25049 to land; I'll close #23710.

    One thing I ran into while testing your branch.

    The item annotation is silently dropped when items is a plain $ref

    Take a request with two lists, where only one of them should reject null elements:

    CreateOrderRequest:
      type: object
      properties:
        lines:                 # null elements must be rejected
          type: array
          items:
            $ref: '#/components/schemas/OrderLine'
            x-field-extra-annotation: '@NotNull'
        notes:                 # null elements are fine here
          type: array
          items:
            $ref: '#/components/schemas/Note'

    OAS 3.0 ignores siblings of $ref, so the annotation never reaches the generator:

    private List<@Valid OrderLine> lines;   // @NotNull is missing
    private List<@Valid Note> notes;

    No annotation, no warning — the line is simply ignored.

    additionalItemsAnnotations=@NotNull does produce it, but it is a generator-wide
    flag, so it also lands on the list that should accept nulls:

    private List<@NotNull @Valid OrderLine> lines;   // wanted
    private List<@NotNull @Valid Note> notes;        // not wanted

    So there is no way to annotate one list: either every list gets it, or that schema
    has to be rewritten with the allOf wrapper from your listCode test.

    Is allOf the intended way here, or would it make sense to also read the extension from the array property level?

    One heads-up on that allOf route: it currently loses @Valid, so OrderLine's own constraints stop being validated. That's pre-existing — getBeanValidation() never looks at allOf, so items: allOf: [$ref] drops @Valid with or without your change. Not your PR's problem, but worth knowing since your PR makes allOf the route for $ref items. I'll file it separately and link it here.

  8. jpfinne commented on Oct 2, 2026

    @jpfinne
    Contributor

    @adraarda23 thanks for your review

    Indeed there is a limitation in the swagger parser, even for 3.1. See discussion in swagger-api/swagger-parser#798
    You need to add the annotation AND to convert to allOf. Two manual steps...

    I'll document it.

    Maybe the OpenApiNormalizer could use x-inner-validation and convert the $ref to an AllOf ?

  9. jpfinne commented on Oct 2, 2026

    @jpfinne
    Contributor

    @adraarda23 sample of a normalizer to move extensions from array to items.extensions.

    #25105
    What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions