Please do not swallow exceptions thrown in REST services methods

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.

1 Like

Hi,
The issue has already been fixed in the upcoming release 7.0 (REST API: fill the cause exception in the RestAPIException object · Issue #1274 · cuba-platform/cuba · GitHub), but probably this fix should also appear in the 6.10. We’ve created a separate issue for that: RestAPIException instances should have causes filled where possible · Issue #1504 · cuba-platform/cuba · GitHub. In this issue we’ll fill RestAPIException causes everywhere where it is possible to find the cause.