Registration Form in Thymeleaf with Spring Boot

Registration Form in Thymeleaf in a Spring Boot Project. In this article, we will learn how to handle a form/registration form in Thymeleaf with spring boot.

Thymeleaf is a server-side Java template engine. It is an open-source Library of Java that is used to create and process HTML, XML, CSS, JS, and text information. It is best for serving HTML/XHTML in the view layer of MVC-based applications. It is also an open-source software licensed under Apache Licence 2.0.

We are going to use Spring Boot to make the development process easy. We are also be sending the data to the database so, at the data access layer, I have used Spring Data JPA. At the view layer, thymeleaf is used to make the HTML code look clean.

Tools and Technologie:

  • Spring Tool Suite 4
  • MySQL Database.
  • Lombok.
  • Thymeleaf
  • Spring Data JPA.
  • Spring Boot

Create a Registration Form using Thymleaf in Spring Boot Project using Spring Data JPA.

Step 1: Open IDE STS- Spring Tool Suite

Step 2: Go to File > Spring Starter Project.

Step 3: Now, fill all the fields as shown below and click Next.

Step 4: Now, Add the dependencies of Thymeleaf, spring data JPA, Lombok, and spring web and click Next > Finish.

Now, wait for some time and your project structure will be ready. Go to the pom.xml file and you will see the following dependencies will be added automatically.

<dependencies>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</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-web</artifactId>
  </dependency>

  <dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <scope>runtime</scope>
  </dependency>
  <dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
   <optional>true</optional>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
  </dependency>
 </dependencies>

Create a Database in MYSQL

mysql> create database db_demo;

Configure application. properties file

spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/db_demo
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name =com.mysql.jdbc.Driver
spring.jpa.show-sql= true
## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
#To format SQL queries generated by Hibernate
spring.jpa.properties.hibernate.format_sql=true
#change port number
server.port=8888
  • spring.jpa.hibernate.ddl-auto is set to update so that whatever changes we will do will be reflected in the schema.
  • spring.datasource.url is used to set the URL of the MYSQL DB.
  • spring.datasource.username is used to set the username and spring. datasource. password is used to set the password.
  • spring.datasource.driver-class-name is used to set the driver class name.
  • spring.jpa.show-sql is set to true to show SQL generated by the Hibernate.
  • spring.jpa.properties.hibernate.dialect is used to generate better SQL for the chosen database.
  • spring.jpa.properties.hibernate.format_sql is set to true to format SQL queries.
  • server.port is set to 8888.

The project Structure will look like this:

Create a Model Class

Student.java

package com.example.thymeleaf.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Entity
@Table(name = "student")
@Setter
@Getter
public class Student {

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private int id;
 @Column(name = "first_name")
 private String firstName;
 @Column(name = "last_name")
 private String lastName;
 @Column(name = "gender")
 private String gender;
 @Column(name = "course")
 private String course;
 @Column(name = "email")
 private String email;
 @Column(name = "password")
 private String password;
 @Column(name = "mobile_number")
 private String mobileNumber;
 @Column(name = "dob")
 private String dob;
}
  • @Entity is used to annotate the classes to indicate that they are JPA entities.
  • @Table annotation is used to specify the name of the table that should be mapped with entities.
  • @Id annotation is used for the primary key.
  • I have used the Lombok library to remove boilerplate code. In case you want to know what is Lombok check this article https://codedec.com/tutorials/how-to-configure-lombok-into-eclipse/

Create Repository Interface

The repository here is the DAO layer, which performs all the database operations. StudentRepository interface is created which will extend JPARepository<ClassName, ID>.

package com.example.thymeleaf.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.example.thymeleaf.model.Student;
@Repository
public interface StudentRepository extends JpaRepository<Student, Integer>{

}

Create a Service Layer

StudentService

package com.example.thymeleaf.services;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.thymeleaf.model.Student;
import com.example.thymeleaf.repository.StudentRepository;

