Spring Boot 2 - Spring MVC + Thymeleaf Input Form Validation


In this quick article, we will discuss the process of configuring a web application form to support validation. We will use latest Spring boot 2.0.5 RELEASE, Hibernate validator with Thymeleaf to develop simple Spring MVC web application. We get Hibernate Validator for free when we use Spring Boot Starter Web.
Check out how to do Spring Boot CRUD Rest APIs validation on Spring Boot CRUD REST APIs Validation Example

What you’ll build

We’ll build a simple Spring MVC application that takes user input and checks the input using standard validation annotations. We’ll also see how to display the error message on the screen so the user can re-enter a valid input. The below diagram shows an overall project structure, running application etc.

2. Tools and Technologies Used

  • Spring Boot - 2.0.5.RELEASE
  • JDK - 1.8 or later
  • Spring Framework - 5.0.9 RELEASE
  • Maven - 3.2+
  • IDE - Eclipse or Spring Tool Suite (STS)
  • Tomcat - 8.5+
  • Thymeleaf - 3.0.9 RELEASE

3. Creating and Importing a Project

There are many ways to create a Spring Boot application. The simplest way is to use Spring Initializr at http://start.spring.io/, which is an online Spring Boot application generator.
Look at the above diagram, we have specified the following details:
  • Generate: Maven Project
  • Java Version: 1.8 (Default)
  • Spring Boot:2.0.4
  • Group: net.javaguides.springboot
  • Artifact: springboot-webapp-validate-input-form
  • Name: springboot-webapp-validate-input-form
  • Package Name : net.javaguides.springboot
  • Packaging: jar (This is the default value)
  • Dependencies: Web
Click on the Generate Project button. Now you can extract the downloaded ZIP file and import it into your favorite IDE.

4. Project Structure

A diagram shows a Project structure for your reference -

The pom.xml File - Maven Dependencies

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>net.javaguides.springboot</groupId>
    <artifactId>springboot-webapp-validate-input-form</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springboot-webapp-validate-input-form</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Create a PersonForm object

The application involves validating a user’s name and age, so first, you need to create a class to back the form to create a person.
package net.javaguides.springboot.springbootwebappvalidateinputform;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class PersonForm {

    @NotNull
    @Size(min = 2, max = 30)
    private String name;

    @NotNull
    @Min(18)
    private Integer age;

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String toString() {
        return "Person(Name: " + this.name + ", Age: " + this.age + ")";
    }
}
The PersonForm class has two attributes: name and age. It is flagged with several standard validation annotations:
  • @Size(min=2, max=30) will only allow names between 2 and 30 characters long
  • @NotNull won’t allow a null value, which is what Spring MVC generates if the entry is empty
  • @Min(18) won’t allow if the age is less than 18
In addition to that, you can also see getters/setters for name and age as well as a convenient toString() method.

Create a Spring Controller - WebController.java

Let's create a simple WebController class.
package net.javaguides.springboot.springbootwebappvalidateinputform;

import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Controller
public class WebController implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/results").setViewName("results");
    }

    @GetMapping("/")
    public String showForm(PersonForm personForm) {
        return "form";
    }

    @PostMapping("/")
    public String checkPersonInfo(@Valid PersonForm personForm, BindingResult bindingResult) {

        if (bindingResult.hasErrors()) {
            return "form";
        }

        return "redirect:/results";
    }
}
This controller has a GET and a POST method, both mapped to /.
The showForm() method returns the form template. It includes a PersonForm in its method signature so the template can associate form attributes with a PersonForm.
The checkPersonFormInfo() method accepts two arguments:
- A personForm object marked up with @Valid to gather the attributes filled out in the form you’re about to build.
- A bindingResult object so you can test for and retrieve validation errors.
You can retrieve all the attributes from the form bound to the PersonForm object. In the code, you test for errors, and if so, send the user back to the original form template. In that situation, all the error attributes are displayed.
If all of the person’s attribute is valid, then it redirects the browser to the final results template.

Thyemeleaf Templates

form.html

Note that this is very simple example, these web pages don’t have any sophisticated CSS or JavaScript. But for any production website, it’s valuable to learn how to style your web pages.

Refer below articles to add CSS or JavaScript to web pages.
Spring Boot 2 MVC Web Application Thymeleaf JPA MySQL Example
Spring Boot + Spring MVC + Role Based Spring Security + JPA + Thymeleaf + MySQL Tutorial 
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" 
   xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
 <form action="#" th:action="@{/}" th:object="${personForm}"
  method="post">
  <table>
   <tr>
    <td>Name:</td>
    <td><input type="text" th:field="*{name}" /></td>
    <td th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name
     Error</td>
   </tr>
   <tr>
    <td>Age:</td>
    <td><input type="text" th:field="*{age}" /></td>
    <td th:if="${#fields.hasErrors('age')}" th:errors="*{age}">Age
     Error</td>
   </tr>
   <tr>
    <td><button type="submit">Submit</button></td>
   </tr>
  </table>
 </form>
</body>
</html>
The page contains a simple form with each field in a separate slot of a table. The form is geared to post towards /. It is marked as being backed up by the personForm object that you saw in the GET method in the web controller. This is known as a bean-backed form. There are two fields in the PersonForm bean, and you can see them tagged th:field="{name}" and th:field="{age}". Next to each field is a secondary element used to show any validation errors.
Finally, you have a button to submit. In general, if the user enters a name or age that violates the @Valid constraints, it will bounce back to this page with the error message on display. If a valid name and age are entered, the user is routed to the next web page.

results.html

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
   <body>Congratulations! You are old enough to sign up for this
         site.
   </body>
</html>

Create an Application class

For this application, you are using the template language of Thymeleaf. This application needs more than raw HTML.
package net.javaguides.springboot.springbootwebappvalidateinputform;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
To activate Spring MVC, you would normally add @EnableWebMvc to the Application class. But Spring Boot’s @SpringBootApplication already adds this annotation when it detects spring-webmvc on your classpath. This same annotation allows it to find the annotated @Controller class and its methods.
The Thymeleaf configuration is also taken care of by @SpringBootApplication: by default, templates are located in the classpath under templates/ and are resolved as views by stripping the '.html' a suffix of the file name. Thymeleaf settings can be changed and overridden in a variety of ways depending on what you need to achieve, but the details are not relevant to this guide.

Running Spring Boot Application

You can run an application via Application.main() method or using ./mvnw spring-boot:run. Or you can build the JAR file with ./mvnw clean package. Then you can run the JAR file:
java -jar target/gs-validating-form-input-0.1.0.jar
The application should be up and running within a few seconds.

Demo

Hit this link in browser http://localhost:8080/, you should see a form like this:
What happens if you enter A for the name and 15 for your age and click on Submit?
Here you can see that because it violated the constraints in the PersonForm class, you get bounced back to the "main" page. If you click on Submit with nothing in the entry box, you get a different error.
If you enter a valid name and age, you end up on the results page!
Learn complete Spring boot on Spring Boot Tutorial

Related Spring Boot Web Application Development Articles


Comments