Spring Boot : Custom Validation in Request Params

Case 1: If the annotation ValuesAllowed is not triggered at all, it could be because of not annotating the controller with @Validated.

@Validated
@ValuesAllowed(propName = "orderBy", values = { "OpportunityCount", "OpportunityPublishedCount", "ApplicationCount", "ApplicationsApprovedCount" })
public class OpportunityController {
@GetMapping("/vendors/list")
public String getVendorpage(@RequestParam(required = false) String term,..{
}

Case 2: If it is triggered and throwing an error, it could be because of the BeanUtils.getProperty not resolving the properties and throwing exceptions.

If the above solutions do not work, you can try moving the annotation to the method level and update the Validator to use the list of valid values for the OrderBy parameter. This worked for me. Below is the sample code.

@RestController
@RequestMapping("/api/opportunity")
@Validated
public class OpportunityController {
    @GetMapping("/vendors/list")
    public String getVendorpage(@RequestParam(required = false) String term,
            @RequestParam(required = false) Integer page, @RequestParam(required = false) Integer size,
            @ValuesAllowed(propName = "orderBy", values = { "OpportunityCount", "OpportunityPublishedCount", "ApplicationCount",
                    "ApplicationsApprovedCount" }) @RequestParam(required = false) String orderBy, @RequestParam(required = false) String sortDir) {
        return "success";
    }
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = { ValuesAllowed.Validator.class })
public @interface ValuesAllowed {

    String message() default "Field value should be from list of ";

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

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

    String propName();

    String[] values();

    class Validator implements ConstraintValidator<ValuesAllowed, String> {
        private String propName;
        private String message;
        private List<String> allowable;

        @Override
        public void initialize(ValuesAllowed requiredIfChecked) {
            this.propName = requiredIfChecked.propName();
            this.message = requiredIfChecked.message();
            this.allowable = Arrays.asList(requiredIfChecked.values());
        }

        public boolean isValid(String value, ConstraintValidatorContext context) {
            Boolean valid = value == null || this.allowable.contains(value);

            if (!valid) {
                context.disableDefaultConstraintViolation();
                context.buildConstraintViolationWithTemplate(message.concat(this.allowable.toString()))
                        .addPropertyNode(this.propName).addConstraintViolation();
            }
            return valid;
        }
    }
}

Leave a Comment