@Service
public class StudentService {

 @Autowired
 private StudentRepository repository;
 public void save(Student student) {
  repository.save(student);
 }
}
  • In this, we have used the save(entity) method of JPARepository and persist data into MySQL database.
  • student entity is passed into the save() method.

Create a Controller class

The request for the web page will be handle by the handler methods in the controller class using @GetMapping.

package com.example.thymeleaf.controller;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.example.thymeleaf.model.Student;
import com.example.thymeleaf.services.StudentService;

@Controller
public class TestController {

 @Autowired
 private StudentService service;
 
 List<String> courses; 
 
 @ModelAttribute
 public void preLoad() {
  courses = new ArrayList<String>();
  courses.add("C");
  courses.add("CPP");
  courses.add("Java");
 }
 @RequestMapping(value = "/" , method = RequestMethod.GET)
 public String home(Model model, Student student) {
  model.addAttribute("courses", courses);
  return "register";
 }
 @RequestMapping(value = "/save",method = RequestMethod.POST)
 public String register(@ModelAttribute("student") Student student, Model model) {
  System.out.println("get coursess:::"+student.getCourse());
  service.save(student);
  return "welcome";
 }
}
  • @Controller annotation marks the TestController class a Request Handler.
  • Every request coming for the ‘/’ URL will be handled by the home() method. It would redirect you to the register page.
  • Here, create a method preLoad() and annotate it with @ModelAttribute annotation. Use the Array List to add the list of objects.
  • Pass the list into the model inside the home() method.
  • @ModelAttribute in register method will read data from the form.
  • The request for ‘/register’ is handled by the register() method and it will call the save method of service class.

Create View using Thymeleaf

Go to src/main/resources/template folder and create a register.html file. Now inside the register.html file make sure to add the following code:

<html xmlns:th="http://www.thymeleaf.org">

Now, let us see the register.html file

  • The name of the object model is in th:field=”*{}” attribute.
  • In thymeleaf, the @ denotes the page context.
  • In order to access the model object, we have to use ${} notation in thymeleaf.
  • The th: object attribute is used to get the model object sent from the controller side.

There is a complete article on How to populate dropdown in Thymeleaf in Spring Boot.

<!DOCTYPE html>
<html xmlns:th="www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.3/dist/umd/popper.min.js" integrity="sha384-eMNCOe7tC1doHpGoWe/6oMVemdAVTMs2xqW4mwXrXsW0L84Iytr2wi5v2QjrP/xp" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.min.js" integrity="sha384-cn7l7gDp0eyniUwwAZgrzD06kc/tftFf19TOAs2zVinnD/C7E91j9yyk5//jjpt/" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<title>Register</title>
</head>
<body>
<div class="container mt-5">
<h3 align="justify">Registration using Thymeleaf + Spring Data JPA + Spring Boot</h3>
<div class="card" style="width: 55rem; ">
  <div class="card-header text-center bg-info ">
    <h3>Register</h3>
  </div>
  <div class="card-body">
<form th:action="@{/save}" method="post" th:object="${student}">
  <div class="form-group">
    <label for="exampleInputEmail1">First Name</label>
    <input type="text" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" th:field="*{firstName}">
  </div>
  <div class="form-group">
    <label for="exampleInputEmail1">Last Name</label>
    <input type="text" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" th:field="*{lastName}">
  </div>
  <div class="form-group">
    <label for="exampleInputEmail1">Email</label>
    <input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" th:field="*{email}">
  </div>
  <div class="form-group">
    <label for="exampleInputPassword1">Password</label>
    <input type="password" class="form-control" id="exampleInputPassword1" th:field="*{password}">
  </div>
  <div class="form-group">
    <label for="exampleInputPassword1">Mobile Number</label>
    <input type="text" class="form-control" id="exampleInputPassword1" th:field="*{mobileNumber}">
  </div>
  <div class="form-group">
    <label for="exampleFormControlSelect1">Course</label>
    <select class="form-control" id="exampleFormControlSelect1" th:field="*{course}">
      <option th:each="course : ${courses}" th:value="${course}"  th:text="${course}"/>
    </select>
  </div>
  <div class="form-group">
  <label for="example">Date of Birth</label>
  <div id="date-picker-example" class="md-form md-outline input-with-post-icon datepicker">
  <input placeholder="Select date" type="text" id="example" class="form-control" th:field="*{dob}">	  
