JPA Validation of Email String Collection
Asked Answered
A

3

10

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?

Ably answered 28/1, 2016 at 0:41 Comment(0)
C
13

@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>();
Cutlip answered 28/1, 2016 at 1:22 Comment(2)
The line "return validator.isValid(s, context)" only returns if the first element in the collection is valid. I edited the answer to fix this, but it was rejected.Mailand
is there any way to set the rejected values (only invalid emails) so that I can get only those values in spring's fieldError.getRejectedValue() ?Intrepid
L
7

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.

Lacee answered 29/1, 2016 at 9:1 Comment(1)
I tried with List<@Email String> and it does not work with error ava.lang.IllegalStateException: JSR-303 validated property 'toEmailAddressList[0].<list element>' does not have a corresponding accessor for Spring data binding But List<@Email String> workedFootplate
A
6

From Hibernate Validator version 6.0 and up you can do directly

Set<@Email String> emails

reference:
https://hibernate.atlassian.net/browse/HV-1094
https://github.com/hibernate/hibernate-validator/pull/512/commits/a24b47eb596737d2255bcd5a93298bd4f22097c3#diff-58473853b1e525d36641484e943b462d7b17cab5ca74357216f81f499400d7a6

Assumpsit answered 16/1, 2021 at 6:22 Comment(1)
works with jakarta ` import jakarta.validation.constraints.Email; @NotNull Set<@Email String> emails; `Yvetteyvon

© 2022 - 2024 — McMap. All rights reserved.