Search code examples
validationkotlin

How do we do kotlin data class validation on Collection?


I am trying to add validation to my data models in kotlin, The simple fields are easy to do using the @field annotations. But, I am struggling to do the same with collections.

I have uploaded the issue to github here

The java model is working with no issues but the kotlin version is not. I am adding both the models here.

public class JavaUser {
    @NotEmpty
    @NotNull
    @Pattern(regexp = "[a-z]*", message = "Only lower case first name")
    private String name;

    private List<
            @NotNull
            @NotEmpty
            @Pattern(regexp = "\\d{10}", message = "Only 10 digits")
                    String> phones;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<String> getPhones() {
        return phones;
    }

    public void setPhones(List<String> phones) {
        this.phones = phones;
    }
}
data class KotlinUser(
    @field:NotEmpty
    @field:NotNull
    @field:Pattern(regexp = "[a-z]*", message = "Only lower case first name")
    val name: String,

    // Cannot use @field here, anything else we could use?
    val phones: List<
        @NotNull
        @NotEmpty
        @Pattern(regexp = "\\d{10}", message = "Only 10 digits")
        String>
)

My tests - The java test passes but the kotlin one fails

    @Test
    fun `java user validation`() {
        val javaUser = JavaUser()
        javaUser.name = "sadfjsjdfhsjdf"
        javaUser.phones = listOf("dfhgd")

        webTestClient.put().uri("/user/java")
            .body(BodyInserters.fromObject(javaUser))
            .exchange()
            .expectStatus().is4xxClientError
    }

    @Test
    fun `kotlin user validation`() {
        val kotlinUser = KotlinUser(name = "sadfjsjdfhsjdf", phones = listOf("dfhgd"))

        webTestClient.put().uri("/user/kotlin")
            .body(BodyInserters.fromObject(kotlinUser))
            .exchange()
            .expectStatus().is4xxClientError
    }

Controller

@RestController
class Controller {
    @PutMapping("/user/java")
    fun putUser(@RequestBody @Valid javaUser: JavaUser): Mono<ResponseEntity<String>> =
        Mono.just(ResponseEntity("shouldn't get this", HttpStatus.OK))

    @PutMapping("/user/kotlin")
    fun putUser(@RequestBody @Valid kotlinUser: KotlinUser): Mono<ResponseEntity<String>> =
        Mono.just(ResponseEntity("shouldn't get this", HttpStatus.OK))
}

Any help would be greatly appreciated. Thank you!


Solution

  • This is currently not supported. The Kotlin compiler currently ignores annotations on types.

    See for details:

    There are also issues on the Kotlin issue tracker for this:

    The latter has target version 1.4.