Chaining multiple view resolvers in Spring – using two InternalResourceViewResolver

3 min read >

Chaining multiple view resolvers in Spring – using two InternalResourceViewResolver

Enterprise solutions

Spring allows chaining of multiple view resolvers. However, there are some view resolvers like the ones extending UrlBasedViewResolver which must be the last in the chain, hence the limitation of having only one such view resolver in your chain.
Javadoc for UrlBasedViewResolver mentions: “Note: When chaining ViewResolvers, a UrlBasedViewResolver always needs to be last, as it will attempt to resolve any view name, no matter whether the underlying resource actually exists.”

There are however situations in which one needs chaining multiple view resolvers such as InternalResourceViewResolver or UrlBasedViewResolver. For example, you need to support views returned both as JSP pages and Tiles layouts.

Chaining two InternalResourceViewResolver won’t do the job, since the first one will always try to resolve your view, and it will fail either on the JSP page or Tiles layout.

In order to support this feature, you have to write your own view resolver extending UrlBasedViewResolver. Here’s an idea of how you can chain these resolvers: your custom view resolver can analyze the view returned by your Spring MVC controller and check its name. If its name contains the suffix “.layout”, your ViewResolver will pass control to the other view resolvers in the chain. Here’s a sample code:

/**
* Custom view resolver – checks if view name contains string layout, in which case lets the request
* reach the other view resolvers in the chain
*
* @author Marius Hanganu
*/
public class MyViewResolver extends UrlBasedViewResolver implements Ordered {
    /**
    * Overrides loadView in UrlBasedViewResolver to be able to make a     difference when letting the other views
    * in the chaing take control of the request
    *
    * @see org.springframework.web.servlet.view.UrlBasedViewResolver#loadView(String,java.util.Locale)
    */
    protected View loadView(String viewName, Locale locale) throws Exception {
    AbstractUrlBasedView view = buildView(viewName);
    View viewObj = (View)     getApplicationContext().getAutowireCapableBeanFactory().initializeBean(view, viewName);
        if (viewObj instanceof JstlView) {
            JstlView jv = (JstlView) viewObj;
            if (jv.getBeanName().indexOf(“layout”) != -1) {
                return null;
            }
        }

        return viewObj;
    }
}

The only other thing one needs to do is to declare the view resolvers.

<bean id=”viewResolver” class=”ro.tremend.bigg.web.spring.BiggViewResolver”>
    <property name=”order” value=”1″/>
    <property name=”viewClass” value=”org.springframework.web.servlet.view.JstlView”/>
    <property name=”prefix” value=”/WEB-INF/jsp/”/>
    <property name=”suffix” value=”.jsp”/>
</bean>

<bean id=”tilesViewResolver” class=”org.springframework.web.servlet.view.InternalResourceViewResolver”>
    <property name=”order” value=”2″/>
    <property name=”requestContextAttribute” value=”requestContext”/>
    <property name=”viewClass” value=”org.springframework.web.servlet.view.tiles.TilesJstlView”/>
</bean>