Can JSR 303 Bean Validation be used with Spring Data Rest?

后端 未结 4 1565
我寻月下人不归
我寻月下人不归 2020-12-14 10:12

I understand from the docs http://docs.spring.io/spring-data/rest/docs/2.1.2.RELEASE/reference/html/validation-chapter.html that I can declare validators with certain prefix

相关标签:
4条回答
  • 2020-12-14 10:52

    //Edit - Giving more information based on the comment for this answer and changing the code accordingly.

    Related Documentation - http://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc

    Notes

    //This is making the handler global for the application
    //If this were on a @Controller bean it would be local to the controller
    @ControllerAdvice
    
    //Specifies to return a 400
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    
    //Which exception to handle
    @ExceptionHandler(ConstraintViolationException.class)
    
    //Specifies to make the return value JSON.
    @ResponseBody
    
    //This class if for modeling the error we return.
    //(Could use HashMap<String, Object> also if you feel it's cleaner)
    class ConstraintViolationModel {
    

    This is an exception handler for Spring that should work in spring boot just fine.

    import java.util.ArrayList;
    import java.util.List;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.validation.ConstraintViolation;
    import javax.validation.ConstraintViolationException;
    
    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.ResponseStatus;
    
    @ControllerAdvice
    public class ExceptionHandlingController {
        @ResponseStatus(value = HttpStatus.BAD_REQUEST)
        @ExceptionHandler(ConstraintViolationException.class)
        public @ResponseBody List<ConstraintViolationModel> handleConstraintViolation(
                HttpServletRequest req, final ConstraintViolationException exception) {
            ArrayList<ConstraintViolationModel> list = new ArrayList<ConstraintViolationModel>();
            for (ConstraintViolation<?> violation : exception
                    .getConstraintViolations()) {
                list.add(new ConstraintViolationModel(violation.getPropertyPath()
                        .toString(), violation.getMessage(), violation
                        .getInvalidValue()));
            }
            return list;
        }
    
        private static class ConstraintViolationModel {
            public String field;
            public String message;
            public Object invalidValue;
    
            public ConstraintViolationModel(String field, String message,
                    Object invalidValue) {
                this.field = field;
                this.message = message;
                this.invalidValue = invalidValue;
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-14 11:05

    this (validatingListener.addValidator("beforeCreate", validator);) doesn't really fully work because the validation only manages the entities.

    So if you try for example to put a validation on a non-entity you get a nasty error saying org.springframework.beans.NotReadablePropertyException: Invalid property '...' of bean class [... the non-entity one ...]: Bean property '....' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

    While obviously more laborious you can perform the validation directly on the Validator manually, e.g:

    @Component("beforeSaveListingValidator")
    public class BeforeSaveListingValidator implements Validator {
    
        @Autowired
        private LocalValidatorFactoryBean validator;
    
        @Override
        public void validate(Object object, Errors errors) {
            BindingResult bindingResult = new BeanPropertyBindingResult(object, errors.getObjectName());
            validator.validate(object, bindingResult);
            errors.addAllErrors(bindingResult);
    
    0 讨论(0)
  • 2020-12-14 11:15

    This seems to work:

    @Configuration
    protected static class CustomRepositoryRestMvcConfiguration extends RepositoryRestMvcConfiguration {
    
        @Autowired
        private Validator validator;
    
        @Override
        protected void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
            validatingListener.addValidator("beforeCreate", validator);
            validatingListener.addValidator("beforeSave", validator);
        }
    }
    
    0 讨论(0)
  • 2020-12-14 11:15

    To customize the spring data-rest configuration, register a RepositoryRestConfigurer (or extend RepositoryRestConfigurerAdapter) and implement or override the configureValidatingRepositoryEventListener method for your specific use case.

    public class CustomRepositoryRestConfigurer extends RepositoryRestConfigurerAdapter {
    
        @Autowired
        private Validator validator;
    
        @Override
        public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
            validatingListener.addValidator("beforeCreate", validator);
            validatingListener.addValidator("beforeSave", validator);
        }
    }
    
    0 讨论(0)
提交回复
热议问题