Проблема в том, что метод MethodValidationInterceptor.invoke
ищет группы проверки, определенные в аннотации @Validated
для каждого метода или класса, но не для отдельных параметров. Указанные группы проверки будут применяться к параметрам, а также к возвращаемому значению.
Для того чтобы разные группы проверки применялись к параметрам и возвращаемым значениям, вам даже не нужно указывать группы внутри аннотация @Validated; вместо этого вы можете использовать @ javax.validation.groups.ConvertGroup.
@Validated
public interface UserOperations {
@NotNull
@Valid
@ConvertGroup(from = Default.class, to = User.Existing.class)
User create(@NotNull @Valid @ConvertGroup(from = Default.class, to = User.New.class) User user);
}
public interface User {
@Email(groups = {New.class, Existing.class})
String getEmail();
@Null(groups = {Existing.class})
@NotNull(groups = {New.class})
String getPassword();
interface Existing {
}
interface New {
}
}
Учитывая вышесказанное, когда вызывается UserOperations.create
, аргумент для user
будет проверен по группе New
(must иметь ненулевой пароль), в то время как возвращаемое значение будет проверено по группе Existing
(должен иметь нулевой пароль).
В качестве примечания, я понял, что валидация метода Spring не ведет себя точно точно так же, как и проверка c Spring MVC в @Valid @RequestBody
. Кроме того, если проверка метода включена для контроллера (имеет аннотацию @Validated
для класса), то один и тот же аргумент метода @RequestBody
будет проверен дважды: один раз при проверке стандартного метода-перехватчика и один раз MVC. Чтобы избежать проверки MVC на @RequestBody
аргументах данного контроллера, я сделал следующее:
@RestController
public class UserController implements UserOperations {
...
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.setValidator(null);
}
...
}