Hi
this is something that hits me in the back since I started working with CUBA rest APIs (v2).
When we invoke a service method via REST API controller /services, every exception that is not a ValidationException is swallowed by the ServicesControllerManager class, mapping it to a clueless RestAPIException.
The culprit is the following code in the _invokeServiceMethod method in the ServicesControllerManager class:
Object methodResult;
try {
methodResult = serviceMethod.invoke(service, paramValues.toArray());
} catch (InvocationTargetException | IllegalAccessException ex) {
if (ex.getCause() instanceof ValidationException) {
throw (ValidationException) ex.getCause();
} else {
log.error("Error on service method invoke", ex.getCause());
throw new RestAPIException("Error on service method invoke", "", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
It’s sufficient to pass the underlying Throwable when constructing the RestAPIException so that we can extract it in a @ExceptionHandler method, like so:
@ExceptionHandler(RestAPIException.class)
@ResponseBody
public ResponseEntity<ErrorInfo> handleRestAPIException(RestAPIException e) {
RestAPIException exc = e;
if (e.getCause() == null) {
log.error("RestAPIException: {}, {}", e.getMessage(), e.getDetails());
} else if (e.getCause() instanceof ServiceMethodException) {
exc = (RestAPIException) e.getCause();
log.error("ServiceMethodException: {}, {}", e.getMessage(), e.getDetails());
} else {
log.error("RestAPIException: {}, {}", e.getMessage(), e.getDetails(), e.getCause());
}
ErrorInfo errorInfo = new ErrorInfo(exc.getMessage(), exc.getDetails());
return new ResponseEntity<>(errorInfo, exc.getHttpStatus());
}
As of today, the previous code does not work (e.getCause is always null).
Thanks
P.