0

I have written an grails application, In UrlMappings.groovy file I have url mapping as

"500"(controller:"exception" , action:"internalServerError")

, so whenever any exception occurred I getting the exception in the ExceptionController but I need the payload and the url which throwed this exception , Is it possible to get that data.

vicky
  • 2,119
  • 4
  • 18
  • 32
  • 1
    Have you checked the `request` object that should be available in an action? – christopher Aug 31 '16 at 09:26
  • Yes , I tried but it is giving me null value . – vicky Aug 31 '16 at 10:14
  • The answer will depend on a number of factors. The body of the request can only be read once so if the original controller action has read the body, the exception handling action will not be able to. Solutions depend on details in the app. – Jeff Scott Brown Aug 31 '16 at 10:53
  • @JeffScottBrown , yeah i am reading the body in the original controller .Is there any other best way to get the payload in the exception handling action , as a temporary solution I am using "flash" to hold the data in original controller and fetch it in exception handling action 2. Is it possible to get the method name from which the exception is thrown . I don't see any property in request body of exception handling action. – vicky Aug 31 '16 at 13:22
  • "Is it possible to get the method name from which the exception is thrown" - Maybe. One way that may or may not work, depending on how the request was initiated and whether or not you are accessing the default action in the controller implicitly, `params.action` may be what you want. – Jeff Scott Brown Aug 31 '16 at 14:53
  • "as a temporary solution I am using "flash" to hold the data in original controller and fetch it in exception handling action 2" - Using `flash` for this is a bad idea because the data will remain there for a whole additional request. Depending on what you are really trying to do, a request attribute might be a better idea. – Jeff Scott Brown Aug 31 '16 at 14:54
  • Your situation really calls for a discussion. http://grails.slack.com or https://groups.google.com/forum/#!forum/grails-dev-discuss are better forums for that. – Jeff Scott Brown Aug 31 '16 at 14:54

2 Answers2

1

Hope this helps. This code is straight from default Grails installation

<g:if test="${Throwable.isInstance(exception)}">
            <g:renderException exception="${exception}" />
        </g:if>
        <g:elseif test="${request.getAttribute('javax.servlet.error.exception')}">
            <g:renderException exception="${request.getAttribute('javax.servlet.error.exception')}" />
        </g:elseif>
        <g:else>
            <ul class="errors">
                <li>An error has occurred</li>
                <li>Exception: ${exception}</li>
                <li>Message: ${message}</li>
                <li>Path: ${path}</li>
            </ul>
        </g:else>
elixir
  • 1,394
  • 1
  • 11
  • 21
1

in your exceptionController (when a 500 happened) you should be able to access the original URL via

request['javax.servlet.error.request_uri']

additionally you can get the requested URL in every controller via

request[RequestDispatcher.FORWARD_REQUEST_URI]

for accessing the request body after it has been consumed, you could use a solution as suggested in Accessing the raw body of a PUT or POST request but bear in mind that this of course has to keep the body in memory.

to get the originally called controller and action name inside your exceptionController, the only solution I know right now would be either:

class ExceptionController {
    def grailsUrlMappingsHolder

    internalServerError() {
        // request['javax.servlet.error.request_uri'] sometimes returns null?
        def url = request['javax.servlet.error.request_uri'] ?: request[RequestDispatcher.FORWARD_REQUEST_URI]
        def originalCall = url ? grailsUrlMappingsHolder.match(request['javax.servlet.error.request_uri'])?.paramss : [:]
        def controller = original?.controller
        def action = original?.action
        ...
    }
}

alternatively, by saving the first controller call in a filter like that:

class SaveFirstCallFilter {
    def filters = {
        all(controller:'*', action:'*') {
            before = {
                // don't want to overwrite when forwarding or including other actions
                if (!request['SAVED_CONTROLLER']) {
                    request['SAVED_CONTROLLER'] = controllerName
                    request['SAVED_CONTROLLER'] = actionName
                }
            }
        }
    }
}
Community
  • 1
  • 1
norganos
  • 141
  • 1
  • 8