2013-06-19 7 views
17

So come gestire genericamente le eccezioni in Grails utilizzando UrlMappings e un ErrorController per la gestione delle eccezioni generiche, in modo che se un'eccezione sfugge a un controller, l'utente verrà inviato a una pagina di errore generica e l'eccezione essere registrato So anche come usare i blocchi try/catch per gestire eccezioni specifiche e provare a recuperare da loro.Gestione delle eccezioni nei controller Grails

Ma nella maggior parte dei controller, voglio solo dare all'utente un messaggio di errore leggermente più specifico se si verifica un'eccezione. Quindi, nell'azione di creazione, voglio dire all'utente che l'oggetto non è stato creato. O nell'azione di importazione, voglio dire all'utente che l'importazione non è riuscita. In questo momento, i controllori assomigliano:

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) 
    } 
} 

Si noti che i blocchi catch non fanno nulla di diverso in base al tipo o al contenuto della deroga; stanno solo dando un messaggio di errore leggermente più descrittivo basato sul controller. Il codice del controller "reale" è di solito 6-10 linee, quindi avere 4 righe di codice aggiuntive solo per cambiare il messaggio di errore sembra eccessivo. Inoltre, la regola "CatchException" di CodeNarc si lamenta, il che rafforza la mia opinione secondo cui ci deve essere un modo migliore per farlo. Presumo che altre applicazioni Grails abbiano requisiti simili. Qual è il modo idiomatico per specificare diversi messaggi di errore in base all'azione da cui l'eccezione ha gorgogliato?

Mi interessano le risposte che provengono dall'esperienza con un particolare modo di risolvere questo problema, o ancora meglio, collegano a codebase dove posso vedere la soluzione in pratica.

+5

Per i voti negativi, si prega di spiegare cosa deve essere cambiato sulla domanda, o perché non è appropriato per Stack Overflow. Grazie –

risposta

27

Grails dispone del meccanismo per le eccezioni del controller di gestione generale. È possibile farlo all'interno di un controller degli errori dedicato. I controller regolari non hanno bisogno di usare try/catch.

Controller:

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 

    } 
} 

movimentazione 500 errore nel urlMappings Add:

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]) 
    } 
} 

È possibile gestire REST e le eccezioni non REST che utilizzano questo approccio. Inoltre v'è Declarative Exception Handling plug-in, ma non hanno un aggiornamento

È possibile ottenere i messaggi di errore specifici di controllo degli errori. Quando nel controller viene lanciata una nuova RuntimeException ("Si è verificato un errore durante il tentativo di eliminare la Cosa"), nel controller di errore request.exception.cause.message verrà visualizzato il messaggio: "Si è verificato un errore durante il tentativo di eliminare la Cosa".

+0

Grazie, ma questo sembra quello che abbiamo già: un modo per gestire le eccezioni con un messaggio di errore generico.La dichiarazione di eccezione dichiarativa è interessante perché consente di gestire determinati tipi di eccezioni in un unico posto, ma non mi aiuta ancora a fornire messaggi di errore più specifici in base al controller/azione invocato. –

+0

Penso che sia possibile ottenere i messaggi di errore specifici nel controller degli errori. Vedi la mia risposta aggiornata. –

1

Vedi anche How to know from where was thrown error 500 (Grails)

creo pagine di errore personalizzate sulla base delle annotazioni sui controller, dando procedure di gestione comune delle eccezioni in diversi controllori.

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' 
}