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
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);
}
}
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);
}
}
//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;
}
}
}
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, eg:
@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);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.