How to avoid handing over the same type of data to a view by multiple controllers using Spring MVC with tiles

StackOverflow https://stackoverflow.com/questions/17885184

  •  04-06-2022
  •  | 
  •  

Question

I have a Spring MVC 3 application which integrates tiles 3 to use a common view template for every page. For the sake of simplicity assume this template consists of a header, a body and a footer part. The header and footer parts always display the same type of data, which is retrieved from a database. The body part changes from request to request.

Since Spring MVC is based on an MVC architecture, my first idea was that each controller has to provide the data which is displayed in the header and footer part. This is ugly and feels not appropriate, because it leads to duplication of the same code in multiple controllers. Also, storing this type of data as session values seems not to be a good solution.

How is this problem usually solved?

Thanks a lot!

Was it helpful?

Solution

You could create an interceptor which will inject the common data into your model. A nice feature of using interceptors is that you can easily map them to URLs of your choice.

public class CommonDataInjectingInterceptor extends HandlerInterceptorAdapter {
    @Autowired
    private CommonDataHolder holder;

    public void setCommonDataHolder(CommonDataHolder holder) {
        this.holder = holder;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        if (holder != null && modelAndView != null) {
            modelAndView.addObject("menu", holder.getMenu());
            modelAndView.addObject("footer", holder.getFooter());
        }
    }
}

Another way could be to create a @ControllerAdvice which will define generic behavior shared across all controllers. The functionality of such @ControllerAdvice in Spring 3 is rather basic. Spring 4 introduces new options to control which controllers should be affected by it.

Using a @ControllerAdvice in combination with @ModelAttribute can be quite handy. Like Ayub Malik partially explained in his answer.

@ControllerAdvice
public class CommonDataControllerAdvice {
    @Autowired
    private CommonDataHolder holder;

    public void setCommonDataHolder(CommonDataHolder holder) {
        this.holder = holder;
    }

    @ModelAttribute("menu")
    public Menu menu() {
        return holder.getMenu();        
    }

    @ModelAttribute("footer")
    public Footer footer() {
        return holder.getFooter();
    }
}

Spring 3 ControllerAdvice:

http://docs.spring.io/spring/docs/3.2.7.RELEASE/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html

Spring 4 ControllerAdvice

http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html

OTHER TIPS

In your controller create a method (or methods) with the annotation @ModelAttribute.

e.g.

@ModelAttribute("someData")
public SomeData getData() {
   return new SomeData(); // init your common data here
}

This will make 'someData' available to your Tiles view layer.

You could then have an abstract base class with this method, if you need to reuse.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top