Configuring Spring to validate constructor parameters of Kotlin data classes


#1

By default @Valid annotation on constructor arguments tells Spring to validate object fields. But Kotlin places constraint annotations on the constructor parameters, so validation doesn’t work. To make it work I have to define use-site targets for annotations:

data class Credentials(@field:Email @field:NotBlank val email: String, @field:NotBlank val password: String)

which is annoying and adds visual garbage. Is it possible to configure Spring to validate constructor parameters?


#2

The problem is that Kotlin code has to compile to JVM class bytecode. The inline constructor is just a syntactic sugar which results in a constructor, getters and setters being generated in the .class file.
So the above is just the idiomatic Kotlin way of going around this.

As per Kotlin docs:

If you don’t specify a use-site target, the target is chosen according to the @Target annotation of the annotation being used. If there are multiple applicable targets, the first applicable target from the following list is used:

  1. param;
  2. property;
  3. field

One possible way of cleaning this up is to declare your own annotations which have @Target(FIELD) only. This way the compiler will infer the target accordingly:

@Target(AnnotationTarget.FIELD)
@Retention(AnnotationRetention.RUNTIME)
@Constraint(validatedBy = arrayOf())
@NotBlank
@Email
annotation class ValidEmail constructor(
        val message: String = "ignored message",
        val groups: Array<KClass<*>> = [],
        val payload: Array<KClass<out Payload>> = []
)

then

data class Credentials(@ValidEmail val email: String, ...

One advantage of doing this is that you can combine multiple standard JSR-303 constraints into a single domain-specific annotation (as in the email example above, although @Email already implies @NotBlank so not the best illustration)