Как узнать откуда была выброшена ошибка 500 (Grails) - PullRequest
6 голосов
/ 30 марта 2011

У меня есть следующий сценарий в моем UrlMappings.groovy:

"/user/$action?" (controller:"user")
"/admin/$action?" (controller:"user")

"500"(controller:"error", action:"show")
"404"(controller:"error", action:"show")

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

Есть идеи?

Заранее спасибо.

Ответы [ 5 ]

12 голосов
/ 31 марта 2011

Вы можете получить доступ к исключению в вашем ErrorController через request.exception.Исключение верхнего уровня всегда указывает на контроллер, куда он был брошен, поэтому вы можете узнать имя контроллера с помощью exception.className.Вот очень простой пример.

class ErrorController {

    def show = {
      def exception = request.exception
      render(text: "Exception in ${exception?.className}", 
        contentType: "text/plain", encoding: "UTF-8")
    }
}
7 голосов
/ 31 марта 2011

Используя request.getAttribute("exception"), вы получите исключение. Я бы посмотрел на все атрибуты запроса, может быть, есть прямая ссылка на исходный контроллер.

UPDATE

Хитрость в том, что Grails превращает выброшенное исключение в GrailsWrappedRuntimeException , обеспечивающее удобный доступ к коду, отвечающему за исключение. Используйте следующий фрагмент в вашем контроллере ошибок:

import org.codehaus.groovy.grails.web.errors.GrailsWrappedRuntimeException
def action = {   
   def exception = request.getAttribute('exception')
   if (exception instanceof GrailsWrappedRuntimeException) {
       log.error "exception $exception.className, line $exception.lineNumber has throw $exception.cause"
   }
}
1 голос
/ 31 марта 2011

Чтобы отобразить другую страницу «ошибка 500», я думаю, вы могли бы сделать то же самое со скаффолдингом Grails:

Во-первых, нам просто нужно указать представление в URL Mapping:

"500"(view: "/500")   // Point to 500.gsp

Тогда вот код представления "500":

<code>        <h1>Grails Runtime Exception</h1>

        <h2>Error Details</h2>

        <div class="message">
            <strong>Error ${request.'javax.servlet.error.status_code'}:</strong>
            ${request.'javax.servlet.error.message'.encodeAsHTML()}<br/>
            <strong>Servlet:</strong> ${request.'javax.servlet.error.servlet_name'}<br/>
            <strong>URI:</strong> ${request.'javax.servlet.error.request_uri'}<br/>
            <g:if test="${exception}">
                <strong>Exception Message:</strong> ${exception.message?.encodeAsHTML()} <br/>
                <strong>Caused by:</strong> ${exception.cause?.message?.encodeAsHTML()} <br/>
                <strong>Class:</strong> ${exception.className} <br/>
                <strong>At Line:</strong> [${exception.lineNumber}] <br/>
                <strong>Code Snippet:</strong><br/>

                <div class="snippet">
                    <g:each var="cs" in="${exception.codeSnippet}">
                        ${cs?.encodeAsHTML()}<br/>
                    </g:each>
                </div>
            </g:if>
        </div>
        <g:if test="${exception}">
            <h2>Stack Trace</h2>

            <div class="stack">
                <pre><g:each in="${exception.stackTraceLines}">${it.encodeAsHTML()}<br/></g:each>

Вы можете извлечь любую информацию, которая вам нужна, из error & stacktrace (div class = "stack").

Вы можете создать 2 различных шаблона для пользователя и администратора, а затем *Тег 1014 * определит, какой шаблон необходимо включить в представление.

0 голосов
/ 19 ноября 2013

Я иногда комментирую свои контроллеры описанием, которое я хотел бы показать в сообщении об ошибке:

// ControllerType is a custom annotation
@ControllerType(description= "this does foo bar")
class MainController {
    ...

С этим на основе поста от Aoi Karasu, вот как извлечьинформация из исходного контроллера:

class ErrorsController {
def index() {
    def initialController = request.exception?.className
    if (initialController) {
        def controller = grailsApplication.getArtefact("Controller", initialController).getReferenceInstance()
        render "Controller: ${initialController}, annotations ${controller.getClass().getDeclaredAnnotations()}"
        return
    }
    render 'no initial controller'
}

}

request.exception? .className в сочетании с grailsApplication.getArtefact позволяет получить контроллер, из которого можно, например, извлечь аннотации

0 голосов
/ 11 марта 2013

Вы можете получить доступ к экземпляру Controller, который обрабатывал неверный запрос, через атрибут запроса org.codehaus.groovy.grails.CONTROLLER, например. (в ВСП):

Controller: ${request['org.codehaus.groovy.grails.CONTROLLER']}

Чтобы получить имя контроллера:

Controller name: ${request['org.codehaus.groovy.grails.CONTROLLER_NAME_ATTRIBUTE']}

Я проверил это в Grails 2.0 и 2.2, но я не могу найти его где-либо задокументированным, поэтому это может отличаться в разных версиях Grails. Чтобы увидеть все атрибуты, доступные в вашем запросе, добавьте следующее к error.gsp:

${${request.findAll { true }}
...