When a bean property of type java.util.Set is annotated with @Valid (cascade validation), and an element of that Set is violated, the resulting Path of the ConstraintViolation does contain no information which element of the Set is violated. Unfortunately, the validation spec does not describe how the Path should be build when traversing a java.util.Set. However, using a Set is the most natural many-association type when it comes to domain modeling.
Violated elements of Lists and arrays can be identified by their index, violated elements in a Map can be identified by the key. The only way to reliably identify the violated element of a Set is the element itself. Therefore the violated element has to be stored in the Path.
Since the spec is very unclear what to do with Set elements, I suggest to store the violated element as Node.key in the Path. This would make the API changes minimal. It makes even more sense, since a Set can be considered as special kind Map, where each element is mapped to itself.
As is saying, we cannot just change this behavior. The spec is clear on this. If anything it needs to be something which one can enable via a Hibernate Validator specific option.
I am also wondering what one really gains here. As nice as it sounds to: "a Set can be considered as special kind Map, where each element is mapped to itself" - it is still a bit of a stretch. I assume you you get your Path instance from a ConstraintViolation which already has a #getInvalidValue.
#getInvalidValue only returns the element of a Set, if the element is the last element in the Path.
I have a use case, where user input is validated with the validator. The user is entering data in a single UI but the model behind the UI is rather complex with multiple classes with references between each other. One of these relations is a Set and without this patch, no visisble feedback can be given to the user which property exactly was invalid.
I understand your concerns about the specification conformity, espacially the javadoc on the Node interface. I think a special configuration option to activate the behaviour will be OK, I do not know how to implement that, though. Maybe someone else could implement that on top of my pull request?
Hey : and me have mused a bit more about this. How about this: Instead of (ab)-using getKey() you create a new sub-interface of Node exposing a getter for the set element if present. Then one can obtain an instance of this via myNode.as(NewNodeSubType.class).getSetElement().
Sounds good to me. However, I don't know when I find time to implement this. If you have some time to spare, I will be more than happy to see this being implemented .
Are there any chances that this feature finds its way in the upcoming bean validation specification? It would be nice if a user would not have to unwrap the Node subtype.
I will give it a go.
Wrt. to Bean Validation, I am sympathetic to the idea of addressing this issue in one way or another. I will open a BVAL issue.