</div>
  </div>
  <div class="form-group">
  <label for="exampleFormControlSelect1">Gender</label>
    <div class="form-check form-check-inline">    
  <input class="form-check-input" type="radio" name="inlineRadioOptions" id="inlineRadio1" value="Male" th:field="*{gender}">
  <label class="form-check-label" for="inlineRadio1">Male</label>
</div>
<div class="form-check form-check-inline">
  <input class="form-check-input" type="radio" name="inlineRadioOptions" id="inlineRadio2" value="Female" th:field="*{gender}">
  <label class="form-check-label" for="inlineRadio2">Female</label>
</div>
<div class="form-check form-check-inline">
  <input class="form-check-input" type="radio" name="inlineRadioOptions" id="inlineRadio2" value="Other" th:field="*{gender}">
  <label class="form-check-label" for="inlineRadio2">Other</label>
</div>
    
  </div>
  
   <div class="form-group">
          
            </div>
        </div>
  <button type="submit" class="btn btn-primary">Submit</button>
</form>    

  </div>
</div>
</div>

<script type="text/javascript">
//Data Picker Initialization
$('.datepicker').datepicker();
</script>
</body>
</html>

welcome.html

<!DOCTYPE html>
<html xmlns:th="www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.3/dist/umd/popper.min.js" integrity="sha384-eMNCOe7tC1doHpGoWe/6oMVemdAVTMs2xqW4mwXrXsW0L84Iytr2wi5v2QjrP/xp" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.min.js" integrity="sha384-cn7l7gDp0eyniUwwAZgrzD06kc/tftFf19TOAs2zVinnD/C7E91j9yyk5//jjpt/" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<title>Register</title>
</head>
<body>
<div class="container mt-5">
<div class="card" style="width: 25rem;">
  <div class="card-header text-center bg-info ">
    <h3>Successfully Registered!!!</h3>
  </div>
  <div class="card-body">
  <div class="form-group">
    <label for="exampleInputEmail1">First Name:</label>
    <span th:text="${student.firstName}"></span>
  </div>
  <div class="form-group">
    <label for="exampleInputEmail1">Last Name:</label>
    <span th:text="${student.lastName}"></span>
  </div>
  <div class="form-group">
    <label for="exampleInputEmail1">Email:</label>
    <span th:text="${student.email}"></span>
  </div>
  <div class="form-group">
    <label for="exampleInputPassword1">Password:</label>
    <span th:text="${student.password}"></span>
  </div>
  <div class="form-group">
    <label for="exampleInputPassword1">Mobile Number:</label>
    <span th:text="${student.mobileNumber}"></span>
  </div>
  <div class="form-group">
    <label for="exampleFormControlSelect1">Course:</label>
    <span th:text="${student.course}"></span>
  </div>
  <div class="form-group">
  <label for="example">Date of Birth:</label>
  <span th:text="${student.dob}"></span>  
</div>
  
  <div class="form-group">
  <label for="exampleFormControlSelect1">Gender:</label>
   <span th:text="${student.gender}"></span>
  </div>
  
   <div class="form-group">
          
            </div>
        </div>
      

  </div>
</div>
</div>

<script type="text/javascript">
//Data Picker Initialization
$('.datepicker').datepicker();
</script>
</body>
</html>

Now, Run the ThymeleafLesson6Application and Go to localhost:8888 and see the following output.

In this way, we use the thymeleaf template in a spring boot application to create or handle the form.

In case you want to know more about the above technologies follow these articles.