Using HandlerInterceptor or ControllerAdvice to Make Spring MVC Model Attribute Available Everywhere

Often you’ll want a particular model attribute to be available everywhere (eg: application version, name, etc). Doing model.addAttribute() everytime is a really bad idea, if you have to refactor it down the track you could end up with hundreds of line modification scattered everywhere.

Using ControllerAdvice

One simple way to achieve this as outlined by Spring documentation is by using Spring 3.1’s e annotation.

Create a new class like this:

e
public class PopulateGlobalAttribute {
  ("appversion")
  public String getAppVersion() {
    return "1.0";
  }
}

And the getAppVersion() will be used to help each handler method in all controllers to add additional stuff to Model object.

However this method poses one problem. If the handler method is returning a redirect view, the model attributes will be exposed as a query string on the browser URL.

Using HandlerInterceptor

Fortunately Josh Kalderimis proposes a nice solution on his blog post using HandlerInterceptor.

This is my own version of HandlerInterceptor which is based from Josh’s:

public class PopulateGlobalAttrInterceptor implements HandlerInterceptor {
  private Map properties = new HashMap();

  /**
   * This method ensures the global attributes are added only for non-redirection view / view name
   */
  
  public void postHandle(HttpServletRequest req, HttpServletResponse res, Object handler,
      ModelAndView mav) throws Exception {
    if(mav == null) return;

    boolean isRedirectView = mav.getView() instanceof RedirectView;
    boolean isViewObject = mav.getView() != null;
    boolean viewNameStartsWithRedirect = (mav.getViewName() == null ? true : 
      mav.getViewName().startsWith(UrlBasedViewResolver.REDIRECT_URL_PREFIX));
    
    if(mav.hasView() && (
      ( isViewObject && !isRedirectView) ||
      (!isViewObject && !viewNameStartsWithRedirect))){
        addCommonModelData(mav);
    }
  }

  private void addCommonModelData(ModelAndView mav) {
    mav.getModel().putAll(properties);
  }

  
  public void afterCompletion(HttpServletRequest req, HttpServletResponse res, Object handler,
      Exception ex) throws Exception {
  }

  
  public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler)
      throws Exception {
    return true;
  }

  /* getters & setters */
}

In SpringMVC HandlerInterceptors are similar like servlet filters, it will be used to filter (intercept) through every requests. Similar like ControllerAdvice, the postHandle method will be invoked by all handlers to help populate the model.

Once you have this you need to register this interceptors. If you use xml based configuration you can do something like this:



  ...

  

  
    
      
        
      
    
  

  
    
  
  ...

Now without any additional code, you’re guaranteed ${appversion} is available everywhere on your jsp view.

Leave a Reply