Monday, January 6, 2020

Spring MVC Configuring Multiple View Resolvers Example

In this post we’ll see how to configure multiple view resolvers with in Spring MVC application. In Spring MVC view resolver is used to resolve the view name without actually hardcoding the view file. That way you are not tightly coupled with a specific view technology.

Spring MVC framework also provides the flexibility to configure more than one view resolver.

Technologies used

Following is the list of tools used for this Spring MVC configuring multiple view resolvers example.

  • Spring 5.0.8 Release (Spring core, spring web, spring webmvc).
  • Java 10
  • Tomcat server V 9.0.10
  • Eclipse Photon 4.8.0 for Java EE development (This Eclipse version supports Java 10)

Spring MVC Project structure using Maven


Spring MVC configuring multiple view resolvers example

In this example we’ll configure three different view resolvers in our Spring MVC application to show multiple view resolvers in action. We’ll show both ways of configuration – XML configuration and Java Config.

Three View resolvers that are configured in the Spring MVC application are the following ones-

  • BeanNameViewResolver- A simple implementation of ViewResolver that interprets a view name as a bean name in the current application context.
  • ResourceBundleViewResolver- Implementation of ViewResolver that uses bean definitions in a ResourceBundle, specified by the bundle base name, and for each view it is supposed to resolve, it uses the value of the property [viewname].(class) as the view class and the value of the property [viewname].url as the view url.
  • InternalResourceViewResolver- A subclass of UrlBasedViewResolver that supports InternalResourceView (in effect, Servlets and JSPs) and subclasses such as JstlView and TilesView.

Spring MVC configuring multiple view resolvers – XML Configuration

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">
        
     <mvc:annotation-driven />
     <!-- <mvc:annotation-driven validator="validator"/> -->
     <context:component-scan base-package="org.netjs.controller" />
     <bean id="BeanViewResolver" class=
        "org.springframework.web.servlet.view.BeanNameViewResolver">
        <property name="order" value="0"/>
     </bean>
     <bean id="ResourceResolver" class=
        "org.springframework.web.servlet.view.ResourceBundleViewResolver">
         <property name="order" value="1"/>
        <property name="basename" value="views"/>
    </bean>
     <bean id="JSPViewResolver" class=
        "org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="order" value="2"/>
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
     <bean name="beanView" class="org.netjs.config.CustomView" />
</beans>

BeanNameViewResolver Spring configuration

Since BeanNameViewResolver interprets a view name as a bean name in the application context that is why there is this bean definition-

<bean name="beanView" class="org.netjs.config.CustomView" />

Corresponding handler method in the Controller class is as follows-

 @RequestMapping(value = "/showMsg", method = RequestMethod.GET)
 public String showMessage(Model model) throws Exception{
  model.addAttribute("msg", "Configuring multiple view resolver example");
  return "beanView";
 }

From the handler method view name is returned as “beanView” which means View for this handler method resolves to CustomView class.

CustomView class

CustomView class implements View interface and provides implementation of the render() method which is used to render view.

public class CustomView implements View {
    
    @Override
    public void render(Map<String, ?> model, HttpServletRequest request, 
            HttpServletResponse response) throws Exception {
        response.setContentType("text/html");
        PrintWriter writer = response.getWriter();
        writer.println("This is a custom view for BeanNameViewResolver <br />");
        writer.print("<b>Message- </b>" + model.get("msg"));
    }
}

ResourceBundleViewResolver Spring configuration

For ResourceBundleViewResolver bean “basename” property has the value views which means properties file is named views.properties file.

views.properties

msg.(class)=org.springframework.web.servlet.view.JstlView
msg.url=/WEB-INF/jsp/message.jsp

Here view URL is “/WEB-INF/jsp/message.jsp” so a JSP with the same name should be present at that location.

Corresponding handler method in the Controller class is as follows-

 @RequestMapping(value = "/showResource", method = RequestMethod.GET)
 public String showResource(Model model) throws Exception{
  model.addAttribute("msg", "Configuring ResourceBundleViewResolver example");
  return "msg";
 }

From the handler method, view name is returned as “msg” which is found in the views.properties file.

message.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Spring MVC ResourceBundle view</title>
</head>
<body>
<h3>Spring MVC configuring multiple resolvers example</h3>
<b>Message</b> - <span>${msg}</span>
</body>
</html>

InternalResourceViewResolver Spring configuration

Another view resolver InternalResourceViewResolver is used to resolve the view name to JSPs.

Corresponding handler method in the Controller class is as follows-

 @RequestMapping(value = "/showUser", method = RequestMethod.GET)
 public String showUser(Model model) throws Exception{
  User user = new User("Leonard", "Nemoy", "ln@st.com");
  model.addAttribute("user", user);
  return "user";
 }

From the handler method, view name is returned as “user” which resolves to the JSP /WEB-INF/jsp/user.jsp

