I am currently investigating using the hibernate validators support for Method validation using JSR 303 annotations. An initial attempt tried to wrap the resources with a proxy (generated using cglib) that performed the validation, however, this appears to have come to a dead-end, as the proxy methods I have tried do not seem to copy parameter annotations, so resource methods that rely on this end up being called with no parameters. I have another question open at the moment on that item:
How can I create a dynamic proxy in java that retains parameter annotations on methods?
Is there an alternative mechanism to hook into wink's request chain to do something like this without using proxies?
You can do this is a partially supported way by creating a RequestHandler, and overriding the actual HandlersFactory to return a list containing your request handler. The configuration for this is discussed here. This request handler will be inserted into the request handling chain directly before the InvokeMethodHandler (which is the last request handler called, and this is the one which actually invokes the resource method).
Based on reading the source code for the InvokeMethodHandler (which actually calls your JAX/RS resource), you can get the parameters, instance and method parameters as follows:
// Get Method Validator from hibernate
MethodValidator validator = Validation.byProvider(HibernateValidator.class).configure()
.buildValidatorFactory().getValidator().unwrap(
MethodValidator.class);
// Extract the method parameters, object instance and method metadata from the JAX/RS internals.
Method javaMethod = null;
Object instance = null;
Object[] parameters = null;
SearchResult searchResult = context.getAttribute(SearchResult.class);
javaMethod = searchResult.getMethod().getMetadata()
.getReflectionMethod();
parameters = searchResult.getInvocationParameters();
instance = searchResult.getResource().getInstance(context);
// Use all this to perform validation...
Set<MethodConstraintViolation<Object>> violations = validator
.validateAllParameters(instance, javaMethod, parameters);
if (!violations.isEmpty()) {
// do something with the violations here
}
This is somewhat hacky, as it relies on (undocumented as far as I can tell) implementation details of wink to get the instance, parameters, and metadata (it would be nice if they provided a public way to get to this information). However, it is somewhat preferable to using a proxy, because you don't infer multiple overheads from reflection that occur with a proxy.