I have a list of String in my bean. These strings are email and I would like to validate them.
@Email
@ElementCollection(fetch = FetchType.LAZY)
@OrderColumn
private List<String> emails = new ArrayList<String>();
At execution, I got this error:
Caused by: javax.validation.UnexpectedTypeException: HV000030: No validator could be found for type: java.util.List<java.lang.String>.
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager.verifyResolveWasUnique(ConstraintValidatorManager.java:218)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager.findMatchingValidatorClass(ConstraintValidatorManager.java:193)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager.getInitializedValidator(ConstraintValidatorManager.java:97)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:125)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateComposingConstraints(ConstraintTree.java:233)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:102)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:91)
at org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:83)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:547)
...
What is the correct way of doing this? Or are there any other ways to do this?
@Email
only works on String
not List
, but you can create your own validator:
@Target({ ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EmailCollectionValidator.class)
@Documented
public @interface EmailCollection {
String message() default "Invalid Email";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
validator:
public class EmailCollectionValidator implements ConstraintValidator<EmailCollection, Collection<String>> {
@Override
public void initialize(EmailCollection constraintAnnotation) {
}
@Override
public boolean isValid(Collection<String> value, ConstraintValidatorContext context) {
if (value == null) {
return false;
}
EmailValidator validator = new EmailValidator();
for (String s : value) {
if (!validator.isValid(s, context)) {
return false;
}
}
return true;
}
}
implementation:
@EmailCollection
@ElementCollection(fetch = FetchType.LAZY)
@OrderColumn
private List<String> emails = new ArrayList<String>();
Implementing an additional constraint validator for @Email
validating collections as suggested here is one way of doing it. Note, you might have problems with generating the right property paths in case you get a constraint violation. See also HV-264.
If you are using Java 8, you could use the latest Hibernate Validator release as well (5.2.x) which supports Java 8 type level annotations. You can write something like List<@Email String>
. In this case, however, you need to create for now your own @Email
constraint annotation and make sure that @Target
contains ElementType.TYPE_USE
. See also Hibernate Validator docs.
The next version of Bean Validation (2.0) will align with Java 8. All provided constraints will then have ElementType.TYPE_USE
and can be used out of the box. See also BVAL-202.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With