7

I have a simple class that has one of its properties as a String array. As per this document, using @Valid on an array, collection etc. will recursively validate each element of the array/collection.

@Valid
@Pattern(regexp="^[_ A-Za-z0-9]+$")
public String[] defaultAppAdminRoles;

the above annotation on the property generates the following exception:

Exception in thread "main" javax.validation.UnexpectedTypeException: No validator could be found for type java.lang.String[]. See: @Pattern at public java.lang.String[] com.hm.vigil.platform.ops.model.Application.defaultAppAdminRoles
at org.apache.bval.jsr303.AnnotationProcessor.checkOneType(AnnotationProcessor.java:326)
at org.apache.bval.jsr303.AnnotationProcessor.getConstraintValidator(AnnotationProcessor.java:301)
at org.apache.bval.jsr303.AnnotationProcessor.applyConstraint(AnnotationProcessor.java:241)
at org.apache.bval.jsr303.AnnotationProcessor.processAnnotation(AnnotationProcessor.java:149)
at org.apache.bval.jsr303.AnnotationProcessor.processAnnotations(AnnotationProcessor.java:90)
at org.apache.bval.jsr303.Jsr303MetaBeanFactory.processClass(Jsr303MetaBeanFactory.java:134)
at org.apache.bval.jsr303.Jsr303MetaBeanFactory.buildMetaBean(Jsr303MetaBeanFactory.java:95)
at org.apache.bval.MetaBeanBuilder.buildForClass(MetaBeanBuilder.java:131)
at org.apache.bval.MetaBeanManager.findForClass(MetaBeanManager.java:102)
at org.apache.bval.jsr303.ClassValidator.validate(ClassValidator.java:140)
at com.hm.vigil.platform.commons.AbstractValidatable.isValid(AbstractValidatable.java:33)
at com.hm.vigil.platform.ops.model.Application.main(Application.java:54)

I am using Apache BVal as validation provider.

The question, is the above method correct?

If it is not correct, what is the correct way to validate an array/collection with bean validation?

If it is correct, then is it some limitation of Apache BVal?

Thed
  • 23
  • 7
Ironluca
  • 3,402
  • 4
  • 25
  • 32

3 Answers3

18

Another thing worth mentioning is the introduction of type annotation in Java 8 which lets you annotate parameterized type

private List<@MyPattern String> defaultAppAdminRoles;

It's not yet in the bean-validation standard (surely in next version) but already available in hibernate-validator 5.2.1. Blog entry here for further information.

Joe Lee-Moyet
  • 1,804
  • 1
  • 20
  • 24
Franck
  • 1,754
  • 1
  • 13
  • 14
  • https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#type-arguments-constraints – o_nix Mar 13 '17 at 11:01
  • 1
    NOTE: for backward compatibility it requires creation of custom validator. – o_nix Mar 13 '17 at 11:02
3

First... i'm not sure... but @Pattern only accepts regex, right? Correct sintax is not:

@Pattern("^[_ A-Za-z0-9]+$")   // delete 'regexp='

If this is not the problem you can create a wrapper class with validators in the attributes:

public class Role {

    @Pattern(regexp="^[_ A-Za-z0-9]+$")
    String adminRole;

    //getters and setters
}

Then just need to mark the field @Valid in your existing object:

@Valid
Role[] defaultAppAdminRoles;
Community
  • 1
  • 1
Jordi Castilla
  • 26,609
  • 8
  • 70
  • 109
  • You'd also need to add single String Constructor in your Wrapper class for implementing this. `public Role(String adminRole){ this.adminRole = adminRole; }` – Vibhum Bhardwaj Jul 03 '17 at 06:21
3

By adding the @Valid annotation like you've done, the validation algorithm is applied on each element (validation of the element constraints).

In your case the String class has no constraints. The @Pattern constraint you've added is applied to the array and not on each element of it. Since @Pattern constraint cannot be applied on a array, you are getting an error message.

You can create a custom validation constraint for your array (see Hibernate docs for more info) or you can use a wrapper class like @Jordi Castilla mentioned.

Tunaki
  • 132,869
  • 46
  • 340
  • 423