0

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?

Leonardo
  • 1,263
  • 7
  • 20
  • 51

1 Answers1

0

As I can see on the example above, you added two constraint violation message but in the different if cases. For a getting several checks and violation messages from one validator you should have not placed return after each if cases, instead of this you can create a local boolean variable and set its value from each of if statement cases, and after all make return that variable.

Pay attention to a little thing: it is important for your validator to set a temporary boolean variable correctly, because if once your if was set into false that means ultimate return value should be false. Cuz there is a principle anyMatch(false) or allMatch(true)

Dmitrii B
  • 2,672
  • 3
  • 5
  • 14
  • Thanks Dimitri, I created a boolean variable and return it according to each validation but still keeps printing the original message from `MyAnnotation.value`. According to the exception detail, it does not map the message code from validation, even when I force the correct "placeholder" (`MyAnnotation.conditionOne`). – Leonardo Aug 31 '22 at 06:34