Martin Erlic
Martin Erlic

Reputation: 5667

Springboot form validation for ensuring one date does not come before another?

After following this guide: https://spring.io/guides/gs/validating-form-input/, I want to do form validation that checks if the dateTo value comes before the dateFrom value. It would be awesome if there were some kind of annotation solution. They are stored as strings in the empty model supplied by my form.

@NotNull(message="You must select a date.")
@NotBlank(message="You must select a date.")
private String dateFrom;

@Min(dateFrom)
private String dateTo;

Obviously this doesn't work because we can't compare whether one String is smaller than the other... Is there an alternative? The problem is that I want to provide a message in the UI right from the form validation check, just like how I can check if the message is null or blank.

    // Create Request
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    String saveRequest(Principal principal, @Valid @ModelAttribute(value = "requestModel") RequestModel requestModel, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
    ....
    if (bindingResult.hasErrors()) {
        // log.info("There are binding errors.");
        return "send";
    }
    ....

    // Format given date
    Date dateFrom = null;
    try {
        SimpleDateFormat formatter = new SimpleDateFormat(DateUtil.dateFormat);
        dateFrom = formatter.parse(requestModel.getDateFrom());
    } catch (ParseException e) {
        e.printStackTrace();
        return "send";
    }

    try {
        if (requestModel.getDateTo() != null && !(requestModel.getDateTo().isEmpty())) {
            SimpleDateFormat formatter = new SimpleDateFormat(DateUtil.dateFormat);
            Date dateTo = formatter.parse(requestModel.getDateTo());

            // Check if dateTo is before dateFrom
            if (!dateTo.before(dateFrom)) {
                // If not (proper case), set the date
                requestDOOb.setDateTo(dateTo);
            } else {
                // Improper case, log error
                //TODO Update UI?
                log.info("dateTo cannot come before dateFrom");
                return "send";
            }

        } else {
            requestDOOb.setDateTo(dateFrom);
        }
    } catch (ParseException e) {
        e.printStackTrace();
        return "send";
    }

I don't want to have to perform the validation in the POST method itself...

Update:

@AssertTrue(message="The end date cannot come before the initial date.")
private boolean isValid() {
    return !dateTo.before(dateFrom) && this.dateFrom.before(this.dateTo);
}

public Date getDateFrom() {
    return dateFrom;
}

public void setDateFrom(Date dateFrom) {
    this.dateFrom = dateFrom;
}

public Date getDateTo() {
    return dateTo;
}

public void setDateTo(Date dateTo) {
    this.dateTo = dateTo;
}

What about something like the above?

Upvotes: 4

Views: 9533

Answers (1)

Dirk Lachowski
Dirk Lachowski

Reputation: 3151

You could create your own validator/validation annotation (see https://docs.jboss.org/hibernate/validator/5.0/reference/en-US/html/chapter-bean-constraints.html#d0e371 )

Annotation:

@Target({ElementType.TYPE}) 
@Retention(RetentionPolicy.RUNTIME) 
@Constraint(validatedBy=YourDateValidator.class) 
public @interface ValidDates {
    String message() default "{message.id}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

Validator:

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class YourDateValidator implements ConstraintValidator< ValidDates, 
    TypeToBeValidated> {

    @Override
    public void initialize(ValidDates constraintAnnotation) {
    }

    @Override
    public boolean isValid(TypeToBeValidated value, ConstraintValidatorContext context) 
    {
        < validation code, returning true for a valid value >
    }

}

Usage:

@ValidDates
class TypeToBeValidated {
    private String dateFrom;
    private String dateTo;
}

Upvotes: 5

Related Questions