Spring Boot – Thymeleaf with Example

13 Jun, 2022
Thymeleaf is a server-side Java-based template engine for both web and standalone environments, capable of processing HTML, XML, JavaScript, CSS and even plain text. It is more powerful than JPS and responsible for dynamic content rendering on UI. The engine allows a parallel work of the backend and frontend developers on the same view. It can directly access the java object and spring beans and bind them with UI. And it is mostly used with spring MVC when we create any web application. So let’s start with an example to understand how Thymeleaf works with the Spring framework. 
Here we are going to perform crud operation on Employee dataset. So for building this we have to add certain dependencies which are listed in bulleted form or also in pom.xml. 
Spring Web (Build web, including RESTful, applications using Spring MVC. Uses Apache Tomcat as the default embedded container.)
Spring Data JPA (Persist data in SQL stores with Java Persistence API using Spring Data and Hibernate.)
Spring Boot Devtools (Provides fast application restarts, LiveReload, and configurations for enhanced development experience)
MySQL Driver (MySQL JDBC and R2DBC driver)
Thymeleaf ( server-side Java template engine for both web and standalone environments. Allows HTML to be correctly displayed in browsers and as static prototypes.)
POM.XML
XML
<?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 https:/                        /maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.6.2</version>        <relativePath/> <!-- lookup parent from repository -->    </parent>    <groupId>com.example</groupId>    <artifactId>thymeleaf</artifactId>    <version>0.0.1-SNAPSHOT</version>    <name>thymeleaf</name>    <description>Demo project for Spring Boot</description>    <properties>        <java.version>17</java.version>    </properties>    <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>org.springframework.boot</groupId>            <artifactId>spring-boot-devtools</artifactId>            <scope>runtime</scope>            <optional>true</optional>        </dependency>        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <scope>runtime</scope>        </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>
application.properties file
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/emp
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE
Employee Pojo
This is the simple pojo class which is used to store the data of Employee. 
Java
package com.microservice.modal; import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id; @Entitypublic class Employee {    @Id    @GeneratedValue(strategy=GenerationType.IDENTITY)    private long id;    private String name;    private String email;         public long getId() {        return id;    }    public void setId(long id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getEmail() {        return email;    }    public void setEmail(String email) {        this.email = email;    }}
Employee Service interface and EmployeeServiceImpl class
Java
package com.microservice.service; import java.util.List; import com.microservice.modal.Employee; public interface EmployeeServices {    List<Employee> getAllEmployee();    void save(Employee employee);    Employee getById(Long id);    void deleteViaId(long id);}
EmployeeServiceImpl class which implements EmployeeSerivce interface methods
Java
package com.microservice.service; import com.microservice.modal.Employee;import com.microservice.repository.EmployeeRepository;import java.util.List;import java.util.Optional;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service; @Servicepublic class EmployeeServiceImpl    implements EmployeeServices {       @Autowired private EmployeeRepository empRepo;     @Override public List<Employee> getAllEmployee()    {        return empRepo.findAll();    }     @Override public void save(Employee employee)    {        empRepo.save(employee);    }     @Override public Employee getById(Long id)    {        Optional<Employee> optional = empRepo.findById(id);        Employee employee = null;        if (optional.isPresent())            employee = optional.get();        else            throw new RuntimeException(                "Employee not found for id : " + id);        return employee;    }     @Override public void deleteViaId(long id)    {        empRepo.deleteById(id);    }}
EmployeeRepository Interface
Here we are using JPA for communicating and saving the object into database.
Java
package com.microservice.repository; import org.springframework.data.jpa.repository.JpaRepository;import org.springframework.stereotype.Repository; import com.microservice.modal.Employee; @Repositorypublic interface EmployeeRepository extends JpaRepository<Employee,Long> { }
EmployeeController class
This is the controller class it basically controls the flow of the data. It controls the data flow into model object and updates the view whenever data changes. So here we are mapping our object data with Thymeleaf. 
When user type the URL localhost:8080/ on browser than request goes to the viewHomePage() method and in this method we are fetching the list of employee and added it into the modal with key, value pair and return the index.html page. In index.html page the key (allemplist) is identified as a java object and Thymeleaf iterate over the list and generate dynamic content as per the user provided template.
/addNew –  when user clicks on Add Employee button than request goes to addNewEmployee() method. And in this method we simply create the empty object of the employee and send it back to newemployee.html so that user can fill the data in this empty object and when user hits on save button than /save mapping runs and get the object of the employee and save that object into database.
/showFormForUpdate/{id} – This mapping is for updating the existing employee data.
/deleteEmployee/{id} – This mapping is for deleting the existing employee data.
Java
package com.microservice.controller; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.ModelAttribute;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.PostMapping; import com.microservice.modal.Employee;import com.microservice.service.EmployeeServiceImpl; @Controllerpublic class EmployeeController {     @Autowired    private EmployeeServiceImpl employeeServiceImpl;     @GetMapping("/")    public String viewHomePage(Model model) {        model.addAttribute("allemplist", employeeServiceImpl.getAllEmployee());        return "index";    }     @GetMapping("/addnew")    public String addNewEmployee(Model model) {        Employee employee = new Employee();        model.addAttribute("employee", employee);        return "newemployee";    }     @PostMapping("/save")    public String saveEmployee(@ModelAttribute("employee") Employee employee) {        employeeServiceImpl.save(employee);        return "redirect:/";    }     @GetMapping("/showFormForUpdate/{id}")    public String updateForm(@PathVariable(value = "id") long id, Model model) {        Employee employee = employeeServiceImpl.getById(id);        model.addAttribute("employee", employee);        return "update";    }     @GetMapping("/deleteEmployee/{id}")    public String deleteThroughId(@PathVariable(value = "id") long id) {        employeeServiceImpl.deleteViaId(id);        return "redirect:/";     }}
index.html
This page is used to displaying the list of employee. Here we are iterating over the allemplist object which is sent by our controller from viewHomePage() method. 
HTML
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="ISO-8859-1"><title>Employee</title><link rel="stylesheet"    href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"    integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"    crossorigin="anonymous"></head><body><div class="container my-2" align="center"> <h3>Employee List</h3><a th:href="@{/addnew}" class="btn btn-primary btn-sm mb-3" >Add Employee</a>    <table style="width:80%" border="1"           class = "table table-striped table-responsive-md">    <thead>  <tr>    <th>Name</th>    <th>Email</th>    <th>Action</th>  </tr>  </thead>  <tbody>  <tr th:each="employee:${allemplist}">        <td th:text="${employee.name}"></td>        <td th:text="${employee.email}"></td>        <td> <a th:href="@{/showFormForUpdate/{id}(id=${employee.id})}"                class="btn btn-primary">Update</a>                <a th:href="@{/deleteEmployee/{id}(id=${employee.id})}"                class="btn btn-danger">Delete</a>    </td>  </tr>  </tbody></table></div></body></html>
newemployee.html
This page is used to add new employee in the database. Here we simply provide the value in empty fields and click the submit button. Than the data of the employee goes to the saveEmployee() method and save the data into database. 
HTML
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="ISO-8859-1"><title>Employee Management System</title><link rel="stylesheet"    href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"    integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"    crossorigin="anonymous"></head><body>    <div class="container">        <h1>Employee Management System</h1>        <hr>        <h2>Save Employee</h2>         <form action="#" th:action="@{/save}" th:object="${employee}"            method="POST">            <input type="text" th:field="*{name}" placeholder="Employee Name"                class="form-control mb-4 col-4"> <input type="text"                th:field="*{email}" placeholder="Employee Email"                class="form-control mb-4 col-4">             <button type="submit" class="btn btn-info col-2">Save                Employee</button>        </form>         <hr>         <a th:href="@{/}"> Back to Employee List</a>    </div></body></html>
update.html
This page is used to update the data of existing employee. 
HTML
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="ISO-8859-1"><title>Employee Management System</title> <link rel="stylesheet"    href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"></head><body>    <div class="container">        <h1>Employee Management System</h1>        <hr>        <h2>Update Employee</h2>         <form action="#" th:action="@{/save}" th:object="${employee}"            method="POST">                         <!-- Add hidden form field to handle update -->            <input type="hidden" th:field="*{id}" />                         <input type="text" th:field="*{Name}" class="form-control mb-4 col-4">                                                 <input type="text" th:field="*{email}" class="form-control mb-4 col-4">                                 <button type="submit" class="btn btn-info col-2"> Update Employee</button>        </form>                 <hr>                 <a th:href = "@{/}"> Back to Employee List</a>    </div></body></html>
Output:
simmytarika5
surinderdawra388
sumitgumber28
Java-Spring-Boot
Java
Java
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Stream In Java
Introduction to Java
Constructors in Java
Exceptions in Java
Generics in Java
Functional Interfaces in Java
Strings in Java
Java Programming Examples
Abstraction in Java
HashSet in Java