Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 847
Sachin Avatar asked Apr 26 '19 15:04

Sachin


People also ask

What are requirements for a data class in Kotlin?

There are following conditions for a Kotlin class to be defined as a Data Class: The primary constructor needs to have at least one parameter. All primary constructor parameters need to be marked as val or var. Data classes cannot be abstract, open, sealed, or inner.

Can Kotlin data classes have functions?

The data class in Kotlin is used to hold the data. This data class contains some utility functions that are often derivable from the data. With the help of the data class, you don't need to write the boiler plate code. The compiler automatically generates all the getter and setter for all the data class properties.


1 Answers

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

See for details:

  • https://discuss.kotlinlang.org/t/i-have-a-question-about-applying-bean-validation-2-0/5394
  • Kotlin data class and bean validation with container element constraints

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

  • https://youtrack.jetbrains.net/issue/KT-26605
  • https://youtrack.jetbrains.net/issue/KT-13228

The latter has target version 1.4.

like image 132
Mathias Dpunkt Avatar answered Sep 20 '22 16:09

Mathias Dpunkt