Spring and Spring Boot are what I would call “kotlin-friendly” frameworks. However, the beans validation aspect specifically just doesn’t play nice with kotlin. Here’s why.
Let’s assume the following data class:
data class UserDTO(
@jakarta.validation.constraints.Size(max = 10)
val username: String
)
… and the following REST controller:
@RestController
class UserRestController {
@PostMapping("/users")
@ResponseBody
fun saveUser(@RequestBody @jakarta.validation.Valid userDTO: UserDTO): Int {
return 0 // doesn't matter
}
}
Let’s post some data to this endpoint:
{
"username": "1234567890ABC"
}
Now, given the @Size
annotation on the username
property, I would assume that the request would fail due to the username being too long. The validation should kick in, throwing an appropriate exception, the client should receive some 4xx HTTP response code. But that doesn’t happen.
Instead, the request above is accepted by the server and the validation is ignored.
After some investigation (because debugging runtime annotation processors is always fun, right?) it turns out that the Kotlin compiler takes the @Size
annotation and places it on the constructor parameter. The beans validation API doesn’t find it there. From the point of view of the beans validation API, there is no annotation.
The way to fix this is to change the @Size
to @field:Size
to force the kotlin compiler to put the annotation on the field.
This may seem like a minor thing. But it’s something we as developers constantly have to keep in mind. It’s not just syntactically unpleasant. If you don’t know about this issue, you’ll not even think about this, and then you’re hit with the big surprise that your validation doesn’t work. And the original code totally looks like it should work.
Ways I see to fix this:
- The kotlin spring compiler plugin could relocate the annotations of the bean validation package to the fields instead of the constructor parameter.
- The beans validation API spec could be changed to check for constructor parameter annotations as well.
- The beans validation API may provide a plug-in mechanism that allows us to have a Beans-Validation-Kotlin addon that finds the annotations on the primary constructor arguments.
- Somebody goes ahead and implements the beans validation API from scratch, in Kotlin, for Kotlin projects.
I tried to report this on the Kotlin YouTrack but it was quickly dismissed without further consideration.
Did anybody else get hit by this?