I have implemented a ConstraintValidator in order to valide a DTO that contains an enumeration. I followed this Spring documentation for that.
This is the custom annotation to be applied to the enum field:
@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();
}
The EnumValidator
looks like this:
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);
}
}
This is the enum:
public enum Gender {
MALE,FEMALE;
}
This is the DTO to validate:
public final class UserDTO{
@ValidEnum(target = Gender.class)
private Gender gender;
@NotEmpty
@Max(100)
private String fullName;
}
And the controller that is validating the field:
@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);
}
}
It seems that Spring is not detecting the validator, because it throws this exception:
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'
I am using Spring boot 2.0.4 which include the required dependencies for validation.
Any idea why it fails?
You have three mistakes in your code.
@Max(100)
this annotation shouldn't be applied to String field! only for numeric type. If you need to specify String size range restrictions you may use @Size(min = 2, max = 250)
annotation. RequestBody
annotation in the controller method signature:register(@Valid @RequestBody UserDTO userRegistrationRequest)
I've created test project for you. Please check it here https://github.com/alex-petrov81/stackoverflow-answers/tree/master/enum-validator