The Hibernate implementation of the BeanValidation spec has already been enhanced to support EL expressions in validation messages. It would be convenient to be able to leverage this capability to provide the desired contextual information.
For example, a value object ("Actor") that's used in multiple locations could anticipate this by providing the additional context.
Code:
public static class Actor {
@NotEmpty.List({
@NotEmpty(message = "First Name is required", groups = ActorValidation.class),
@NotEmpty(message = "First Name is required for role \"${character}\"", groups = MovieValidation.class),
@NotEmpty(message = "First Name is required for role \"${character}\" in movie \"${movieTitle}\"", groups = MovieListValidation.class)
})
public final String firstName;
@NotEmpty.List({
@NotEmpty(message = "Last Name is required", groups = ActorValidation.class),
@NotEmpty(message = "Last Name is required for role \"${character}\"", groups = MovieValidation.class),
@NotEmpty(message = "Last Name is required for role \"${character}\" in movie \"${movieTitle}\"", groups = MovieListValidation.class)
})
public final String lastName;
public Actor(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
Full example:
https://gist.github.com/phaas/94b37d579b6eff9d1d60#file-2-enhancedvalidationexampleIn this example, I'm presuming that groups could be used to selectively enable or disable context-specific validations. I'm also imagining that the required EL variables "character" and "movieTitle" would be added to the validation context when the object graph is traversed. This could be done by annotating the relevant objects with an EL context variable provider that would be able to populate the expression variables using values of the current object being validated. These expression variables would need to be preserved / inherited as the validation descends to properties and nested objects.
Looking at the implementation of the validator framework however, this seems to break several fundamental assumptions made, which makes it not feasible to maintain such an enhancement other than as a "full fork" of the project (not something I'm at all interested in.)
I've also considered using the Path to describe the context of a constraint violation. If it was possible to access the "currentNode.object", "currentNode.parent.object" etc. in the EL expression, this could be used to extract information to describe the path to the user.
This option also seems to be actively discouraged not just by the information put in the EL context, but also by the Path interface, which seems to be lacking any way of looking 'up' the path (even though I'm pretty sure that the implementation does track this.)