I'm using JAX-RS resources with Bean Validation and integration between these two works as expected.
However, the default error messages generated in case of a validation error report parameter names as arg0, like so
[PARAMETER]
[login.arg0.password]
[password is required]
[]
Corresponding method definition:
@POST //and other JAX-RS annotations
public Response login(
@NotNull
@Valid
LoginBody loginBody) {
[...]
protected static class LoginBody {
@NotNull(message = EMAIL_REQUIRED)
public String email;
@NotNull(message = PASSWORD_REQUIRED)
public String password;
}
While I'm generally fine with this message pattern, what actually is annyoing, is the fact that the original parameter name is not recognized, i. e. I'd rather like to see
login.loginBody.password instead of arg0.
Is there an easy way to fix this, e. g. somehow provide an explicit name for that parameter?
I'm using WildFly Swarm 2017.6.0. From what I found out this means I have resteasy + resteasy-validator + hibernate-validator
Thanks.
You could try to compile your app with -parameters
or instruct your IDE to do so, e.g. in case of
eclipse: preferences -> java -> compiler -> "store information about method parameters (usable via reflection)"
With that in place you then need to instruct the Bean Validation infrastructure (e.g. ) hibernate-validator to
use the ReflectiveParameterNamer
via META-INF/validation.xml
.
<parameter-name-provider>org.hibernate.validator.parameternameprovider.ReflectionParameterNameProvider</parameter-name-provider>
See also Hibernate Validator Configuration
I got something reliably working with the Paranamer library
META-INF/validation.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<validation-config
xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://jboss.org/xml/ns/javax/validation/configuration
validation-configuration-1.1.xsd"
version="1.1">
<default-provider>org.hibernate.validator.HibernateValidator
</default-provider>
<message-interpolator>org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator
</message-interpolator>
<traversable-resolver>org.hibernate.validator.internal.engine.resolver.DefaultTraversableResolver
</traversable-resolver>
<constraint-validator-factory>org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorFactoryImpl
</constraint-validator-factory>
<parameter-name-provider>org.hibernate.validator.parameternameprovider.ParanamerParameterNameProvider</parameter-name-provider>
</validation-config>
To get paranamer
working with wildfly I needed to create a parameter-namer
jboss-module
and reference that module from the module.xml
of the hibernate-validator
module.
With that in place I could simply write:
@POST
public Response login(@NotNull @Valid @Named("authRequest") AuthRequest authRequest) {
return Response.ok().build();
}
...
public class AuthRequest {
@NotNull(message = AuthMessages.EMAIL_REQUIRED)
public String email;
@NotNull(message = AuthMessages.PASSWORD_REQUIRED)
public String password;
}
which yields the following response for a request sent via curl
:
curl -H "Content-Type: application/json" -H "Accept: application/json" -d '{"email":"foo@bar.com"}' -v http://localhost:8080/javaweb-training/resources/auth
Response:
{"exception":null,"fieldViolations":[],"propertyViolations":[],"classViolations":[],"parameterViolations":[{"constraintType":"PARAMETER","path":"login.authRequest.password","message":"password.required","value":""}],"returnValueViolations":[]}%
... note login.authRequest.password
instead of just login.arg0.password