user.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Spring MVC tutorial - User</title>
</head>
<body>
<table>
<tr>
<td><b>First Name</b> - <span>${user.firstName}</span></td>
</tr>
<tr>
<td><b>Last Name</b> - <span>${user.lastName}</span></td>
</tr>
<tr>
<td><b>Email</b> - <span>${user.email}</span></td>    
</tr>
</table>
</body>
</html>

Model class – User.java

public class User {

 private String firstName;
 private String lastName;
 private String email;

 public User() {
  
 }
 public User(String firstName, String lastName, String email) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.email = email;
 }
 
 public String getFirstName() {
  return firstName;
 }
 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }
 public String getLastName() {
  return lastName;
 }
 public void setLastName(String lastName) {
  this.lastName = lastName;
 }
 public String getEmail() {
  return email;
 }
 public void setEmail(String email) {
  this.email = email;
 }
}

Spring MVC configuring multiple view resolvers – Controller class

Here is the full controller class.

@Controller
public class MultiViewController {
 @RequestMapping(value = "/showMsg", method = RequestMethod.GET)
 public String showMessage(Model model) throws Exception{
  model.addAttribute("msg", "Configuring multiple view resolver example");
  return "beanView";
 }
 
 @RequestMapping(value = "/showUser", method = RequestMethod.GET)
 public String showUser(Model model) throws Exception{
  User user = new User("Leonard", "Nemoy", "ln@st.com");
  model.addAttribute("user", user);
  return "user";
 }
 
 @RequestMapping(value = "/showResource", method = RequestMethod.GET)
 public String showResource(Model model) throws Exception{
  model.addAttribute("msg", "Configuring ResourceBundleViewResolver example");
  return "msg";
 }
}

Spring MVC configuring multiple view resolvers – Java configuration

If you are using Java configuration then same configuration as seen above using XML configuration can be written as following-

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.BeanNameViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.ResourceBundleViewResolver;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages="org.netjs.controller")
public class WebConfig implements WebMvcConfigurer {
 
 @Bean
 public ViewResolver viewResolver() {
  InternalResourceViewResolver resolver = new InternalResourceViewResolver();
  resolver.setPrefix("/WEB-INF/jsp/");
  resolver.setSuffix(".jsp");
  resolver.setOrder(3);
  return resolver;
 }
 @Bean
 public ViewResolver resourceResolver() {
  ResourceBundleViewResolver resourceResolver = new ResourceBundleViewResolver();
  resourceResolver.setBasename("views");
  resourceResolver.setOrder(2);
  return resourceResolver;
 }
 
 @Bean
 public ViewResolver beanViewResolver() {
  BeanNameViewResolver beanResolver = new BeanNameViewResolver();
  beanResolver.setOrder(1);
  return beanResolver;
 }
 @Bean("beanView")
 public View customView() {
  return new CustomView();
 }
 /**
  * Configure a handler to delegate unhandled requests by forwarding to the
  * Servlet container's "default" servlet. A common use case for this is when
  * the {@link DispatcherServlet} is mapped to "/" thus overriding the
  * Servlet container's default handling of static resources.
  */
 public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
  configurer.enable();
 }
 
}

Setting order property for resolvers

Here note that the Resolvers have a property order set too which decides the priority. Lower order value means higher priority. Here BeanNameViewResolver has order property set as 0 which means Spring framework will first try to resolve view using this class.

As a rule InternalResourceViewResolver should always have higher order among all view resolvers value because it will always be resolved to view irrespective of value returned giving no chance to any other Resolver class.

Deploying and testing the application

Once the application is deployed to Tomcat server it can be accessed as shown below-

For BeanNameViewResolver (http://localhost:8080/spring-mvc/showMsg)

Spring MVC Configuring Multiple View Resolvers

For ResourceBundleViewResolver (http://localhost:8080/spring-mvc/showResource)

Configuring Multiple View Resolvers

For InternalResourceViewResolver (http://localhost:8080/spring-mvc/showUser)

Configuring Multiple View Resolvers in Spring MVC

That's all for this topic Spring MVC Configuring Multiple View Resolvers Example. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Spring MVC PDF Generation Example
  2. Spring MVC Generate Response as JSON Example
  3. Spring MVC Form Example With Bean Validation
  4. Difference Between @Controller And @RestController Annotations in Spring
  5. Spring Batch Processing With List of Objects in batchUpdate() Method

You may also like-

  1. Select Query Using NamedParameterJDBCTemplate in Spring Framework
  2. Wiring Collections in Spring
  3. How to Inject Null And Empty String Values in Spring
  4. Bean Definition Inheritance in Spring
  5. Difference Between ArrayList And CopyOnWriteArrayList in Java
  6. Phaser in Java Concurrency
  7. Difference Between Encapsulation And Abstraction in Java
  8. Java Lambda Expression Comparator Example