Reputation: 41
I am using JSR 303 and have written a number of annotations so I am familiar with the process of getting custom constraints working.
I have just come up against a problem that I am not sure I can solve elegantly. The objects here are for illustration ! So I have a grandparent object which has a list of children. Each child has its own list of children (grandchildren to the grandparent, obviously). The size of this list can be constrained with @Size. But I need to constrain the TOTAL size of the number of (grand)children from the grandparent so that if I validate the Grandparent instance, they are limited to 50 grandchildren across all of their children. Odd example, I know :-)
I started this by creating a method in the grandparent which simply counts all of the elements in the children lists of the children lists in the GrandParent and adding a simple @Size annotation to that. This feels just a little ugly - adding a method like this which is only there to serve some validation. Wasn't that part of what JSR was supposed to solve ?
Or - create a custom annotation like this :
@CustomListSize(listName="children.children", min=0, max=50)
Grandparent
--> List<Child> children
@Size(min=0, max=5)
-->List<Child> children
--> List<Object> list1
-->List<Object> list2
I can obviously get this with reflection / propertydescriptor and check against the min / max value. Does that sound OK or is there a better way in JSR 303 that I am missing. This works too but requires more code and is still not ideal.
Finally, what if I wanted to do the same check on the number of entries in list2 ? I can't repeat CustomListSize so how to do that - have an inner list ?
Thanks
Chris
Upvotes: 4
Views: 709
Reputation: 781
Create a custom validator for Grandparent
public class GrandParentValidator implements ConstraintValidator {
@Override
public boolean isValid(GrandParent bean,
ConstraintValidatorContext ctx) {
//Count the number of Grandkids
int noOfGrandKids = 0 ;
for (Children child :bean.getAllChild() ){
noOfGrandKids += child.getAllChild().size ;
}
if (int noOfGrandKids > 50){
ctx.disableDefaultConstraintViolation();
ctx.buildConstraintViolationWithTemplate("Invalid -More than 50 Grandkids found").addConstraintViolation();
return false ;
}
return true ;
}
}
Upvotes: 0
Reputation: 22672
I think that custom validator for your grandparent object would be a good approach.
@InnerListSize(lists = {"list1", list2"}, min=0, max=50)
class GrandParent{
List list1;
List list2;
}
Reflection can be used to get lists. Once we have them it is easy to calculate overall size. The validator class would not be particularly complicated.
Upvotes: 1