Spring: A Head Start 🔥— Spring MVC (Part 5)

Spring MVC, working with, and validating form data.

Omar Elgabry
OmarElgabry's Blog
9 min readSep 12, 2017

--

Spring: A Head Start 🔥 — Spring MVC

Quick Overview

Spring provides Model-View-Controller (MVC) architecture, and components that can be used to develop flexible and loosely coupled web applications. It uses the features of Spring core features like IoC and DI.

  • The Model encapsulates the application data and in general they will consist of POJOs.
  • The View is responsible for rendering the model data and in general it generates HTML output that the client’s browser can interpret.
  • The Controller is responsible for processing user requests and building an appropriate model and passes it to the view for rendering.

The Workflow

The Spring Web MVC framework is designed around the DispatcherServlet.

💡Java Servlet are programs that act as a middle layer between a request coming from a Web browser or HTTP client, and applications on the HTTP server.

🔍 What happens behind the scene when an HTTP request is sent to the server

Spring MVC Workflow — tutorialspoint
  • The DispatcherServlet handles all the HTTP requests and responses.
  • After receiving an HTTP request, the DispatcherServlet consults the HandlerMapping to call the appropriate Controller.
  • The Controller takes the request, calls the appropriate method, and builds the model and returns the view page name to the DispatcherServlet.
  • The DispatcherServlet will then take help from the ViewResolver to pick up the defined view page for the request.
  • Once the view is finalized, the DispatcherServlet passes the model data to the view, which is finally rendered on the browser.

💡 All the above-mentioned components (i.e. HandlerMapping, Controller, and ViewResolver) are parts of WebApplicationContext, which is an extension of the ApplicationContext with some extra features necessary for web applications

Spring MVC Application Components

  • A collection of web pages to layout UI components.
  • A collections of Spring beans (controllers, services, etc).
  • Spring configurations (XML, Annotation, or Java).

Setting Up The Environment 💪

First, you need to create a new “Dynamic Web Project”, and add all the jar files to “WEB-INF/lib” folder we added before, or use Maven (as discussed before).

In addition, we’ll need to add Java Servlet, JSP, and JSTL. If you’re using Maven, there add these dependencies to your “pom.xml” file.

  <!-- Servlet+JSP+JSTL -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependency>

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

Configurations

[1] Configuring Spring MVC dispatcher servlet(s)

Create an XML file “WEB-INF/web.xml” for defining and configuring Spring MVC dispatcher servlet(s).

Then, we setup URL mapping of dispatcher servlet(s) we’ve just defined. This means all requests coming in (since the url-pattern is “/” below) should be handled by dispatcher called “MyDispatcher”.

[2] Configuring “MyDispatcher” Dispatcher Servlet

Now, when you make a request, this will be mapped to a specific dispatcher. And so, Spring will load the configuration of that dispatcher from “WEB-INF” folder. In this case, our file is “WEB-INF/spring-mvc-demo-servlet.xml”.

We can add support for features like Spring component scanning, conversions, formatting, validation, configure Spring MVC View Resolver.

💡The “prefix” and “suffix” will be used to render the view page.

📣 We need to create “view” folder inside the “WEB-INF” folder.

📣 I’m assuming you’ve created a package called “com.springmvcdemo” where all of your Java classes live. The package name has to be aligned with “Step 3” above.

— How to add CSS, JavaScript and Images?

Any static resource is processed as a URL mapping in Spring MVC.

You can configure references to static resources by adding the following entry to the configuration file of the Dispatcher Servlet.

<!-- A handler for serving static resources -->
<mvc:resources mapping="/assets/**" location="/assets/" />

The double asterisk “**” means to look also for the subdirectory.

In your view pages, we can access the static files using one of the following:

<link rel="stylesheet" type="text/css"  href="${pageContext.request.contextPath}/assets/css/main.css">

Or, …

<!-- Include the core JSTL tags (will be discussed later) -->
<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<!-- ... --><link rel="stylesheet" type="text/css" href="<c:url value="/assets/css/main.css" />">

