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

馋奶兔 提交于 2019-11-27 12:42:48

问题


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 prefixes.

I'm using JSR 303 so my domain entities are annotated with validation annotations.

Can - and if yes, how - I use JSR 303 Bean Validation with Spring Data Rest?

PS: I'm using Spring Boot


回答1:


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);
    }
}



回答2:


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);
    }
}



回答3:


//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;
        }
    }
}



回答4:


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);


来源:https://stackoverflow.com/questions/25220440/can-jsr-303-bean-validation-be-used-with-spring-data-rest

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!