Using @Valid annotation on a Spring Component method

Viewed 7423

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"
1 Answers
Related