Spring MVC Application

Now we understand the concepts, and configured our Spring MVC application. Let’s see how can we apply these concepts in action … 🏃

  • The DispatcherServlet delegates the request to the appropriate controller to handle the request.
  • The @Controller annotation indicates that a particular class serves as the role of a controller.
  • The @RequestMapping annotation is used to map a URL to either an entire class or a particular controller method.

[1] Create controller class using @Controller annotation

The @Controller annotation inherits from @Component annotation. So, It’s a special @Component used in MVC web application, and so, it will be scanned by Spring IoC as a component.

So, now, this controller will handle all the requests for root path URL of our MyDispatcher we’ve created.

[2] Define & Map Controller Methods

We can pass different parameters like request, session, model objects, and return different types of objects (as you’ll see later) from controller method.

All request mapping on methods are relative to the controller mapping.

So, now, the welcome()method will handle root path of this controller.

By default, It handles all types of HTTP request (GET, POST, etc) unless explicitly defined (i.e. using method in @RequestMapping).

[3] Adding an attribute (data) to the model

We mean by model here is an object that we can use to pass data around the controller methods and views.

These data is called model attribute(s), they can be java beans that carry form data for data binding.

📣 We’ll discuss HTML form data and data binding later.

So, we can pass a model attribute from a controller method to a view page, and then from the view page back to a controller method (i.e. when form is submitted).

The model object can be passed as a parameter to controller method so that we can add attributes, and these attributes can be accessed by the view to display the final result.

[4] The Controller Method Returned Value

We can return a view page name, an object, or not return anything at all.

In case of returning a view page name, Spring will load the view page from using this format:prefix + view page name + suffix (defined previously in “spring-mvc-demo-servlet.xml” file) to be rendered and displayed.

[5] Create the view pages

These are mostly the JSP pages (but you can have HTML, PDF, Excel worksheets, XML, etc). In JSP pages, you write your HTML, and use the reusable UI components (like tags) in Spring.

In our case, we need to create “welcome-page.jsp” file.

The view pages must be located in the location we’ve defined earlier in “spring-mvc-demo-servlet.xml” file.

The ${message} is the attribute which we assigned in welcome() method.

Testing Our Project

To test the project hit the URL → http://localhost:8080/[NameOfTheProject]/

Working With HTML Form Data

In this section example, we’ll explain how to work with HTML form data; read the submitted data and display the results.

Before we start, let’s say we have a Java class User acts as a model in our MVC Spring application. So, we can add new user, and display user’s data.

[1] Display HTML Form

For the first time, we will display an empty form, right?. So, we can create a model attribute (let’s say called user), and assign it to an empty user object.

So, initially, an empty form will be displayed for adding new user.

[2] Set-Up The Form

In Spring, we have reusable UI components we can use to build our HTML such as the form tags. The form tags allows for data binding; automatically set and retrieve data from java beans (model attributes).

All what we need to do is to reference the Standard Tag Library (JSTL) in our JSP pages. They are classified into 5 groups: Core, Formatting, SQL, XML, and JSTL Functions.

🔍 Behind The Scene …

When the form is loaded, Spring will populate the user objects’ field values using getters. If it’s null, the form input field will be empty. When the form is submitted, Spring will assign the user objects’ field values using setters.

[4] Reading Form Data

— HttpServletRequest

We can pass and use the HttpServletRequest object in a controller method to get access to all request parameters (i.e. GET request).

@RequestMapping("/user")
public String showUser(HttpServletRequest request){
int id = Integer.parseInt(request.getParameter("id"));
/*...*/
}

— RequestParam Annotation

We can also read form data using @RequestParam annotation. This is a different way for reading form data in the request parameters.

Here, we bind a variable with a value fetched from@RequestParam annotation.

@RequestMapping("/user")
public String showUser(@RequestParam("id") int id) {/*...*/}

