Когда я добавляю @Validated
в Spring RestConstroller
, я получаю ответ HTTP 404 для конечных точек этого контроллера. Перед добавлением аннотации конечная точка найдена без проблем.
Проблема связана только с @PathVariable
, и у меня корректная работа проверки (с использованием @Valid
) с не примитивными параметрами RequestBody.
Есть довольно много статей по этому вопросу, и я потратил значительное количество времени, пытаясь несколько вариантов без успеха. Самое простое это.
Согласно этому простому примеру https://sdqali.in/blog/2015/12/05/validating-requestparams-and-pathvariables-in-spring-mvc/ Я полагаю, что это должно быть так же просто, как добавить @Validated
к контроллеру, исключив @Valid
для параметра PathVariable и добавив компонент MethodValidationPostProcessor
. Предпочтительно я бы использовал @Valid
вместо @Validated
.
Я использую Spring 5 (не загрузочный) и у меня есть hibernate-validator 6.0.16.Final на пути к классам
Проблемный RestController
@Validated
@RestController
@RequestMapping(value = "practices")
public class RestPracticeResource implements PracticeResource {
@Override
@GetMapping("/{id}")
public ResponseEntity<Practice> getPractice(@Id @PathVariable("id") final String id) throws ResourceNotFoundException {
final UUID uuidId = UUID.fromString(id);
}
}
Рабочий RestController для RequestBody
@RestController
@RequestMapping(value = "accounts")
public class RestAccountResource implements AccountResource {
@Override
@PostMapping
public ResponseEntity<AccountDto> create(@NotNull @Valid @RequestBody final CreateAccountDto createAccountDto)
throws ResourceAlreadyExistsException {
...
}
}
Id Аннотация
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = Id.IdValidator.class)
public @interface Id {
// ... Stock standard code here
class IdValidator implements ConstraintValidator<Id, String> {
@Override
public void initialize(final Id id) {}
@Override
public boolean isValid(final String id, final ConstraintValidatorContext constraintValidatorContext) {
// Basic REGEX match for UUID format
return ValidationUtil.isValidId(id);
}
}
}
ExceptionHander
@ExceptionHandler(ConstraintViolationException.class)
public final ResponseEntity<ApiError> handleConstraintViolationException(final ConstraintViolationException ex,
final WebRequest webRequest) {
// .. extract violations into standard format
return new ResponseEntity<>(apiError, BAD_REQUEST);
}
MethodValidationPostProcessor bean
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
Фактические результаты
Как только я добавляю @Validated
, я получаю ответы Http 404 для конечной точки /practices/{id}
независимо от того, какой формат у провайдера I id. Если я удаляю @Validated
, я могу передать действительный UUID, и все в порядке, или передать неверный UUID и получить исключение, выданное UUID.fromString(id)
.
@Id
игнорируется, если я пытаюсь использовать @Valid
в соответствии с проверкой тела запроса.
Ожидаемые результаты
При добавлении @Validated
будет включена проверка аннотации @Id
, и выдается ConstraintViolationException
, если предоставляется {id}
в формате, отличном от UUID.