Spring Kotlin Validation(JSR380)

DoggyFootGuy
2 min readSep 26, 2019

When i start to write DTO class with Kotlin, first thing what i wished to work is something like this,

@GetMapping(value = ["/search/users"])
fun searchUsers(@Valid searchRequest: UserSearchRequest): Flux<User{
//TODO search Users
}
data class UserSearchRequest(
@NotNull
val active: Boolean,

@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
@NotNull
val registeredDate: LocalDate,

val names: List<@NotEmpty String>
)

and i ran the test to verify validation,

@Test
fun searchUsers() {
webTestClient.get().uri("/search/users").exchange()
.expectStatus().isBadRequest
}

BadRequest is expected since first ‘active’ is not set and Spring(Boot) will translate validation exception to BadRequest for me, However, wha i got is InternalServerError by ConversionFailedException since request was not validated. That is because NotNull annotation never been applied properly as you can see from Kotlin byte code,

public final class com/rakuten/travel/montblanc/search/provider/web/UserSearchRequest {// access flags 0x12
private final Z active
}

thats because Kotlin will apply annotations on constructors not on fields or getters, so you need to specify target of that annotation, as soon as you add ‘@field’, i could see annotation applied right and again expected to be working!

public final class com/rakuten/travel/montblanc/search/provider/web/UserSearchRequest {// access flags 0x12
private final Z active
@Ljavax/validation/constraints/NotNull;()
}

But again InternalServerError by ConversionFailedException, why? can i could not find the reason yet so far, However, it finally worked when i put nullable on field

data class UserSearchRequest(
@field:NotNull
val active: Boolean?,
// no targeting work
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
@field:NotNull
val registeredDate: LocalDate,

val names: List<@NotEmpty String> // does not work
)

reason for that please refer from here.

Interesting thing is for the “@DateTimeFormat” annotation, with targeting does not work but without …. and validation annotation on List generic type also does not work!, maybe writing DTOs into Java is better for the sake of life.

--

--