Можно ли использовать JSR 303 Bean с помощью Spring Data Rest?

Я понимаю из документов http://docs.spring.io/spring-data/rest/docs/2.1.2.RELEASE/reference/html/validation-chapter.html, что могу объявлять валидаторы с определенными префиксами.

Я использую JSR 303, поэтому мои объекты домена аннотируются аннотациями проверки.

Может - и если да, то как - я использую JSR 303 Bean Проверка с помощью Spring Data Rest?

PS: Я использую Spring Boot

Ответ 1

Это работает:

@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

Чтобы настроить конфигурацию данных spring, зарегистрируйте RepositoryRestConfigurer (или расширьте RepositoryRestConfigurerAdapter) и реализуйте или переопределяйте метод configureValidatingRepositoryEventListener для вашего конкретного варианта использования.

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 - предоставление дополнительной информации на основе комментария для этого ответа и изменения кода соответственно.

Дополнительная документация - http://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc

Примечания

//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 cleaner)
class ConstraintViolationModel {

Это обработчик исключений для Spring, который должен работать в Spring загрузке просто отлично.

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

это (validatingListener.addValidator("beforeCreate", validator);) на самом деле не работает полностью, потому что проверка только управляет сущностями.

Поэтому, если вы попытаетесь, например, поставить проверку не-сущности, вы получите неприятную ошибку, в которой говорится, что 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?

Хотя это очевидно более трудоемко, вы можете выполнить проверку непосредственно на Валидаторе вручную, например:

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