Announcement Announcement Module
Collapse
No announcement yet.
Why is intereceptor postHandle method getting invoked after page is rendered Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Why is intereceptor postHandle method getting invoked after page is rendered

    My Spring MVC web app has a navigation menu at the top of the page with links to a list of items. The list of items is retrieved from the database. This menu is common to all pages in the application. Currently, in every controller, I retrieve and store the list of items in session (if not already in session), so that it is available on every page. It works fine, but I feel this there should be a better way to do this. To avoid this redundancy, I am now trying to use a HandlerInterceptorAdapter. I am able to get it work, but not perfectly. The first time I load the page, I do not see the object I set in session. But, if I refresh the page, I do see the object in session.

    I created my interceptor this way:
    Code:
    public class MyHandlerInterceptor extends HandlerInterceptorAdapter {
      private MyService myService;
    
      //Constructor
      public MyHandlerInterceptor(MyService myService) {
            this.myService = myService;
      }
      
      //Overridden method
      public void postHandle(HttpServletRequest request, 
                             HttpServletResponse response, 
                             Object handler, 
                             ModelAndView modelAndView) throws Exception {
        System.out.println("In posthandle...");
    
        if (request.getSession().getAttribute("items") == null) {
          request.getSession().setAttribute("items", myService.getCategories());
        }
      }
    }
    I declared the interceptor:
    Code:
    <mvc:interceptors>
      <bean class="com.gyanify.webapp.interceptors.MyHandlerInterceptor"
            autowire="constructor"/>
    </mvc:interceptors>
    I am checking if the object is set in session by the time the jsp renders:
    Code:
    ...
    Session Attributes <br/>
    <%
    	System.out.println("Printing from the jsp...");
    	Enumeration keys = session.getAttributeNames();
    	while (keys.hasMoreElements())
    	{
    	  String key = (String)keys.nextElement();
    	  out.println(key + ": " + session.getValue(key) + "<br>");
    	}
    %>
    ...

    With that, when I first load the page, I see the following print in the console:
    Code:
    ...
    Returning view....(this is printed from the controller)
    Printing from the jsp...
    In posthandle...
    ...
    My understanding is that the posthandle method is invoked before the page is rendered. However, according to the output on the console, I see that the jsp is being rendered before the interceptor's posthandle method.

    Can anyone help me understand why it is behaving this way?

  • #2
    On further investigation, I found the issue to be in the way I configured my spring context xml files. I had two files - one for the application context and the other for the web context. Initially I defined the component-scan and mv:annotation-driven tags in the application context xml:
    Code:
    <context:component-scan base-package="com.webapp" />
    <mvc:annotation-driven validator="validator"/>
    and defined my interceptors in the web context xml.

    In the debug mode, I saw that the interceptors were getting mapped to the context after the request is processed.

    To make it work, I changed the configuration in the application context to the following:
    Code:
    <context:component-scan base-package="com.webapp">
      <context:exclude-filter type="regex" expression="com\.webapp\.controllers\.*"/>
    </context:component-scan>
    and added the following to the web context xml:
    Code:
    <context:component-scan base-package="com.webapp.controllers" />
    <mvc:annotation-driven validator="validator"/>
    I am still trying to understand why this worked and the earlier configuration did not.

    Comment


    • #3
      The execution of the interceptors are part of the HandlerAdapters lifecycle and you basically had 2 sets of those configured. 1 in the root context (application-context.xml) which don't know anything of the beans in the child context (dispatcher-servlet).

      There are also some defaults registered by the DispatcherServlet and probably some other URL triggers the handling of that request which cannot be handled by the configuration/handlers in the root context and as such will get executed by the ones in the DispatcherServlet.

      Comment

      Working...
      X