Master java skills

Spring MVC

MVC stands for Model-View-Controller. This module of Spring framework is used to build web applications. Model represents data, View represents view files (html, jsp), whereas Controller represents java classes that have logic to process the incoming requests.

The core of Spring MVC is DispatcherServlet class. It works as the front controller in the web application, meaning all the incoming requests are first intercepted by DispatcherServlet. Then it maps the request to the appropriate Controller. Let’s understand the flow of Spring MVC using the below diagram.

Spring MVC flow

  1. As the request comes for the web application, it is intercepted by DispatcherServlet.
  2. By analyzing the url, the DispatcherServlet with the help of HandlerMapping finds out the appropriate controller that can serve the request, and forwards the request to it.
  3. After processing the request, the controller generates a ModelAndView object that contains the data and the view information.
  4. With the help of ViewResolver and ModelAndView object, DispatcherServlet gets the information of the right view file (html, jsp etc)
  5. View is generated with data and given back as the response to the browser.

Spring MVC Example

  1. Create a maven project using the archetype ‘spring-mvc-archetype‘ with groupId ‘co.ntier‘. If you want to learn how to create a maven project using archetype, click here. Project structure should look like below

pom.xml

2. Since we have created the project using archetype, the pom.xml will have all the required dependencies. If you have created the project without archetype, then add the following dependencies.

	<properties>
		<java.version>1.7</java.version>
		<spring.version>3.1.0.RELEASE</spring.version>
		<cglib.version>2.2.2</cglib.version>
	</properties>
	
	<dependencies>
		<!-- Spring core & mvc -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib-nodep</artifactId>
			<version>${cglib.version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.4</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.1</version>
			<scope>provided</scope>
		</dependency>
		
	</dependencies>

web.xml

3. Update web.xml to add DispatcherServlet entry. Since we have created the project using maven archetype, this entry would already be there

Just make sure package name is correct for contextConfigLocation. For this example, it is com.sks

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
  <display-name>spring-mvc-app</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  
  
  <servlet>
		<servlet-name>SpringDispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextClass</param-name>
			<param-value>
				org.springframework.web.context.support.AnnotationConfigWebApplicationContext
			</param-value>
		</init-param>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>com.sks</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
  </servlet>
  
  <servlet-mapping>
		<servlet-name>SpringDispatcher</servlet-name>
		<url-pattern>/</url-pattern>
  </servlet-mapping>
  
    <context-param>
		<param-name>contextClass</param-name>
		<param-value>
			org.springframework.web.context.support.AnnotationConfigWebApplicationContext
		</param-value>
	</context-param>
	
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
  
  
</web-app>

Spring MVC bean configuration class in package com.sks.config

Create a java class named MvcConfiguration.java. Make sure to keep correct name for basePackages attribute of @ComponentScan. For this example, it is com.javatrainingschool

package com.sks.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@ComponentScan(basePackages = "com.sks")
@EnableWebMvc
public class MvcConfiguration extends WebMvcConfigurerAdapter{
	
	@Bean
	public ViewResolver getViewResolver(){
		InternalResourceViewResolver resolver = new InternalResourceViewResolver();
		resolver.setPrefix("/WEB-INF/views/");
		resolver.setSuffix(".jsp");
		return resolver;
	}
	
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
	}

}

Create model class Drink in package com.sks.model

package com.sks.model;

public class Drink {

	private int id;
	private String name;
	private String type;
	
	
	//getters and setters
	//constructors
	//toString
}

Create DrinkController class in package com.sks.controller

package com.sks.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
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.sks.model.Drink;
import com.sks.service.DrinkService;

@Controller
@RequestMapping("/drink")
public class DrinkController {
	
	@Autowired
	private DrinkService service;
	
	
	@RequestMapping("/display")
	public ModelAndView displayAllDrinks() {
		
		ModelAndView mv = new ModelAndView("displayDrink");  //WEB-INF/views/getAllDrinks.jsp
		
		List<Drink> drinks = service.getAllDrinks();
		
		mv.addObject("drinks", drinks);
		
		return mv;
	}
	
	@RequestMapping("/addDrink")
	public ModelAndView displayAddDrinkPage() {
		
		ModelAndView mv = new ModelAndView("addDrink");
		Drink drink = new Drink();
		
		mv.addObject("command", drink);
		
		return mv;
	}
	
	@RequestMapping(value = "/saveDrink", method = RequestMethod.POST)
	public ModelAndView saveDrink(@ModelAttribute("drink") Drink drink) {
		
		ModelAndView mv = new ModelAndView("displayDrink");
		String action = service.addOrUpdateDrink(drink);
		List<Drink> drinks = service.getAllDrinks();
		mv.addObject("drinks", drinks);
		mv.addObject("msg", drink.getName() + 
				("add".equals(action) ? " added successfully" : " updated successfully"));
		return mv;
	}
	

}

Create DrinkService class in package com.sks.service

package com.sks.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Service;

import com.sks.model.Drink;

