liecno
liecno

Reputation: 934

Howto validate Collections in Maps

I have a problem with the @Valid annotation of JSR-303. The annotation works fine for normal lists or and sets, but I am trying to validate Maps which contain Lists, i.e.

@Valid
HashMap<String, ArrayList<Object1>> map;

In this case, instances of Object1 class are not validated. Is there a convenient way to do this recursively, without iterating over every object and validating it manually?

Upvotes: 16

Views: 10956

Answers (1)

Perception
Perception

Reputation: 80603

The specification does not specify the validation behavior when the map values are themselves lists.

From JSR 303 specification:

Each object provided by the iterator is validated. For Map, the value of each Map.Entry is validated (the key is not validated).

Since the value in your case is a list, which does not have a @Valid annotation, it does not get processed. To get around this you can either:

Wrap the contained list in another bean, forcing the annotation processing onto the list.

public class ListHolder<T extends Iterable> {
    @Valid
    public T wrappedList;
}

Or alternatively you can write a custom validator to handle your complex maps. Something like this:

@Target({ METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = ValidMapValidator.class)
public @interface ValidMap {
   String message() default "valid.map";

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

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

public class ValidMapValidator implements
      ConstraintValidator<ValidMap, Map<?, ?>> {

   @Override
   public void initialize(final ValidMap annotation) {
      return;
   }

   @Override
   public boolean isValid(final Map<?, ?> map,
         final ConstraintValidatorContext context) {
      if (map == null || map.size() == 0)
         return true;

      // Iterate each map entry and validate
      return true;
   }
}

Upvotes: 14

Related Questions