Artur Muszyński
Artur Muszyński

Reputation: 31

How to combine several annotation into one in Kotlin?

I'm trying to validate RequestBody using my custom annotations.

With configuration below my validation works:

data class PlayerRegistration(
    @field: Email
    val email: String,
    @field: Pattern(regexp = NICK_REGEX)
    @field: Size(min = 5, max = 15)
    val nick: String,
    @field: Pattern(regexp = PASSWORD_REGEX)
    @field: Size(min = 8, max = 20)
    val password: String,
    val birthDate: LocalDate
)

But when I try to sum up annotations like this:

data class PlayerRegistration(
    @field: Email
    val email: String,
    @field: ValidNick
    val nick: String,
    @field: ValidPassword
    val password: String,
    val birthDate: LocalDate
)

@Pattern(regexp = NICK_REGEX)
@Size(min = 5, max = 15)
@Target(AnnotationTarget.FIELD)
private annotation class ValidNick

@Pattern(regexp = EMAIL_REGEX)
@Size(min = 8, max = 20)
@Target(AnnotationTarget.FIELD)
private annotation class ValidPassword

It doesn't work. What am I doing wrong?

Upvotes: 2

Views: 4426

Answers (1)

PiotrK
PiotrK

Reputation: 1552

In short: your approach creates annotations that have annotations - two levels of nesting. It's not a mechanism to group annotations.

Try to think like an annotation processor. In the first code snippet, the processor sees a field nick and thinks "OK, I know how to apply Pattern and Size to a field".

In the second code snippet, for the field nick it sees ValidNick and thinks "I don't know this type of annotation, and I don't know how to treat it as a field constraint". The processor would have to know that it has to go to this annotation's annotations, and that's - I believe - is not supported out of the box.

If I were you, I wouldn't push towards such code structure. IMO it decreases the readability because in order to know nick's constraints, you have to go to some other part of the code. In theory it would be reusable, but the question is: how many reuses you would have?

If you really want to achieve something similar, instead of annotations, I'd give delegated properties a try. They let you intercept the setter, and keep such interception logic as a reusable class

Upvotes: 1

Related Questions