I have a Spring Boot project in Kotlin which uses a custom locale interceptor to know from which .properties file it load messages.
This works pretty fine. Also I have a custom annotation which is simple and has a default message value, as follow:
@Target(AnnotationTarget.Field)
@Constraint(validatedBy = [MyCustomValidator::class])
annotation class MyAnnotation(
val message: String = "{javax.validation.constraints.MyAnnotation.message}",
val groups: Array<KClass<*>> = [],
val payload: Array<KClass<out Payload>> = []
)
class MyCustomValidator : ConstraintValidator<MyAnnotation, String> {
override fun isValid(value: String, context: ConstraintValidatorContext) {
return true //Just to make it easy
}
}
The locale properties files contains the key MyAnnotation.value=This field is required and shows as the exception message.
The problem is when I want to add more validations and so, custom messages according to each condition. I read that I should disable the default constraint validator and add the messages, but it is not working.
For example, if I want to create a key at locale file as MyAnnotation.conditionOne, it still prints the message from MyAnnotation.value.
//The only thing that changes in MyAnnotation is that message: String = ""
//Assuming that ConditionOne and ConditionTwo has a isValid static method
class MyCustomValidator : ConstraintValidator<MyAnnotation, String> {
override fun isValid(value: String, context: ConstraintValidatorContext): Boolean {
context.disableDefaultConstraintViolation()
return if (!ConditionOne.isValid(value)) {
context
.buildConstraintViolationWithTemplate("{javax.validation.constraints.MyAnnotation.conditionOne}")
.addConstraintViolation()
false
}
else if (!ConditonTwo.isValid(value)) {
context
.buildConstraintViolationWithTemplate("{javax.validation.constraints.MyAnnotation.message}")
.addConstraintViolation()
false
}
else
true
}
}
Is this the right way to set the message?
As I can see on the example above, you added two constraint violation message but in the different
ifcases. For a getting several checks and violation messages from one validator you should have not placedreturnafter eachifcases, instead of this you can create a local boolean variable and set its value from each ofifstatement cases, and after all makereturnthat variable.Pay attention to a little thing: it is important for your validator to set a temporary boolean variable correctly, because if once your
ifwas set intofalsethat means ultimate return value should befalse. Cuz there is a principleanyMatch(false)orallMatch(true)