Skip to content

[BUG][KOTLIN-SPRING] @field:Valid on container properties triggers HV000271/HV000272 warnings (Hibernate Validator 9.1) #25347

Open

Description

@vklidu

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
Description

With useBeanValidation (default for kotlin-spring), beanValidation.mustache puts @field:Valid on container properties (List, Set, Map) and on free-form kotlin.Any properties.

Hibernate Validator 9.1 (shipped with Spring Boot 4.1) deprecated container-level @Valid and logs a warning while building bean metadata:

WARN org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder - HV000271: Using `@Valid` on a container (java.util.List) is deprecated. You should apply the annotation on the type argument(s). Affected element: items
WARN org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder - HV000272: Using `@Valid` on a container is deprecated. You should apply the annotation on the type argument(s). (java.lang.Object) can potentially be a container at runtime. Affected element: customInfo

Because the bean metadata cache in Hibernate Validator uses soft references, the warnings are not logged only once at startup - they are repeated each time the metadata of a rarely used model is evicted and rebuilt, which produces a steady stream of warnings in production logs.

The same problem was fixed for the Java generators in #24176 (released in 7.26.0, issue #23614) by moving @Valid to the type argument. The kotlin-spring templates were not touched. An attempt for Kotlin (#24027 / #24029) only removed @field:Valid from Map properties and was closed, because that silently drops cascading validation of the values.

Actual output

data class Pet(
    @field:Valid
    @get:JsonProperty("items") val items: kotlin.collections.List<Item>? = null,

    @field:Valid
    @get:JsonProperty("itemsByKey") val itemsByKey: kotlin.collections.Map<kotlin.String, Item>? = null,

    @field:Valid
    @get:JsonProperty("customInfo") val customInfo: kotlin.Any? = null
)

Expected output

data class Pet(
    @get:JsonProperty("items") val items: kotlin.collections.List<@Valid Item>? = null,

    @get:JsonProperty("itemsByKey") val itemsByKey: kotlin.collections.Map<kotlin.String, @Valid Item>? = null,

    @get:JsonProperty("customInfo") val customInfo: kotlin.Any? = null
)

Important note for Kotlin: the Kotlin compiler does not write type-use annotations into the bytecode by default, so List<@Valid Item> alone is invisible to Hibernate Validator (cascading would silently stop working). It works only when the models are compiled with -Xemit-jvm-type-annotations (verified with Kotlin 2.3.21: without the flag there is no RuntimeVisibleTypeAnnotations attribute, with it cascading into list elements and map values works and no HV000271 is logged). The generator should therefore at least document this flag, or add it to the generated build.gradle.kts / pom.xml when useBeanValidation is enabled.

openapi-generator version

7.17.0 (the relevant kotlin-spring templates are unchanged in 7.26.0). Not a regression in the generator - it surfaced with Hibernate Validator 9.1.0.Final.

OpenAPI declaration file content or url
openapi: 3.0.3
info:
  title: valid-on-container
  version: 1.0.0
paths: {}
components:
  schemas:
    Pet:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/Item'
        itemsByKey:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/Item'
        customInfo:
          type: object
    Item:
      type: object
      required:
        - name
      properties:
        name:
          type: string
          minLength: 1
Generation Details

Gradle plugin org.openapi.generator 7.17.0:

openApiGenerate {
  generatorName.set("kotlin-spring")
  configOptions.put("useSpringBoot3", "true")
  configOptions.put("interfaceOnly", "true")
}
Steps to reproduce
  1. Generate the models from the spec above with kotlin-spring.
  2. Validate a Pet instance with Hibernate Validator 9.1 (e.g. Validation.buildDefaultValidatorFactory().validator.validate(Pet(items = listOf(Item(name = ""))))).
  3. HV000271 (for items, itemsByKey) and HV000272 (for customInfo) warnings are logged.
Related issues/PRs
Suggest a fix

In kotlin-spring (beanValidation.mustache + dataClassReqVar.mustache / dataClassOptVar.mustache, and the interface var templates):

  • do not emit @field:Valid for containers; render the type as List<@Valid T> / Set<@Valid T> / Map<String, @Valid V> instead,
  • do not emit @field:Valid for free-form kotlin.Any properties,
  • document (or emit into the generated build file) the -Xemit-jvm-type-annotations compiler option required for the type-use annotations to be visible at runtime.

As a workaround we currently post-process the generated sources after openApiGenerate (moving @field:Valid to the type argument with a regex) and compile the models with -Xemit-jvm-type-annotations.

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