It feels like travelling back in time like 6-7 years when we had to configure the Spring Web MVC using XML.
It was so dreadful for me back then.
It is dreadful for me now as well.
I know many of you might be struggling to set up the Spring Web MVC older versions (versions from 3.x) and so on.
I know this because I’m struggling with it myself. Mostly because I’m working on a legacy system powered by Spring Web MVC 3.x that needs to be migrated to cloud.
And this article is really good for starters as well.
If you are starting out with web development then this is a good starting point as you will know about the working principles behind Spring Web MVC.
And if you are someone just looking for a quick boilerplate that you can use to work on, then grab it from here: Spring Web MVC Boilerplate.
Okay… so let’s begin.
Table of Contents
Start With The Directory Structure
The directory structure is very important if you are going to set up the Spring Web MVC in the fastest/easiest way possible. The directory structure is used by default to package your artefact.
So if you do not have the right directory structure than you might miss to include the necessary files and folder in your generated WAR file that will later cause a problem (after deployment) and takes a lot more time to resolve than usual.
Try to start with the right directory structure.
Copy-paste below command to create all the required directories.
mkdir -p src/main/webapp/WEB-INF
mkdir -p src/main/java
mkdir -p src/main/resources
mkdir -p src/test/java
mkdir -p src/test/resources
Note: resources folder is not required but it’s good to have
So, once you are done with the directory structure, let’s start by setting up the required dependencies for Spring Web MVC application.
Setting Up Spring Web MVC Required Dependencies
I use gradle for packaging and building Java applications. And you should too. Gradle is very easy and modern with a very crisp syntax.
I have written and explained it here:
Coming back to setting up required dependencies in your project.
Create build.gradle
file at the root of your project. For example if your project folder name is SpringWebMvc then create a file directly inside your project folder as build.gradle
.
Prerequisite: Install and setup gradle on your machine.
Tip: Install Gradle using Brew. Code: brew install gradle
.
Read How to Setup Homebrew.
In build.gradle
add all the required dependencies. Simply copy and paste below code:
cat > build.gradle
plugins {
id "java"
id "war"
}
repositories {
mavenCentral()
}
dependencies {
compile group: 'org.springframework', name: 'spring-context', version: '3.1.0.RELEASE'
compile group: 'org.springframework', name: 'spring-webmvc', version: '3.1.0.RELEASE'
compile group: 'org.springframework', name: 'spring-web', version: '3.1.0.RELEASE'
providedCompile group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0'
compile group: 'commons-logging', name: 'commons-logging', version: '1.2'
compile group: 'log4j', name: 'log4j', version: '1.2.14'
}
Great. So far so good.
Now just for a sanity check try to run following command: gradle clean build
.
If the command is successful, it will show build successful.
And you will see a newly generated folder with the name build.
It means everything is good and we can move forward to setting up web.xml
and dispatcher-servlet.xml
.
Setting Up web.xml
First of of all, if you are new to the web development world then I would recommend you to read about Servlet containers like Tomcat and see how they make use of web.xml
to identify which classes to load, what parameters to set in the context, and how to intercept requests coming from browsers.
In short, web.xml
is used by Tomcat (or servlet containers) and it is called Deployment Descriptor. It tells tomcat which classes to load and how to intercept the incoming URLs for the application.
So, in Spring Web MVC, we have only one Servlet called DispatcherServlet. This DispatcherServlet extends from HttpServlet class (part of servlet-api).
You can think of DispatcherServlet as a controller that maps every incoming request to its correct Controller.
Baeldung has explained it rather beautifully here.
So with that information in mind, let’s configure the web.xml
file in such a way that it will forward every request to the DispatcherServlet class of Spring MVC.
cat > src/main/webapp/WEB-INF/web.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Demo for understanding web.xml of spring mvc project</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>
<!-- ===================================================== -->
<!-- 1. Create root context with spring listener -->
<!-- Remove this means only use servlet contxt -->
<!-- ===================================================== -->
<!-- <listener>-->
<!-- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>-->
<!-- </listener>-->
<!-- ===================================================== -->
<!-- Can modify default root context config file -->
<!-- ===================================================== -->
<!--
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/root-context.xml</param-value>
</context-param>
-->
<!-- ===================================================== -->
<!-- 2. Define servlet with private context -->
<!-- ===================================================== -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- ================================================= -->
<!-- Set contextConfigLocation to empty -->
<!-- means only use root context -->
<!-- ================================================= -->
<!--
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
-->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- ===================================================== -->
<!-- One servlet, the dispatcher, to rule it all -->
<!-- ===================================================== -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
</web-app>
Here, we have defined servlet as org.springframework.web.servlet.DispatcherServlet
with its mapping.
Also, one important thing here is the name of the servlet i.e dispatcher.
This name is used to create the dispatcher-servlet.xml
file. So, whatever name you mention in the web.xml
servlet tag, the same name should be used to create the file as {servlet_name}-servlet.xml
.
Setting Up dispatcher-servlet.xml File
Now that you have set up the web.xml file successfully, it is time to set up the dispatcher-servlet.xml
.
Simply, copy and paste the below code:
cat > src/main/webapp/WEB-INF/dispatcher-servlet.xml
<?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 />
<!-- register controller in servlet private context -->
<context:component-scan base-package="com.spring.sample.controller"/>
<mvc:default-servlet-handler />
</beans>
Here we are telling the Dispatcher servlet that we are using Annotation in our application. And also the path where it needs to scan for all the spring components.
This is pretty straight-forward once you read about the DispatcherServlet in detail.
Let’s create our HelloWorldController.
Create HelloWorldController
Okay, so we have everything in place. Let’s create our HelloWorldController.
cat > src/main/java/com/spring/sample/controller/HelloWorldController.java
package com.spring.sample.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloWorldController {
@RequestMapping(value = "/welcome", method = RequestMethod.GET)
@ResponseBody
public String helloWorld() {
return "Hello World!";
}
}
Superb.
Now, let’s build the application and look inside the hood.
To build the application, run the following command: gradle clean build
.
You should see the war artefact inside build/libs/SpringMVCSample.war.
Unzip the file and look for its content. To unzip the war file, run the following command:
unzip -d temp build/libs/SpringMVCSample.war
Then use tree command to see the structure.
You should see the following content inside:
Make sure you have a similar structure with all the required files in place. This is the minimum configuration that is required to run the Spring Web MVC application on the Tomcat server.
Deploy The War On Tomcat Container
I’m running out of time, so I leave the Tomcat setup up to you. All you need to do is place the war file inside the webapps directory of tomcat.
Tomcat will then deploy the artefact which you can access via browser.
This is what you will see on a successful deployment.
Let me know if you need any information related to any of the stuff discussed in this article. The best and fastest way to get the answer is via comments.