Since Grails 2.3 we can define exception methods in our controllers to handle exceptions raised by code invoked in the action methods of the controllers. Normally we would write a try/catch
statement to handle an exception or let it continue up the stack until a 500
error page is shown. But with exception methods we can write code to handle exceptions in a controller without a try/catch
statement. An exception method should define the type of exception it handles as the method argument. We can have multiple exception methods for different exception types. Also subclasses of a controller will use the exception methods if applicable.
In the following controller we have a couple of action methods: index
and show
. And we have two exception methods: connectException
and notFoundException
. The connectException
method has a single argument of type ConnectException
. This means that any code in the controller that will raise a ConnectException
will be handled by this method. And any ResourceNotFoundException
thrown in the controller will be handled by the notFoundException
method, because the argument type is ResourceNotFoundException
.
package com.mrhaki.grails class SampleController { /** * Service with methods that are invoked * from the controller action methods. */ ExternalService externalService //-------------------------------------------- // Action methods: //-------------------------------------------- /** Index action method */ def index() { // These method calls could throw a ConnectException. // If the ConnectException occurs then the // connectException(ConnectException) method is // invoked and that method will handle the // request further. final all = externalService.all(params) final total = externalService.count() [items: all, totalCount: total] } /** Show action method */ def show(final Long id) { // This method can throw a ConnectException // or ResourceNotFoundException. // If the ResourceNotFoundException is thrown // the request is further handled by // the notFoundException(ResourceNotFoundException) // method. final item = externalService.get(id) [item: item] } //-------------------------------------------- // Exception methods: //-------------------------------------------- /** * If any method in this controller invokes code that * will throw a ConnectException then this method * is invoked. */ def connectException(final ConnectException exception) { logException exception render view: 'error', model: [exception: exception] } /** * If any method in this controller invokes code that * will throw a ResourceNotFoundException then this method * is invoked. */ def notFoundException(final ResourceNotFoundException exception) { logException exception render view: 'notFound', model: [id: params.id, exception: exception] } /** Log exception */ private void logException(final Exception exception) { log.error "Exception occurred. ${exception?.message}", exception } }
Code written with Grails 2.4.0.