If you are familiar with the Bean Validation Framework you know that you cannot get the name of a method argument. So if you do a @NotNull constraint on the first argument of a method and the validation fails the getPropertyPath will be something like "arg1".
I would like to create my own version of @NotNull that can take a value e.g. @NamedNotNull( "emailAddress" ). But I can't figure out how to override the #getPropertyPath in my Validator? Is there any way to do this or am I stuck with "arg1" or "arg2", etc.
EDIT
Based on the answer I received I was able to come up with the following implementation that allows me to take the value from my @QueryParam or @PathParam annotations and use those as the property path for Bean Validation annotations like @NotNull.
For Jersey you need to create the following class. Note the implementation of DefaultParameterNameProvider:
public class ValidationConfigurationContextResolver implements ContextResolver<ValidationConfig> {
@Override
public ValidationConfig getContext( final Class<?> type ) {
final ValidationConfig config = new ValidationConfig();
config.parameterNameProvider( new RestAnnotationParameterNameProvider() );
return config;
}
static class RestAnnotationParameterNameProvider extends DefaultParameterNameProvider {
@Override
public List<String> getParameterNames( Method method ) {
Annotation[][] annotationsByParam = method.getParameterAnnotations();
List<String> names = new ArrayList<>( annotationsByParam.length );
for ( Annotation[] annotations : annotationsByParam ) {
String name = getParamName( annotations );
if ( name == null )
name = "arg" + ( names.size() + 1 );
names.add( name );
}
return names;
}
private static String getParamName( Annotation[] annotations ) {
for ( Annotation annotation : annotations ) {
if ( annotation.annotationType() == QueryParam.class ) {
return QueryParam.class.cast( annotation ).value();
}
else if ( annotation.annotationType() == PathParam.class ) {
return PathParam.class.cast( annotation ).value();
}
}
return null;
}
}
}
Then in your RestConfig you need to add the following line:
register( ValidationConfigurationContextResolver.class );
That's it. Now your ConstraintValidationExceptions will contain the name of the QueryParam or PathParam they are annotated with. For example:
public void getUser(
@NotNull @QueryParam( "emailAddress" ) String emailAddress,
@NotNull @QueryParam( "password" ) String password )
{ ... }
if (name == null) name = "payload[" + parameterTypes[index].getSimpleName() + "]";
instead of"arg<n>"
. This provides the type of the payload, the parameter without the inspected annotations in the Rest method. This gives"path": "SomeResource.testValidation.payload[PayloadDto].attributes"
when validating the fields of the payload DTO (and the type of the payload if it is missing entirely and having the @NotNull annotation). – Cuspidation