If you use a controller to implement rest APIs, you want to deal with any exception thrown and return a generic or specific well formed REST response.
We can't use global error URL mapping method, as the application has a number of APIs and interfaces with different response requirements, and we also don't know which type of Grails' HTTP error codes will be thrown (e.g don't know if it will be a 400, 422, 500 etc). Also, if we used the error page mappings, we won't be able to put relevant data into the JSON response.
E.g. this will generate a GrailsRuntimeException:
class SomeController {
def payload = request.JSON
def someMethod() {
BigDecimal x = new BigDecimal(payload.notExists)
}
The problem is, it seems impossible to catch any error thrown.
E.g. neither this approach:
def handleRuntimeException(RuntimeException e) {
render("some JSON error message")
}
Nor this approach:
try {
:
}
catch (GrailsRuntimeException e) {
render("some JSON error message")
}
Works - it never catches the error.
Tried GroovyRuntimeException, Exception, MissingMethodException, Throwable etc.
The only solution we can think of is to not do any work in the controller, do everything in a service, where apparently we can catch errors.
This approach:
static mappings = {
"500"(controller: "error")
}
Is not want we need for several reasons:
- We have several different APIs in different controllers which would require different response formats.
- we also have UI controllers, which would want the default error system which shows the stack trace etc.
- We want to handle the error in the controller where the exception happened, so we can clean up, or at least can log or return the stat which only the controller knows.
Have decided the only way is to move all code into services, and do nothing in the controller except pass the request, and render the resultant string. i.e. all parameter handling, especially number conversion, is done in the service.