How to utilize specific argument in spring validator and I cannot merge arguments into a single object?
Say I have a controller like,
@RequestMapping(value = "url",
consumes = { "application/json" }, produces = { "application/json" },
method = RequestMethod.POST)
public MyResponse getMyData(
@Valid @RequestBody MyRequest myRequest, Errors errors, CustomObject obj){
return new MyResponse();
}
I have a aspect implementation for updating the CustomObject
@Around("@annotation(MyAnnotation) && execution(* MyController.getMyData(..))")
public Object requestsAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
Object value = null;
CustomObject obj = new CustomObject();
try {
Object[] args = proceedingJoinPoint.getArgs();
//populate CustomObject
obj = (CustomObject)args[2];
obj.setField("value");
value = proceedingJoinPoint.proceed(args);
} catch (Throwable e) {
e.printStackTrace();
}
return value;
}
CustomObject's updated value I'm able to get in the controller. Now i need to validate MyRequest also using a spring custom validator like,
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.addValidators(new MyCustomValidator());
}
And MyCustomValidator's 'validate()' function is as,
@Override
public void validate(Object target, Errors errors) {
validate((MyRequest)target);
}
Both aspect and validation are working separately but when both are integrated the validation is failing because target in validate method considers 'CustomObject' for validation rather than using 'MyRequest'. Validate method will accept only two arguments while 'getMyData()' method in controller has three. How to resolve this or is there any other approach to achieve a similar solution?
You can try to assign the name of the object to validate to the initBinder (use the name of the object instance, not the class).
InitBinder("myRequest")
protected void initBinder(WebDataBinder binder) {
...
If it's not working, you can try to give an order to the aspect using the Order annotation on it or implement the Order interface.
Anyway, I'm not totally confident about the correctness of the first two options because I cannot test the code (I answer from a tablet). So, I suggest also a third option, where you put the validation inside the controller
@RequestMapping(value = "url",
consumes = { "application/json" },
produces = {"application/json" },
method = RequestMethod.POST)
public MyResponse getMyData(
@RequestBody MyRequest myRequest, BindingResult result, CustomObject obj){
MyCustomValidator validator = MyCustomValidator();
validator.validate(myRequest, result);
if (result.hasErrors()){
// do something
}
return new MyResponse();
}