Announcement Announcement Module
Collapse
No announcement yet.
Spring MVC Exception handling Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring MVC Exception handling

    Currently I let my exceptions to bubble up and be captured by a class which extends HandlerExceptionResolver. The issue is that due to this approach the post handlers of different interceptors are not called (I think I understand why that is happening).
    Is there away to handle exceptions so that after catching the exception the normal sequence of interceptors (i.e. there post handlers) are appropriately called.

    Thanks

    I would like to mention that all the controllers that have been implemented extend a base class, which currently does nothing.

  • #2
    post handle will only be called after successful completion of the call, an exception is not a successful completion of the call. The afterCompletion method is always called for interceptors for which the preHandle method was successfully invoked.

    Comment


    • #3
      Thanks for the reply.
      Could someone please clarify if afterCompletion is called after postHandle of all the interceptors have been called or immediately after the postHandle of an interceptor is called. e.g if there are two interceptors I1, I2 defined in given order, then the execution would be:
      Way 1: I1.pre, I2.pre, ......, I2.post, I2.after, I1.post, I1.after
      Way 2: I1.pre, I2.pre, ......, I2.post, I1.post, I2.after, I1.after (if this is the scenario then the approach of using afterCompletion will be of no use as I need to put stuff in the response despite any exception) (Edit: It seems that it is the way)

      Also I would like to render a ModelAndView if an exception occurrs. But on using afterCompletion I am not able to figure out how to do that. Although I have read on internet that on using afterCompletion we need to render the view our self, but am not able to figure out how to do so. (I would like to somehow manipulate the ModelAndView instead of writing a custom page to the response.)

      Thanks for any help.
      Last edited by pareshverma91; Jun 12th, 2012, 08:23 AM.

      Comment


      • #4
        You cannot render a view from/in afterCompletion as that is called after the view has rendered. (I strongly suggest a read of the reference guide as that explains the flow for the interceptors).

        The HandlerExceptionResolver is responsible for filling the ModelAndView (it is the return type of the resolveException method).

        Comment


        • #5
          I am already using HandlerExceptionResolver. My use case is that irrespective of what happens inside a controller, the postHandlers should be called. I understand that for this I need to handle all the exceptions that occur in the controller, but my issue is for requests made to non-existent mappings. I am not able to figure out a way to execute the HandlerExceptionResolver before the postHandlers (is it really possible?)

          Comment


          • #6
            Interceptors are only called on existing mappings, for something where there is no mapping there is no interceptor called. The same goes for the HandlerExceptionResolver, it is called HandlerExceptionResolver for a reason, if there is no handler there is no exception going to be resolved, as no handler leads to a 404...

            Could you elaborate on your usecase as I'm a bit lost on what you are trying to do.

            Comment


            • #7
              I have been able to handle all the non-specified mappings while ensuring that the interceptors are called, by creating a dummy method in a controller with RequestMapping as "/**". This way all the requests map to it if no other match is provided. One problem resolved.

              Now my use case is that the methods in my controllers can possibly throw an exception, but still I would like that the postHandler of all the interceptors is called. One of the way would be to put a try-catch in all the methods. But what I am looking for is something such that after an exception is raised instead of bubbling to my ExceptionHandlerResolver, and missing the postHandler's, exception should be caught somewhere in between so that I could return a ModelAndView and after that the postHandle's are called normally (as the exception never reached them).

              I have tried annotating a method of the controller with @ExceptionHandler, but it seems to be of no use as postHandlers are not being called.

              Thanks for your help.

              Comment


              • #8
                As mentioned before that isn't possible as that isn't the flow for HandlerInterceptors... You cannot change that flow unless you rewrite part of the DispatcherServlet...

                Succesful flow
                Code:
                HandlerInterceptor.preHandle
                HandlerAdapter.handle
                HandlerInterceptor.postHandle
                View.render
                HandlerInterceptor.afterCompletion
                Exceptional flow
                Code:
                HandlerInterceptor.preHandle
                HandlerAdapter.handle
                HandlerExceptionResolver.resolveException
                View.render
                HandlerInterceptor.afterCompletion
                This is what happens and which is coded into the DispatcherServlet, so if you want to change that you need to rewrite part of the DispatcherServlet.

                Also mapping something to /** is inherently dangerous especially if your DispatcherServlet is also mapped to /* or / as that could disable correct resolving of static files.

                You still haven't explained your use case only the technical difficulties/solution of your use case.. What is it that you want to accomplish?!

                Comment


                • #9
                  Precisely this is what has been achieved:
                  Currently there is a single interceptor whose postHandle adds a list of string to the webpage. This list of string depends on the environment in which the system runs (effectively meaning that it can't be added statically). Now the site user is free to select one of these strings and branch out of current operations. The list of strings decide a portion of the URL and user can anytime select one of these strings and hence be redirected to a page related to that. Thus what I want is that whatsover may happen, this list of strings should always be added to the ModelAndView that is being rendered (the list is added as an object to the returning ModelAndView).

                  I could specify the list to be added in the ExceptionResolver, but I dont't know how many such things would be added in future and it would be cumbersome to add same information at two places. Since I want all the requests to get the list of strings, I am using the postHandle of interceptors and hence my issue.

                  Could you also please point me to some text related to dangers of "/**" while using "/" and "/*" (I am using both of these). I tested a few combinations and it seems to work fine. As far as static files are concerned I am not able to figure out why there could be an error as according to the Ant pattern documentation /** should cover all the directories and files.
                  Thanks for you time.

                  Comment


                  • #10

                    Could you also please point me to some text related to dangers of "/**" while using "/" and "/*" (I am using both of these). I tested a few combinations and it seems to work fine. As far as static files are concerned I am not able to figure out why there could be an error as according to the Ant pattern documentation /** should cover all the directories and files.
                    There isn't any. It simply could disable the delegation to the underlying container, as long as you have spring serve your static files that shouldn't be a problem.

                    Currently there is a single interceptor whose postHandle adds a list of string to the webpage. This list of string depends on the environment in which the system runs (effectively meaning that it can't be added statically). Now the site user is free to select one of these strings and branch out of current operations. The list of strings decide a portion of the URL and user can anytime select one of these strings and hence be redirected to a page related to that. Thus what I want is that whatsover may happen, this list of strings should always be added to the ModelAndView that is being rendered (the list is added as an object to the returning ModelAndView).
                    Instead of using a HandlerInterceptor you could use a Filter to add those strings to the request, especially because you seem to want it to be added to all requests that are executed by the DispatcherServlet. You currently have a hack (the controller which is a catch all - do nothing controller) to make that possible. I would simply remove the HandlerInterceptor and put the logic in a Filter (in a finally block after the execution of the chain or before you execute the chain). That way it would simply execute for each incoming request regardless of what the outcome is..

                    Comment


                    • #11
                      I need to add content to the response. Am I missing stth here?

                      Comment

                      Working...
                      X