Enterprise Java

Configure multiple View Resolvers in Spring

1. Introduction

In Spring, the View Resolver is provided to resolve the view with the data available in the model, without tightly binding to a View technology, be it JSP, Velocity or Thymeleaf. Spring makes it easy and flexible to configure one or multiple View Resolvers, as per the need would be.

2. Spring MVC application flow

Before we proceed with understanding how multiple View Resolvers serve the purpose, lets take a quick recap of the Spring MVC application flow.

  1. Incoming request comes through web.xml, dispatcher servlet and hits the controller.
  2. Controller interacts with the application layers and prepares the model.
  3. Controller returns the ModelAndView, with model and the view name.
  4. The ViewResolver provides a mapping between view names and actual views.
  5. The View interface addresses the request of a view to respective View technology.
  6. The view is then rendered onto the browser along with the model data.

3. Implementation

Let’s start with the pom dependencies.

pom.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!-- Spring 3 dependencies -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>${spring.version}</version>
</dependency>
  
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${spring.version}</version>
</dependency>
  
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
</dependency>
  
<!-- Jackson JSON Mapper -->
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>${jackson.version}</version>
</dependency>
  
<!-- JSTL Dependency -->
<dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>${jstl.version}</version>
</dependency>

Not much change in the web.xml.

web.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="ISO-8859-1"?>
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    id="WebApp_ID" version="2.5">
  
    <display-name>MultipleViewResolversExample</display-name>
  
    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
  
    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/API/*</url-pattern>
    </servlet-mapping>
  
</web-app>

Here is the mvc-dispatcher-servlet, which has multiple View Resolvers defined.

mvc-dispatcher-servlet.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  
    <mvc:annotation-driven />
    <context:component-scan base-package="com.jcombat.controller" />
  
    <!-- Bean View Resolver -->
    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
        <property name="order" value="0" />
    </bean>
  
    <!-- JSP View Resolver -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
        <property name="order" value="1" />
    </bean>
  
    <bean name="jsonView"
        class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
  
</beans>

Note that the two View Resolvers configured are InternalResourceViewResolver and BeanNameViewResolver. We have also set the priorities using the order property of the View Resolver. So BeanNameViewResolver has a higher priority. This means that when the ModelAndView object is returned, the BeanNameViewResolver checks for the available bean views with the view name that is returned. If the matching bean view is found, it is rendered. If not, the next View Resolver i.e. InternalResourceViewResolver, comes into the picture, and similarly checks for the JSPs with the view name that is returned with ModelAndView. If it is found, the view is rendered. But if not, and there is no more View Resolvers down the hierarchy, an appropriate exception is thrown.

Moving ahead with the implemetation, we have the same Employee entity class, as we have been using recently.

Employee.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
package com.jcombat.bean;
  
public class Employee {
    private String empId;
    private String name;
     
    public String getEmpId() {
        return empId;
    }
    public void setEmpId(String empId) {
        this.empId = empId;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

Let’s now write down the EmployeeController.

EmployeeController.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.jcombat.controller;
  
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
  
import com.jcombat.bean.Employee;
  
@Controller
@RequestMapping(value = "/Employee")
public class EmployeeController {
  
    @RequestMapping(value = "/{name}/{empId}", method = RequestMethod.GET)
    public ModelAndView process(
            @PathVariable("name") String name,
            @PathVariable("empId") String empId) {
        ModelAndView modelAndView = new ModelAndView();
        Employee employee = new Employee();
        employee.setEmpId(empId);
        employee.setName(name);
        modelAndView.setViewName("employeeDetails");
        modelAndView.addObject("employee", employee);
        return modelAndView;
    }
}

We now make sure the JSP with the view name – employeeDetails, exists.

employeeDetails.jsp

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Via JSP View Resolver</title>
    </head>
    <body>
        <!-- Retrieve the model data through JSTL -->
        <p>${employee.empId}</p>
        <p>${employee.name}</p>
    </body>
</html>

4. Running the application

When we run the application, below is what we see.

Snap1

Note that we don’t have any bean view with name employeeDetails, but rather matches with the actual JSP view file employeeDetails.jsp. Hence, the view gets resolved as JSP.

Now let’s return the view name as jsonView, modifying the below statement in the controller method.

1
modelAndView.setViewName("jsonView");

BeanNameViewResolver being higher in priority, this time finds the bean view with the name jsonView, and instead of rendering the JSP view, the same URI now returns a JSON.

Snap2

5. Download the source code

Reference: Configure multiple View Resolvers in Spring from our JCG partner Abhimanyu Prasad at the jCombat blog.
Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy

Abhimanyu Prasad

Abhimanyu is a passionate tech blogger and senior programmer, who has an extensive end-to-end development experience with wide range of technologies. He is the founder and administrator at jCombat.
Subscribe
Notify of
guest


This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Gelin Luo
8 years ago

Hi Abhimanyu, I can get your attention to ActFramework (http://actframework.org)? Although I’ve just released the first version to maven central repository, it has been put into comercial usage for 1 years. I suppose most feature SpringBoot provided in a better and simpler way. Take for the Multiple view as an example, the developer doesn’t need to configure anything, just put the different resource folder root that matches the view engine id. Here is the sample app demonstrate using multiple view engine in an ACT application: https://github.com/actframework/act-demo-apps/tree/master/views There are some other links you might feel interesting: 1. TechEmpower(https://www.techempower.com/benchmarks/) ACT test bed… Read more »

Back to top button