Grails also allows you to map HTTP response codes to controllers, actions or views. All you have to do is use a method name that matches the response code you are interested in:

static mappings = {
   "403"(controller: "errors", action: "forbidden")
   "404"(controller: "errors", action: "notFound")
   "500"(controller: "errors", action: "serverError")
}

Or alternatively if you merely want to provide custom error pages:

static mappings = {
   "403"(view: "/errors/forbidden")
   "404"(view: "/errors/notFound")
   "500"(view: "/errors/serverError")
}

Declarative Error Handling

In addition you can configure handlers for individual exceptions:

static mappings = {
   "403"(view: "/errors/forbidden")
   "404"(view: "/errors/notFound")
   "500"(controller: "errors", action: "illegalArgument", exception: IllegalArgumentException)
   "500"(controller: "errors", action: "nullPointer", exception: NullPointerException)
   "500"(controller: "errors", action: "customException", exception: MyException)
   "500"(view: "/errors/serverError")
}

With this configuration, an IllegalArgumentException will be handled by the illegalArgument action in ErrorsController, a NullPointerException will be handled by the nullPointer action, and a MyException will be handled by the customException action. Other exceptions will be handled by the catch-all rule and use the /errors/serverError view.