Thymeleaf Integration

About

Thymeleaf is a server-side Java template engine that is commonly used in web development, particularly in Java-based applications. It allows developers to create dynamic web pages by combining HTML templates with server-side data and logic.

Thymeleaf uses a syntax that is similar to HTML, making it relatively easy for developers to learn and use. Thymeleaf allows us to use the full power of Java within our templates, including conditional statements, loops, variables, and method invocations. This makes it flexible and powerful for handling complex rendering scenarios. Compared to client-side rendering frameworks, server-side rendering with Thymeleaf may have a performance overhead due to the need for server processing. If we have complex client-side logic, we may need to integrate Thymeleaf with a separate JavaScript framework.

In Thymeleaf, "th:" is a prefix used to indicate Thymeleaf-specific attributes within HTML templates. It is used to define and manipulate data in the template, control rendering behavior, and perform various other operations. The "th:" prefix stands for "Thymeleaf".

For example, some commonly used Thymeleaf attributes include:

  • "th:text": Sets the text value of an HTML element based on the provided expression.

  • "th:if" and "th:unless": Conditionally renders or omits an HTML element based on a specified condition.

  • "th:each": Iterates over a collection and renders HTML elements for each item in the collection.

Features of Thymeleaf

  • Server-side rendering: Thymeleaf enables server-side rendering of web pages, which means that the HTML templates are processed on the server before being sent to the client's browser. This allows for the dynamic generation of web content based on data from the server.

  • Data binding: Thymeleaf provides a way to bind data from the server to the HTML templates. It allows us to insert data dynamically into the templates, making it easy to display and manipulate server-side data on the client side.

  • Template layout: Thymeleaf supports the creation of reusable templates and layout components, which can be shared across multiple pages. This makes it easier to maintain consistent designs and improve code reusability.

  • Integration with Spring Framework: Thymeleaf integrates well with the Spring Framework, especially with the Spring Boot ecosystem. It is the default template engine for Spring Boot applications, providing seamless integration with other Spring features and libraries.

Overall, Thymeleaf is a powerful and popular choice for server-side Java web development, particularly in the Spring Boot ecosystem. Its simplicity, integration with Spring, and the ability to leverage the full power of Java within templates make it a compelling option for building dynamic web applications.

For more details, visit the official site - https://www.thymeleaf.org/index.html

Use Case

To build a login and dashboard using Thymeleaf and Spring Boot, combining the flexibility of server-side rendering with the security of database validation.

Setting up of MySQL using docker-compose method. Later on, we will connect this instance with MySQL Workbench and create user_credentials table along with test data.

docker-compose.yaml

version: "3.9"
# https://docs.docker.com/compose/compose-file/

services:
  db-mysql:
    container_name: db-mysql
    image: mysql:8.0.29
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root
    volumes:
      - mysql-data:/var/lib/mysql

volumes:
  mysql-data:
    driver: local

networks:
  default:
    name: company_default

Start the mysql instance

docker-compose up db-mysql

Open the MySQL Workbench and execute below SQL commands.

ree

ree

Let's proceed with creating our Springboot project

Add the below dependencies in pom.xml file.

pom.xml

       <!-- Spring Boot Starter Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Spring Boot Thymeleaf -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!-- Spring Boot Starter Data JPA -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!-- MySQL Connector/J -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
         <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
         <!-- Spring Dev Tools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

application.yaml

server:
  port: 4141

spring:
  thymeleaf:
    enabled: true
    prefix: classpath:/templates/
    suffix: .html
    mode: HTML
  resources:
    static-locations: classpath:/static/
  datasource:
    url: jdbc:mysql://localhost:3306/users
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver

We will be using HTML templates available for use freely in the project. Download the login and dashboard template from the below sites

Login Template - https://colorlib.com/wp/template/login-form-v8/

Dashboard Template - https://html.design/?s=digit

Create a folder structure like below add the files in the respective folder

ree

Later, we have the update the path in the html files like below as well as update the attribute to Thymeleaf attributes. For example below.

ree
ree

Also, I have added logic to the existing html and css file to highlight when user credential is incorrect.

ree
ree

Next, we can proceed with creating the required Java classes.

Main Application class

Application.java

package com.company.project;

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

@SpringBootApplication
public class Application {

    public static void main(final String[] args) {
        SpringApplication.run(Application.class, args);
    }
} 

Controller class with 2 methods. One method to show login page and other method which gets into action after submitting the login form by entering the credentials.

LoginController.java

package com.company.project.api;

import com.company.project.repository.UserRepository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@RestController
@RequestMapping("/page")
public class LoginController {

    private final UserRepository userRepository;

    @GetMapping("/login")
    public ModelAndView showLoginPage() {
        return new ModelAndView("login/index");
    }

    @PostMapping("/login")
    public ModelAndView processLoginForm(@RequestParam("username") String username,
                                         @RequestParam("password") String password) {
        ModelAndView modelAndView;
        boolean userExists = userRepository.existsByUsernameAndPassword(username, password);
        if (userExists) {
            modelAndView = new ModelAndView("dashboard/index");
        } else {
            modelAndView = new ModelAndView("login/index");
            modelAndView.addObject("errorMessage", "Invalid username or password.");
        }
        return modelAndView;
    }
}

Of course, we have make model class for the user_credentials as well as repository class.

UserCredentials.java

package com.company.project.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;

@Data
@Entity
@Table(name = "user_credentials")
public class UserCredentials {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String username;
    private String password;
    private String email;
}

UserRepository.java

package com.company.project.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import com.company.project.model.UserCredentials;

public interface UserRepository extends JpaRepository<UserCredentials, Long> {
    boolean existsByUsernameAndPassword(String username, String password);
}

Overall, project structure is as below

ree

It's time to run the application and see it in action.

ree

Navigate to this url - http://localhost:4141/page/login

ree

Case 1: Enter incorrect credential

ree

ree

Case 2: Enter correct credential

ree

​

ree

Attached below are the files for reference.

Last updated