Uploaded image for project: 'Spring Framework'
  1. Spring Framework
  2. SPR-16701

Improve Kotlin + bean validation documentation

    XMLWordPrintable

    Details

    • Type: Task
    • Status: Closed
    • Priority: Minor
    • Resolution: Complete
    • Affects Version/s: 5.0.5
    • Fix Version/s: 5.0.6, 5.1 RC1
    • Component/s: Web
    • Labels:

      Description

      GitHub example project with tests
      Stackoverflow question

      When I define a class implementing CustomValidator and it uses an annotation, for example ValidateRoles, which is defined in Kotlin, then the field validation with this annotation doesn't work. Whereas when I define the same annotation in Java the field is validated correctly.

      Consider these 2 the same annotations. One is in Java and one is in Kotlin.

      @Constraint(validatedBy = RolesValidatorJava.class)
      @Retention(RetentionPolicy.RUNTIME)
      @Target({ElementType.FIELD})
      public @interface ValidateRolesJava {
          String message() default "{com.example.demo.validators.ValidateRolesJava.message}";
      
          Class[] groups() default {};
      
          Class[] payload() default {};
      }
      
      @Constraint(validatedBy = arrayOf(RolesValidatorKotlin::class))
      @Retention(AnnotationRetention.RUNTIME)
      @Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY)
      annotation class ValidateRolesKotlin(
          val message: String = "{com.example.demo.validators.ValidateRolesKotlin.message}",
          val groups: Array<KClass<*>> = arrayOf(),
          val payload: Array<KClass<*>> = arrayOf()
      )
      

      Consider 2 Validators one for each Annotation, each returning false upon validation

      public class RolesValidatorJava implements ConstraintValidator<ValidateRolesJava, Collection<String>> {
          @Override
          public boolean isValid(Collection<String> value, ConstraintValidatorContext context) {
              return false;
          }
      }
      
      class RolesValidatorKotlin : ConstraintValidator<ValidateRolesKotlin, Collection<String>> {
          override fun isValid(value: Collection<String>?, context: ConstraintValidatorContext?): Boolean {
              return false
          }
      }
      

      Now we have 2 the same request bodies, but with different annotations

      class JavaBodyDTO {
          @NotNull
          @ValidateRolesJava
          var roles: Set<String> = emptySet()
      }
      
      class KotlinBodyDTO {
          @NotNull
          @ValidateRolesKotlin
          var roles: Set<String> = emptySet()
      }
      

      Each response should return 400

      @PostMapping("/updateRolesJava")
      fun updateRolesJava(@RequestBody @Valid body: JavaBodyDTO): ResponseEntity<Void> {
          // this should never reach because validator invalidates body
          return ResponseEntity(HttpStatus.OK)
      }
      
      @PostMapping("/updateRolesKotlin")
      fun updateRolesKotlin(@RequestBody @Valid body: KotlinBodyDTO): ResponseEntity<Void> {
          // this should never reach because validator invalidates body, but the validation doesn't work
          return ResponseEntity(HttpStatus.OK)
      }
      

        Attachments

          Activity

            People

            Assignee:
            sdeleuze S├ębastien Deleuze
            Reporter:
            Humberd Maciej Sawicki
            Last updater:
            Spring Issues Spring Issues
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved:
              Days since last comment:
              3 years, 19 weeks, 5 days ago