Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot override ConstraintValidator default message in Spring-MVC

I am having issues with overriding the default ConstraintValidator message when using Spring validation.

I have a custom messages.properties file that contains the following values:

NotNull=This field is mandatory
BankHoliday=You cannot select a bank holiday

My annotation for BankHoliday is as follows:

@Documented
@Constraint(validatedBy = BankHolidayValidator.class)
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BankHoliday {

    String message() default "{BankHoliday}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

My validator is as follows:

public class BankHolidayValidator implements ConstraintValidator<BankHoliday, Date> {

@Override
public void initialize(BankHoliday bankHoliday) { }

@Override
public boolean isValid(Date date, ConstraintValidatorContext cxt) {

    if(date == null) {
        cxt.disableDefaultConstraintViolation();
        cxt.buildConstraintViolationWithTemplate("{NotNull}").addConstraintViolation();
        return false;
    } else if (isBankHoliday(date)) {
        return false;
    } else {
        return true;
    }
}

}

My model is annotated with the @BankHoliday annotation:

@BankHoliday
@DateTimeFormat(pattern = "dd/MM/yy")
private Date desiredBookingDate;

My controller looks like:

@RequestMapping(value="/new/request", method = RequestMethod.POST)
public String putNewRequest(@Valid @ModelAttribute("request") Request request, BindingResult bindingResult, Map<String, Object> map) {

    if (bindingResult.hasErrors()) {

        // return them back

    } else {

        // process the request
    }
}

However, when the user does not populate this field, the error message they see is "You cannot select a bank holiday" instead of "This field is mandatory". Having stepped through the code I can see that the cxt.disableDefaultConstraintViolation() line is definitely being called and the {NotNull} constraint validation is being added, but the user always sees the default message.

I have tried replacing "{NotNull}" with "A test message" and this does not work either. Can anyone point me in the right direction as to why this isn't working?

like image 598
smilin_stan Avatar asked Sep 17 '25 03:09

smilin_stan


2 Answers

I've looked into my own code (which is working) and only one difference is that you didn't invoke addNode() method, so I suggest to invoke it:

cxt.disableDefaultConstraintViolation();
cxt.buildConstraintViolationWithTemplate("{NotNull}")
   .addNode("desiredBookingDate")
   .addConstraintViolation();

But, IMHO, you are going to wrong direction: validator should be responsible only for one type of validation. To mark field as mandatory it's better to use @NotNull annotation instead. You, probably, will face up with another issue: empty string will always pass such constraint. And to fix that, in Spring, you should use StringTrimmerEditor with emptyAsNull = true parameter which turns empty string to null value before validation.

like image 97
Slava Semushin Avatar answered Sep 19 '25 16:09

Slava Semushin


A bit late probably.. but I'll post my answer for others..

Apparently it has something to do with the name of the default message constant.

{BankHoliday} could be replaced with {bank.holiday} (or any other key) and it will work.

Of course.. rename the message key in the properties file as well.. It doesn't like the messages which have exact name as the interface itself.

like image 35
Alex Bondor Avatar answered Sep 19 '25 18:09

Alex Bondor