2013-06-19 3 views
17

Я знаю, как выполнять общую обработку исключений в Grails с использованием UrlMappings и ErrorController для общей обработки исключений, так что если исключение ускользает от контроллера, пользователь будет отправлен на общую страницу ошибок, и исключение будет быть зарегистрированным. Я также знаю, как использовать блоки try/catch для обработки определенных исключений и пытаться восстановить их.Обработка исключений в контроллерах Grails

Но в большинстве контроллеров я просто хочу дать пользователю несколько более конкретное сообщение об ошибке, если возникло исключение. Поэтому в действии create я хочу сообщить пользователю, что элемент не был создан. Или в действии импорта я хочу сообщить пользователю, что импорт завершился неудачно. Прямо сейчас, контроллеры выглядят как:

class ThingController { 
    def create = { 
    try { 
     // The real controller code, which quickly hands it off to a service 
    } catch (Exception e) { 
     handleException(e, "There was an error while attempting to create the Thing") 
    } 
    } 

    def delete = { 
    try { 
     // The real controller code, which quickly hands it off to a service 
    } catch (Exception e) { 
     handleException(e, "There was an error while attempting to delete the Thing") 
    } 
    } 

    private void handleException(Exception e, String message) { 
    flash.message = message 
    String eMessage = ExceptionUtils.getRootCauseMessage(e) 
    log.error message(code: "sic.log.error.ExceptionOccurred", args: ["${eMessage}", "${e}"]) 
    redirect(action:index) 
    } 
} 

Обратите внимание, что ловить блоки ничего другого на основе типа или содержания, за исключением не делать; они просто дают немного более описательное сообщение об ошибке на основе контроллера. «Настоящий» код контроллера обычно составляет 6-10 строк, поэтому наличие дополнительных 4 строк кода просто для изменения сообщения об ошибке кажется чрезмерным. Кроме того, правило CodeNarc «CatchException» жалуется, что подтверждает мое мнение о том, что должен быть лучший способ сделать это. Я предполагаю, что другие приложения Grails имеют аналогичные требования. Что такое idiomatic способ указать разные сообщения об ошибках, исходя из которых действие вышло из-за исключения?

Меня интересуют ответы, которые исходят из опыта с определенным способом решения этой проблемы или, что еще лучше, ссылки на кодовые базы, где я вижу решение на практике.

+5

Для пустых голосов, пожалуйста, объясните, что нужно изменить относительно вопроса или почему это не подходит для переполнения стека. Спасибо –

ответ

27

У Grails есть механизм для исключений контроллера общей обработки. Вы можете сделать это внутри специального контроллера ошибок. Регулярным контроллерам не нужно использовать try/catch.

Контроллер:

class ThingController { 
    def create() { 
     def id = params.id as Long 

     if (id == null) { 
      throw new MissingPropertyException("thingId") 
     } 
     // The real controller code, which mostly parses things out and hands it 
     // off to a service. 
     // Service methods can throws exception 

    } 
} 

Добавить обработки 500 ошибок в UrlMappings:

class UrlMappings { 

    static mappings = { 
     // Exception handling in ErrorController 
     "500"(controller: "error") 
    } 
} 

ErrorController:

class ErrorController { 

    def index() { 

     def exception = request.exception.cause 
     def message = ExceptionMapper.mapException(exception) 
     def status = message.status 

     response.status = status 
      render(view: "/error", model: [status: status, exception: exception]) 
    } 
} 

Вы можете обращаться с REST и без исключений REST с помощью этого подхода. Также есть Declarative Exception Handling плагина, но я не имею

Обновления

Вы можете получить сообщения об ошибках в контроллере ошибок. Когда в контроллере выбрано новое RuntimeException («Произошла ошибка при попытке удалить Thing»), тогда в диспетчере ошибок request.exception.cause.message появится сообщение: «При попытке удалить Thing произошла ошибка».

+0

Спасибо, но это похоже на то, что у нас уже есть: способ обработки исключений с одним общим сообщением об ошибке.Обработка декларативного исключения интересна тем, что позволяет обрабатывать определенные типы исключений в одном месте, но по-прежнему не помогает мне предоставлять более конкретные сообщения об ошибках на основе вызываемого контроллера/действия. –

+0

Я думаю, вы можете получить конкретные сообщения об ошибках в контроллере ошибок. См. Мой обновленный ответ. –

1

Смотрите также How to know from where was thrown error 500 (Grails)

создать пользовательские страницы ошибок на основе аннотаций на контроллерах, давая процедуры обработки исключений общего между несколькими контроллерами.

class ErrorsController { 
def index() { 
    def initialController = request.exception?.className 
    if (initialController) { 
     def controller = grailsApplication.getArtefact("Controller", initialController).getReferenceInstance() 
     // do some rendering based on the annotations 
     render "Controller: ${initialController}, annotations ${controller.getClass().getDeclaredAnnotations()}" 
     return 
    } 
    render 'no initial controller' 
} 
Смежные вопросы