— Accessing request parameter values in view pages

There are set of object made available in JSP pages such as request, response, param, paramValues, cookie, etc.

The param object maps a request parameter name to a single value, while the paramValues maps a request parameter name to an array of values.

<html>
<head>
<title>Spring MVC Demo</title>
</head>
<body>
<h2>${param.id}</h2>
</body>
</html>

— RequestBody Annotation

If the data is passed in the request body (i.e. POST request), then, we can access the data using@RequestBody instead.

@RequestMapping(value = "/addUser", method = RequestMethod.POST)
public String addUser(@RequestBody User user){/*...*/}

💡Similarly, a controller method with@ResponseBody annotation indicates that the returned value should be bound to the web response body.

— ModelAttribute Annotation

When the form is submitted (let’s say for adding a new user), we can bind the user object with form data submitted. How? The model attribute that come with @ModelAttribute annotation is bind-ed to the data submitted.

So, we can bind the user object with the model attribute (call it user for example), and access all the data submitted using the user object.

💡The @ModelAttribute annotation makes the model attribute user available to view pages to access and display it.

📣 This is the method we will be using in our example.

[5] Display Data Submitted

Now, we can use the model attribute user to display it’s data in the view page.

In the result.jsp view page, we can access and display model attributes.

Form Data Validation

Spring 4 supports the Bean Validation API. Hibernate Validator is an implementation for the Java Beans Validation API.

It provides a set of validation annotations we can use to validate the data, such as @NotNull, @Max, @Min, @Size, @Pattern, @Future & @Past.

To add and use hibernate validator. Either download JAR files from and add them to our “lib” folder in the project, or declare the dependency in your Maven “pom.xml” file.

Form Data Validation — The Process

We’re going to use the example above of adding a new user further an apply validation rules on the submitted data.

[1] Add Validation Rules To User Class

For each filed of user object, we’ll specify the validation rule(s).

— The name is required, has min length of 2 and a max of 20. It must only contain alpha numeric characters with spaces.

— The password is required, can’t be empty, min length of 8, and must contain at least one digit, one lower char and one upper char, one special char, and doesn’t contain spaces.

— The email is required, and has a valid email format.

— The date of birth can’t be null, and in the past.

— The age is required, min is 15, and max is 100.

— The height has value between 50 and 300.

— The array of objects hobbies can’t be empty; there must be at least one.

📣 One common question here, “What’s the difference between @NotNull, @NotEmpty, and @NotBlank ?”

  • @NotNull: Checks if the value is not null, disregarding the content (it can be empty). Used with dates, collections, map, array, etc.
  • @NotEmpty: Checks if the value is not null nor empty, allowing empty spaces but size has to be greater than zero. Used with strings, collections, map, array etc.
  • @NotBlank: Checks if the value is not null nor empty, and the trimmed length is greater than zero. Used with strings.

[2] Display Error Message In HTML Form

We’ll use form:errors tag to display the validation error messages (if exist). In addition we can apply a CSS class for displaying errors.

[3] Perform Validation Rules In The Controller

The @Valid annotation performs validation rules on user object (we defined earlier in user class). The results of the validation will be placed in the BindingResult object.

💡 If error exists, it will be displayed as a span replacing the form:errors tag.

<span id="name.errors" class="error">name must have min length of 2, and max of 20</span>

Custom Validation Rules

The annotation validation rules we have used are pre-defined. In some cases, you need to define your own custom logic.

[1] Create a Custom Annotation For Validation Rule

[2] Create A Custom Validation Rule Code (Helper Class)

[3] Use The Custom Validation Rule

@VisaCode(value="IND", message="visa code must start with IND and of length >= 5")
private String visaCode;

Thank you for reading! If you enjoyed it, please clap 👏 for it.

--

--

Omar Elgabry
OmarElgabry's Blog

Software Engineer. Going to the moon 🌑. When I die, turn my blog into a story. @https://www.linkedin.com/in/omarelgabry