Announcement Announcement Module
Collapse
No announcement yet.
Interceptor postHandle skipped on exception Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Interceptor postHandle skipped on exception

    I have a MVC restful spring application set up. I have an interceptor, @Controller, and @ExceptionHandler. When processing a correct request, everything works fine:
    1. preHandle
    2. Controller
    3. postHandle
    4. View
    5. afterCompletion

    But when an exception occurs in the Controller, the postHandle is skipped:
    1. preHandle
    2. Controller
    3. ExceptionHandler
    4. ExceptionView
    5. afterCompletion

    Is there a way to retain or manually call my postHandle stack when catching exceptions? Alternatively is there a way to specify that afterCompletion should be called with the Exception I've caught and handled? (I believe the Exception parameter to afterCompletion is normally set when the View throws an exception.)

    Thanks!

  • #2
    As far as I know the exception should be available but you could check the source code for the DispatcherServlet for that.

    Comment


    • #3
      Unfortunately it is not, but reading through DispatcherServlet gives me a number of ideas about how to make it work.

      An interceptor's postHandle is not called if:
      • any preHandle returns false
      • any preHandle throws an exception
      • ha.handle() throws an exception
      • a preceding postHandle throws an exception

      An interceptor's afterCompletion is always called unless a preceeding afterCompletion throws an exception.

      The easiest work-around is to make lemonaide and use the absence of the postHandle call as an indication that something untoward occurred.

      1) Set a request attribute (SUCCESS) in postHandle. If (SUCCESS) exists in afterCompletion, the call succeeded, otherwise it failed. This works OOTB.

      In order to call postHandle in the non-"sunny day" request cycle, we need to extend DispatcherServlet, override doDispatch, and accept that we might break backwards compatibility for interceptors.

      1) Add a new method triggerPostHandle() equivalent to triggerAfterCompletion() for postHandle.
      2) Call this method after preHandle returns false. (Fixes #1)
      3) Remove the postHandle stack iteration, and add a try/catch'd triggerPostHandle. (Fixes #2 and #3)
      4) This will still abort the postHandle iteration if some postHandle throws an exception (#4), but that's probably ok.

      It might be nice if postHandle() was extended to receive an Exception parameter. In the "sunny day" case this would be null, otherwise it could be used to have postHandle behave appropriately. This would require changes to HandlerInterceptor, etc.

      Comment


      • #4

        It might be nice if postHandle() was extended to receive an Exception parameter. In the "sunny day" case this would be null, otherwise it could be used to have postHandle behave appropriately. This would require changes to HandlerInterceptor, etc.
        Which isn't an option because as documented the postHandle is only called after succesful execution of the handler method in case of an exception this isn't the case.

        Also if you don't have a ExceptionHandlerViewResolver which handles the view the exception is passed to the afterCompletion method if there is a view to be rendered it is assumed request handling occured normally. So if you always want the exception to be passed in the easiest would be to change the behavior when an exception view is resolved to also pass in the exception to the afterCompletionm ethod. This would mean 2 new lines of code and 1 line changed.

        Comment


        • #5
          Marten, would you mind clarifying your comment?

          I am using ExceptionResolver that extends SimpleMappingExceptionResolver... The exception is handled, and when afterCompletion() is called, the exception is missing. It is probably not a good idea to call afterCompletion() directly from ExceptionResolver, or am I missing your point? How would you
          also pass in the exception to the afterCompletion method
          ?

          Thanks in advance!

          Comment

          Working...
          X