Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use multiple ViewResolvers in Spring?

Tags:

I am working on a web app where I have most of my pages making use of apache tiles (2.1.2), but a few of them need to just be plain jsps.

I am having a problem in that both an InternalResourceViewResolver and a UrlBasedViewResolver will try to resolve the view no matter what, so that no matter which ordering I use, it will either fail on the plain JSP pages, or on the tiles pages.

Here is the config:

<bean id="tilesViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
    <property name="order" value="0"/>
</bean>

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/"/>
    <property name="suffix" value=".jsp"/>
    <property name="order" value="1"/>
</bean>

To make it more clear what I am trying to do, I need to be able to have view states like this:

<view-state id="someState" view="/someDir/foo"><!--render foo.jsp -->
    <transition on="foo" to="bar"/>
</view-state>

<view-state id="someState" view="something.core"><!--render tile defintion named 'something.core' -->
    <transition on="foo" to="bar"/>
</view-state>

Does anyone know how to configure things so that I can get it to render tiles definitions and plain jsps?

like image 697
TM. Avatar asked Jun 22 '09 20:06

TM.


People also ask

What is true regarding using multiple view resolver in spring application?

In case you want to use a Multiple View Resolver in a Spring MVC application then priority order can be set using the order property. The following example shows how to use the ResourceBundleViewResolver and the InternalResourceViewResolver in the Spring Web MVC Framework.

What are the different types of view resolver?

Below, we will discuss about three important View Resolver implementations provided by Spring MVC, InternalResourceViewResolver , XmlViewResolver and ResourceBundleViewResolver .

What are view resolvers in spring?

Spring provides view resolvers, which enable you to render models in a browser without tying you to a specific view technology. Out of the box, Spring enables you to use JSPs, Velocity templates and XSLT views, for example.

Which ViewResolver is assigned the lowest priority?

InternalResourceViewResolver can always map any request to the correct view, hence it has to be given the lowest priority. This way we give other View Resolver chance to resolve the view names.


2 Answers

As you say, you cannot chain these together. The javadoc for both states clearly that they must both be at the end of the resolver chain.

I suggest that if you really need to use these togather, then you write a simple custom implementation of ViewResolver which takes the view name, and decides which of your two "real" view resolvers to delegate to. This assumes that you can tell which resolver to call based on the view name.


So you'd define a custom ViewResolver like this:

public class MyViewResolver implements ViewResolver {

    private ViewResolver tilesResolver;
    private ViewResolver jspResolver;

    public void setJspResolver(ViewResolver jspResolver) {
        this.jspResolver = jspResolver;
    }

    public void setTilesResolver(ViewResolver tilesResolver) {
        this.tilesResolver = tilesResolver;
    }

    public View resolveViewName(String viewName, Locale locale) throws Exception {
        if (isTilesView(viewName)) {
            return tilesResolver.resolveViewName(viewName, locale);
        } else {
            return jspResolver.resolveViewName(viewName, locale);
        }
    }

    private boolean isTilesView(String viewName) {
    .....
    }
}

You'd need to implement the isTilesView method to decide which resolver to delegate to.

In the XML config, define this new view resolver, and make sure it appears before the other ones.

<bean class="MyViewResolver">
    <property name="tilesResolver" ref="tilesViewResolver"/>
    <property name="jspResolver" ref="viewResolver"/>
</bean>
like image 150
skaffman Avatar answered Oct 12 '22 00:10

skaffman


I've just solved the same problem by splitting the *-servlet.xml config file in two; in my case the main application uses Tiles, but I want QUnit tests to be simple JSPs.

app-servlet.xml contains only the Tiles view resolver, tests-servlet.xml only contains the JSP view resolver and web.xml mappings are dispatching requests to the correct servlet basing on the URL.

<servlet-mapping>
  <servlet-name>app</servlet-name> <!-- will reach app-servlet.xml -->
  <url-pattern>/foo</url-pattern> <!-- will use "foo" Tile -->
  <url-pattern>/bar</url-pattern> <!-- will use "bar" Tile -->
</servlet-mapping>

<servlet-mapping>
  <servlet-name>tests</servlet-name> <!-- will reach tests-servlet.xml -->
  <url-pattern>/foo-test</url-pattern> <!-- will use foo-test.jsp -->
  <url-pattern>/bar-test</url-pattern> <!-- will use bar-test.jsp -->
</servlet-mapping>
like image 21
kryger Avatar answered Oct 12 '22 02:10

kryger