Reputation: 7662
I'm trying to build a small POC to check if we can use Spring Validation on our projects (REST Endpoints). The goal is to use the @Valid
annotation on some Component's methods, annotate arguments with JSR-303
annotations and build some Validator
instances for custom validation logic.
Consider the following scenario:
Account (Getters and Setters ommited)
public class Account {
private int id;
@Min(0) private double amount;
@NonNull private String cardholder;
}
AccountController
@RestController
@RequestMapping("/account")
public class AccountController {
@Autowired private AccountService service;
@RequestMapping(method= RequestMethod.POST)
public void post(@RequestBody Account account) {
service.save(account);
}
}
AccountService
@Component
public class AccountService {
public void save(**@Valid** Account account) {
// Logic ommited
log.info("Account saved!");
}
}
AccountSaveValidator
public class AccountSaveValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) { return Account.class.isAssignableFrom(clazz); }
@Override
public void validate(Object target, Errors errors) {
Account account = (Account) target;
if (**if account does not exist**)
errors.rejectValue("id", "account.not-exists");
}
}
Whenever I POST
to /account
, the mentioned validations do not run, and the Account saved!
message is displayed regardless. However, if I put the @Valid
annotation on the AccountController
's POST
handler instead, the validations are executed.
I was only able to execute only the custom validation (AccountSaveValidator) manually by calling it on the save() method like this:
ValidationUtils.invokeValidator(new AccountSaveValidator(), account, errors);
if (errors.hasErrors()) {
throw new ValidationException(errors);
}
What am I missing here? I've read that these validation components are normally used along with Spring-MVC
, but that it could be used without it.
The gradle dependencies I have are the following:
compile "org.springframework:spring-core"
compile "org.springframework:spring-context"
compile "org.springframework:spring-web"
compile "org.springframework.boot:spring-boot"
compile "org.springframework.boot:spring-boot-starter-web"
compile "org.springframework.boot:spring-boot-autoconfigure"
compile "javax.validation:validation-api:1.1.0.Final"
compile "org.hibernate:hibernate-validator:5.2.4.Final"
Upvotes: 3
Views: 8503
Reputation: 86
A couple things, I believe that your title on the question here is a bit misrepresentitive of what you are actually asking here. You are not trying to validate a spring Component. You wish to do method parameter validation within a Spring Component, which is different. I believe that your question here is a duplicate of this question: JSR 303. Validate method parameter and throw exception. There are examples there of how to do what you want to do using proxies and a MethodValidationInterceptor.
I will add some additional information here to try to clarify the differences in where JSR-303 validation works and why.
Spring MVC Parameters: Parameters passed into Spring MVC Components are resolved using a combination of user defined and default HandlerParameterResolvers. Part of Spring's default MVC configuration includes hooks for automatic mappings via @RequestParam and @PathVariable to raw types and @RequestBody to Objects all via the afore mentioned HandlerParameterResolver. In the same way that these HandlerParameterResolvers are automatically configured in Spring (mostly by default) there are also Validators that are registered to the DataBinders, which map the data from the request to the params above, JSR-303 validation is automatically configured to tie into these hooks. This of course is a simplified summary of what is going on behind the scenes.
Spring Components/Beans: Spring Beans and Components are validated by a Spring Bean Validator. You can find details on this here: http://docs.spring.io/autorepo/docs/spring/3.2.x/spring-framework-reference/html/validation.html as described in the section called "7.8.2 Configuring a Bean Validation Implementation"
Upvotes: 2