Issue
I have User class with list of roles:
@Data
@Table(name = "users")
@Entity
public class User {
String username;
String password;
List<Role> roles;
}
And the role enum:
public enum Role {
Admin,User,Manager
}
I need to validate the bean before insert it to DB. The validation expression should look like this:
long count = user.getRoles().stream().filter(r -> r.equals(Role.Manager)).count();
!(count > 1);
User cant have more than one manager role, but for other roles its ok to have duplicates; For this i created a custom constraint and a validator for him: Constraint:
@Target({ ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = RoleValidator.class)
public @interface RoleConstraint {
String message() default "error";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
Validator:
public class RoleValidator implements ConstraintValidator<RoleConstraint, List<Role>> {
@Override
public boolean isValid(List<Role> roles, ConstraintValidatorContext context) {
long count = roles.stream().filter(r -> r.equals(Role.Manager)).count();
return !(count > 1);
}
}
but it doesnt work. I also found a solution here but i cant wrap the list in beanList because a lot of other classes depends on this class. Is there other way to solve this problem. Any suggestion is acceptable
Solution
Since you are validating the User
, you can make you annotation work with a user. Have the annotation work on classes:
@Target({ ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = RoleValidator.class)
public @interface RoleConstraint {
String message() default "error";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
Change the validator to work with user:
public class RoleValidator implements ConstraintValidator<RoleConstraint, User> {
@Override
public boolean isValid(User user, ConstraintValidatorContext context) {
long count = user.roles.stream().filter(r -> r.equals(Role.Manager)).count();
//that's simpler, but is the same as '!(count > 1)'
return count <= 1;
}
}
Then apply @RoleConstraint
on User
class.
Answered By - Chaosfire
Answer Checked By - Katrina (JavaFixing Volunteer)