javax.validation.UnexpectedTypeException с использованием Spring ConstraintValidator для перечисления

Я реализовал ConstraintValidator для проверки DTO, содержащего перечисление. Я следовал эта документация Spring для этого.

Это пользовательская аннотация, которая будет применяться к полю enum:

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR,
    ElementType.ANNOTATION_TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EnumValidator.class)
public @interface ValidEnum {

  String message() default "{com.test.validation.constraints.ValidEnum}";

  Class<?>[] groups() default {};

  Class<? extends Payload>[] payload() default {};

  Class<? extends Enum<?>> target();

}

EnumValidator выглядит так:

public class EnumValidator implements ConstraintValidator<ValidEnum,String> {

      private Set<String> enumValues;

      @Override
      public void initialize(ValidEnum targetEnum) {
          Class<? extends Enum> enumSelected = targetEnum.targetClassType();
          enumValues = (Set<String>) EnumSet.allOf(enumSelected).stream()
              .map(e -> ((Enum<? extends Enum<?>>) e).name()).collect(Collectors
                  .toSet());
      }

      @Override
      public boolean isValid(String value, ConstraintValidatorContext context) {
          return enumValues.contains(value);
      }
  }

Это перечисление:

public enum Gender {
  MALE,FEMALE;
}

Это DTO для проверки:

public final class UserDTO{

  @ValidEnum(target = Gender.class)
  private Gender gender;

  @NotEmpty
  @Max(100)
  private String fullName;
}

И контроллер, который проверяет поле:

@Controller
public class RegistrationController {

  private static final String REGISTER_USER = "/register";

  private final RegistrationService registrationService;


  @PostMapping(value = REGISTER_USER)
  @Consumes(APPLICATION_JSON)
  @Produces(APPLICATION_JSON)
  public UserRegistrationResponse register(@Valid UserDTO userRegistrationRequest) {

    return registrationService.register(userRegistrationRequest);
  }

}

Кажется, что Spring не обнаруживает валидатор, потому что выдает это исключение:

org.springframework.web.util.NestedServletException: Request processing failed; 
nested exception is javax.validation.UnexpectedTypeException: HV000030: 

No validator could be found for constraint 'com.test.ws.web.validation.ValidEnumType' validating type 'com.test.ws.domain.model.Gender'. Check configuration for 'gender'

Я использую Spring boot 2.0.4, который включает необходимые зависимости для проверки.

Любая идея, почему это терпит неудачу?


person lsantamaria    schedule 01.09.2018    source источник


Ответы (1)


У вас три ошибки в коде.

  1. @Max(100) эту аннотацию нельзя применять к полю String! только для числового типа. Если вам нужно указать ограничения диапазона размера строки, вы можете использовать аннотацию @Size(min = 2, max = 250).
  2. Вы забыли аннотацию RequestBody в сигнатуре метода контроллера:

register(@Valid @RequestBody UserDTO userRegistrationRequest)

  1. Проверка Enum использует строковое значение из Rest API, а не самого Enum. Вот почему у вас здесь ошибка.

Я создал тестовый проект для вас. Пожалуйста, проверьте это здесь https://github.com/alex-petrov81/stackoverflow-answers/tree/master/enum-validator

person Alexander Petrov    schedule 01.09.2018
comment
Я уже исправил 2 первых пункта, потому что были небольшие ошибки, но последний, который я действительно забыл. Это сработало, спасибо - person lsantamaria; 01.09.2018