Blog top image

Kotlin Custom annotation


I was working a simple spring boot with Kotlin project and needed password and confirm password matching validation. So, I  developed a custom validator with Kotlin. 


Validator annotation and its implementation

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@Constraint(validatedBy = [PasswordMatchingValidator::class])
annotation class PasswordMatching(

val password: String,
val confirmPassword: String,
val message: String = "The password and confirm password do not match",
val groups: Array<KClass<Any>> = [],
val payload: Array<KClass<Payload>> = [],
)

class PasswordMatchingValidator : ConstraintValidator<PasswordMatching, Any> {
private var password = ""
private var confirmPassword = ""

override fun initialize(constraintAnnotation: PasswordMatching) {
password = constraintAnnotation.password
confirmPassword = constraintAnnotation.confirmPassword
}

override fun isValid(value: Any, context: ConstraintValidatorContext): Boolean {
val password = BeanWrapperImpl(value).getPropertyValue(password) as String
val confirmPassword = BeanWrapperImpl(value).getPropertyValue(confirmPassword) as String
return password == confirmPassword
}
}


Use of the custom validator

@PasswordMatching(
password = "password",
confirmPassword = "confirmPassword",
message = "The password and confirm password do not match")
data class RegistrationRequest(
@field:Email(message = "Valid email is required")
@field:NotBlank(message = "Email is required")
val email: String,

@field:NotBlank(message = "Password is required")
@field:Size(min = 6, message = "Password must be at least 6 characters long")
val password: String,

@field:NotBlank(message = "Confirm password is required")
@field:Size(min = 6, message = "Confirm password must be at least 6 characters long")
val confirmPassword: String,

@field:NotNull(message = "At least one role is required")
val roles: Set<Role>
)


 
Unit test for the validator

@Test
fun `test registration password and confirm password not match`() {
val registrationRequest = RegistrationRequest("test@gmail.com", "654321", "123456", setOf(Role.ROLE_USER))
val constraintValidations = validatorFactory.validator.validate(registrationRequest)

assertThat(constraintValidations.size).isEqualTo(1)
assertThat(constraintValidations.map { it.message }
.contains("The password and confirm password do not match")).isTrue()
}