@Service
public class DrinkService {

	private static List<Drink> drinks = new ArrayList<Drink>();
	
	static {
		Drink d1 = new Drink(1, "Cappuccino", "Hot Beverage");
		Drink d2 = new Drink(2, "Cappi Nirvana", "Cold Beverage");
		Drink d3 = new Drink(3, "Ginger Tea", "Hot Beverage");
		Drink d4 = new Drink(4, "Cafe Latte", "Hot Beverage");
		drinks.add(d1);
		drinks.add(d2);
		drinks.add(d3);
		drinks.add(d4);
	}
	
	public Drink getDrinkById(int id) {
		Drink drink = null;
		for(Drink d : drinks) {
			if(id == d.getId()) {
				drink = d;
				break;
			}
		}
		return drink;
	}
	
	public List<Drink> getAllDrinks(){
		return drinks;
	}
	
	public String addOrUpdateDrink(Drink drink){
		String action = "add";
		for(Drink d : drinks) {
			if(d.getId() == drink.getId()) {
				drinks.remove(d);
				action = "update";
				break;
			}
		}
		drinks.add(drink);
		return action;
	}
	
	
	
}

Create addDrink.jsp file under WEB-INF/views folder

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>


<html>
<body>
	<h1>Add Drink</h1>
	<form:form method="post" action="saveDrink">
		<table>
			<tr>
				<td>Drink Id :</td>
				<td><form:input path="id" /></td>
			</tr>
			<tr>
				<td>Drink Name :</td>
				<td><form:input path="name" /></td>
			</tr>
			<tr>
				<td>Drink Type :</td>
				<td><form:input path="type" /></td>
			</tr>
			<tr>
				<td></td>
				<td><input type="submit" value="Save Drink" /></td>
			</tr>
		</table>
	</form:form>
</body>
</html>

Create displayDrink.jsp file under WEB-INF/views folder

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<html>
<body>

	<h1>Drinks Menu</h1><br>
	<div> ${msg}  </div><br>
	<table border="2" width="70%" cellpadding="2">
		<tr>
			<th>Id</th>
			<th>Drink Name</th>
			<th>Drink Type</th>
			<th>Edit</th>
			<th>Delete</th>
		</tr>
		<c:forEach var="drink" items="${drinks}">
			<tr>
				<td>${drink.id}</td>
				<td>${drink.name}</td>
				<td>${drink.type}</td>
				<td><a href="${pageContext.request.contextPath}/drink/edit/${drink.id}">Edit</a></td>
				<td><a href="${pageContext.request.contextPath}/drink/delete/${drink.id}">Delete</a></td>
			</tr>
		</c:forEach>
	</table>
	<br />
	<a href="${pageContext.request.contextPath}/drink/addDrink">Add a Drink</a>
</body>
</html>

editDrink.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>


<html>
<body>
	<h1>Edit Drink</h1>
	<form:form method="post" action="${pageContext.request.contextPath}/drink/saveDrink">
		<table>
			<tr>
				<th>Details</th>
				<th>Old Value</th>
				<th>New Value</th>
			</tr>
			<tr>
				<td>Drink ID :</td>
				<td>${drink.id}</td>
				<td><form:input path="id" value="${drink.id}" /></td>
			</tr>
			<tr>
				<td>Drink Name :</td>
				<td>${drink.name}</td>
				<td><form:input path="name" /></td>
			</tr>
			<tr>
				<td>Drink Type :</td>
				<td>${drink.type}</td>
				<td><form:input path="type" /></td>
			</tr>
			<tr>
				<td></td>
				<td><input type="submit" value="Edit Drink" /></td>
			</tr>
		</table>
	</form:form>
</body>
</html>

Add jstl dependency in pom.xml file

Add below dependency in your pom.xml file

<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>jstl</artifactId>
	<version>1.2</version>
</dependency>

Project structure

project structure should look like this

Deploy and test the application on Tomcat

If Tomcat is not already installed on your machine, click below to download and configure it into STS.

How to download and configure Tomcat

After successful installation of the server, deploy your application onto it. After deployment is done on the server, run it and test your application.

Upon starting the server if you see an issue like below, then follow the given steps under the snapshot

  1. Open the project’s properties (e.g., right-click on the project in the project explorer and select ‘Properties’).
  2. Select ‘Deployment Assembly’.
  3. Click the ‘Add…’ button on the right
  4. Select ‘Java Build Path Entries’ from the menu of Directive Type and click ‘Next’.
  5. Select ‘Maven Dependencies’ from the Java Build Path Entries menu and click ‘Finish’.

Once the server is up without any error, tit below url from the browser.

http://localhost:8080/spring-mvc-app/drink/display

http://localhost:8080/spring-mvc-app/drink/addDrink

Iced Tea added successfully

When ‘Delete’ is clicked, it displays the below message

Any drink record can be edited by clicking on ‘Edit’ hyperlink. Below screen appears with old and new values

Drink edited successfully