Form Submitting with Spring Boot Validation

Posted on



Introduction

This tutorial is how to create and submit a form and how to validate our registration form.



Necessary Environments



Source Code

You can refer to the source code below.
https://github.com/ZarLiHninn/Form-Submitting-with-Spring-Boot-Validation



Let’s start by following these steps



Step 1. Creating a project

  • File → New → Spring Starter Project
    Alt Text
  • Fill the necessary information and add dependencies.
    Alt Text
    Alt Text
  • Project Explorer is like this.
    Alt Text



Step 2. Let’s start code



Student.java

package com.reytech.demo.model;

import java.time.LocalDate;
import java.util.List;
import javax.validation.constraints.Email;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import javax.validation.constraints.Positive;
import javax.validation.constraints.Size;
import org.springframework.format.annotation.DateTimeFormat;

public class Student {

    @NotEmpty(message = "{validation.name.NotEmpty}")
    @Size(min = 2, max = 50, message = "{validation.name.Size}")
    private String name;

    @NotNull(message = "{validation.age.NotNull}")
    @Positive(message = "{validation.age.Positive}")
    @Max(value = 18, message = "{validation.age.Maximum}")
    private Integer age;

    @NotEmpty(message = "{validation.email.NotEmpty}")
    @Email(message = "{validation.email.Type}")
    private String email;

    @NotEmpty(message = "{validation.subjects.NotEmpty}")
    private List <String> subjects;

    @NotNull(message = "{validation.birthDate.NotNull}")
    @Past(message = "{validation.birthDate.Past}")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate birthDate;

    @NotEmpty(message = "{validation.gender.NotEmpty}")
    private String gender;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public LocalDate getBirthDate() {
        return birthDate;
    }

    public void setBirthDate(LocalDate birthDate) {
        this.birthDate = birthDate;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public List <String> getSubjects() {
        return subjects;
    }

    public void setSubjects(List <String> subjects) {
        this.subjects = subjects;
    }

}
  • We will store student information in Student.class model.

  • And, @Size, @NotEmpty, @Email, etc. are to validate input when the user fills an error input.

  • We will use custom message by creating message.properties. (e.g.message=”{validation.name.NotEmpty}”, you can see the custom message in messages.properties file.)



messages.properties

  • We will set custom messages.
validation.name.NotEmpty=Please fill in Name
validation.name.Size=Name size must be between 2 and 30
validation.name.Pattern=Name must be only characters
validation.age.NotNull=Please fill in Age
validation.age.Maximum=Age must be under 18
validation.age.Positive=Age must not be negative value and 0
validation.age.Pattern=Age must be only numbers
validation.email.NotEmpty=Please fill in Email
validation.email.Type=Please fill in valid Email
validation.birthDate.NotNull=Please fill in Birth Date
validation.birthDate.Past=Please fill in valid Birth Date
validation.subjects.NotEmpty=Please select Subjects
validation.gender.NotEmpty=Please select Gender



AppConfiguration.java

  • To handle message.properties, MessageSource and LocalValidatorFactoryBean are needed.
package com.reytech.demo;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

@Configuration
public class AppConfiguration {

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename("classpath:messages");
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }

    @Bean
    public LocalValidatorFactoryBean validator() {
        LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
        bean.setValidationMessageSource(messageSource());
        return bean;
    }
}



Gender.java

package com.reytech.demo.constant;

public enum Gender {
   MALE,FEMALE,OTHER
}



Subject.java

package com.reytech.demo.constant;

public enum Subject {
    MYANMAR("Myanmar"),
    ENGLISH("English"),
    MATH("Math"),
    CHEMISTRY("Chemistry"),
    PHYSICS("Physics"),
    BIO("Bio"),
    ECO("Eco");

    private final String value;

    private Subject(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}



HomeController.java

package com.reytech.demo.controller;

import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import com.reytech.demo.constant.Gender;
import com.reytech.demo.constant.Subject;
import com.reytech.demo.model.Student;

@Controller
public class HomeController {

    @GetMapping("/form")
    public String showForm(Model model) {
        Student student = new Student();
        model.addAttribute("student", student);
        model.addAttribute("gender_value", Gender.values());
        model.addAttribute("subject_value", Subject.values());
        return "form";
    }

    @PostMapping("/form/result")
    public String submitForm(@Valid Student student, BindingResult bindingResult, Model model) {
        if (bindingResult.hasErrors()) {
            model.addAttribute("student", student);
            model.addAttribute("gender_value", Gender.values());
            model.addAttribute("subject_value", Subject.values());
            return "form";
        } else {
            model.addAttribute("result", student);
            return "result";
        }
    }

    @GetMapping("/back")
    public String backHome() {
        return "redirect:/form";
    }

}

The controller is used to handle GET/POST requests at /HTTP endpoint.

  • The showForm() method is to reach localhost:/8080/form as a GET request and return the view which is form.html by using thymeleaf. It uses a Model object to expose a new Student object to the view template. The values of Gender and Subjects are carried by using the model.addAttribute and displayed the result in result.html.

  • The saveForm() method is to reach localhost:8080/form/result as a POST request when submitting data by the user. The submitted data is saved in “result” and carried by model.addAttribute. And this method returns the view which is result.html but it returns back to form.html when submitted data are errors.



form.html

  • We will create a form to fill data in form.html.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Form_Registration</title>
<link rel="stylesheet"
href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
<script>
$(function() {
$("#datepicker").datepicker({dateFormat:"yy-mm-dd"});
});
</script>
<style>
.error{
color:red;
}
</style>
</head>
<body>
<div class="container">
<h1>Form Registration</h1>
<form th:action="@{/form/result}" th:object="${student}" method="post">
<div class="form-group">
<label>Student Name</label>
<input class="form-control" type="text" th:field="*{name}" />
<span class="error" th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name Error</span>
</div>
<div class="form-group">
<label>Age</label>
<input class="form-control" type="text" th:field="*{age}" />
<span class="error" th:if="${#fields.hasErrors('age')}" th:errors="*{age}">Age Error</span>
</div>
<div class="form-group">
<label>Email</label>
<input class="form-control" type="text" th:field="*{email}" />
<span class="error" th:if="${#fields.hasErrors('email')}" th:errors="*{email}">Email Error</span>
</div>
<div class="form-group">
<label>BirthDate</label>
<input class="form-control" type="text" id="datepicker" th:field="*{birthDate}">
<span class=<

Leave a Reply

Your email address will not be published. Required fields are marked *