javaspring-bootrestvalidation

Spring Boot request body validation


I am working on Spring REST API and have following controller:

@RestController
@RequestMapping(
        value = "/api/Test",
        produces = "application/json"
)
public class MyController {

    @RequestMapping(method = RequestMethod.POST)
    public Response serviceRequest(@Valid @RequestBody ServiceRequest myServiceRequest)  {    
             ....    
    }
}

ServiceRequest has following structure:

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class ServiceRequest {

    @NotBlank
    private LocalDate fromDate;

    @NotBlank
    private LocalDate toDate;

}

My task is to introduce validation based on combination of fromDate and toDate field's values: if time period between them is longer that 1 week then validation should fail.

What is the best way to archive this please?


Solution

  • You may create a custom constraint validator that will validate the required conditions before processing the request.

    DatesDifference.java

    @Constraint(validatedBy = DatesDifferenceValidator.class)
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DatesDifference {
        String message() default "Dates difference is more than a week";
        Class<?>[] groups() default { };
        Class<? extends Payload>[] payload() default { };
    }
    

    DatesDifferenceValidator.java

    @Component
    public class DatesDifferenceValidator implements ConstraintValidator<DatesDifference, ServiceRequest> {
        
        @Override
        public boolean isValid(ServiceRequest serviceRequest, ConstraintValidatorContext context) {
            System.out.println("validation...");
            if (!(serviceRequest instanceof ServiceRequest)) {
                throw new IllegalArgumentException("@DatesDifference only applies to ServiceRequest");
            }
            LocalDate from = serviceRequest.getFromDate();
            LocalDate to = serviceRequest.getToDate();
    
            long daysBetween = ChronoUnit.DAYS.between(from, to);
            System.out.println("daysBetween "+daysBetween);
            return daysBetween <= 7;
        }
    }
    

    ServiceRequest.java

    @Getter
    @Setter
    @AllArgsConstructor
    @NoArgsConstructor
    @DatesDifference
    public class ServiceRequest {
        @NotBlank
        private LocalDate fromDate;
    
        @NotBlank
        private LocalDate toDate;
    }