Sunday, March 26, 2023

Thymeleaf To Build Spring MVC Web Application

springframework,springboot,controller,thymeleaf,java,programming,software development,technology This tutorial is on how to use Thymeleaf to build Spring MVC Web Applications with Spring Boot. We will learn how to add Thymeleaf expressions to our HTML page and how to style the HTML pages.

👉 So what is Thymeleaf? According to thymeleaf.org, it is a modern server-side Java template engine for web and standalone environments. According to Wikipedia, a "template processor" (also known as a "template engine" or "template parser") is software designed to combine templates with a data model to produce result documents.

👉 So how does Thymeleaf help build Spring Web applications? The Spring Web Framework is built using the MVC (Model-View-Controller) pattern. In the MVC pattern, "Model" is actually the data, and "View" is how we arrange the data to present it to the world. Now the template engine, like Thymeleaf, helps us bind the data model with views. We use HTML to create views. To bind the dynamic content with the HTML, we use Thymeleaf expressions, and the Thymeleaf expressions can access Java codes, objects, and Spring Beans.

Create Spring Boot Project

Here is the pom.xml of the Spring Boot project:
<?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.7.8</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.raven</groupId>
	<artifactId>springboot-thymeleaf-demo</artifactId>
	<version>springboot-thymeleaf-demo-1.0.0</version>
	<name>springboot-thymeleaf-demo</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>11</java.version>
	</properties>
	<dependencies>
		<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>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>
We have used 2.7.8 as our Spring Boot version. We have added a spring-boot-starter-thymeleaf dependency to use Thymeleaf in our web application.

👉 To demonstrate how to use Thymeleaf with a Spring MVC Web application, we create a controller class to generate a model and then bind the model in the Thymeleaf template (a simple HTML page) using Thymeleaf expressions.

Motivation Controller

Create a package of name controller under the root package. Inside this controller package, create a class: MotivationController and add the following code snippet:
package com.raven.springbootthymeleafdemo.controller;

import java.util.Random;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class MotivationController {
	@GetMapping("/motivation")
	public String motivation(Model _model) {
		String motivationString = "";
		Random random = new Random();
		int randomInt = random.nextInt(9); // random integers from 0 to 8

		switch (randomInt) {
		case 0:
			motivationString = "Inspiration does exist, but it must find you working. — Pablo Picasso";
			break;
		case 1:
			motivationString = "Success is stumbling from failure to failure with no loss of enthusiasm. — Winston Churchill";
			break;
		case 2:
			motivationString = "Keep your eyes on the stars, and your feet on the ground. — Theodore Roosevelt";
			break;
		case 3:
			motivationString = "Get a good idea and stay with it. Dog it, and work at it until it’s done right. — Walt Disney";
			break;
		case 4:
			motivationString = "Optimism is the faith that leads to achievement. Nothing can be done without hope and confidence. — Helen Keller";
			break;
		case 5:
			motivationString = "Life is like riding a bicycle. To keep your balance you must keep moving. — Albert Einstein";
			break;
		case 6:
			motivationString = "I have never let my schooling interfere with my education. — Mark Twain";
			break;
		case 7:
			motivationString = "If you really want to do something, you'll find a way. If you don't, you'll find an excuse. — Jim Rohn";
			break;
		case 8:
			motivationString = "Be sure you put your feet in the right place, then stand firm. — Abraham Lincoln";
			break;
		}

		_model.addAttribute("motivationString", motivationString);

		return "motivation";
	}
}
We are using Spring Model as the container for our application data. We can put anything in the model - string, list, object, etc. Then in the Thymeleaf template (view page) we can retrieve the data from the model and bind the data with the HTML tag using Thymeleaf expressions.

So we have added the data in the model using addAttribute() method and the attribute name is motivationString.

Finally returns a string motivation. As we have added the Thymeleaf dependency in the pom.xml, Spring Framework will automatically configure the Thymeleaf for us. So when we return motivation, Spring Framework will look for motivation.html resource in the template directory.

Motivation View

Now we will create a view page (Thymeleaf template). So create an HTML page named motivation.html in the /resources/templates directory:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">

<head>
<title>Motivation</title>
</head>

<body>
	<p th:text="${motivationString}" style="font-size:24px; color:red;"></p>
</body>

</html>
To use the Thymeleaf expressions in the HTML page, we have added the Thymeleaf namespace at the beginning using xmlns:th. Now we can use th:* attributes in our HTML page.

We used the Thymeleaf expression th:text="${motivationString}" to bind the motivationString attribute with the HTML tag that was set into the model in our controller class.

Here th:text attribute is used to evaluate the expression that is assigned to it and set the result of the evolution in the HTML tag. Using ${...} we are defining the expression. This type of expression is known as value expression which is generally used to execute the model attributes. There are other types of expressions: selection variable or asterisk expressions (*{...}) execute on the selected objects, message expressions (#{...}) are for internationalization, and link expressions (@{...}) re-write URLs.   

Run the application and put this URL http://localhost:8082/motivation in the browser. You can see one of the motivational strings in the browser. If you refresh the page the string will change.

So when we put the URL in the browser on the client side, the browser will forward this request to the server. On the server, this request is sent to MotivationController, the controller then creates a model with some data, the model is sent to the Thymeleaf Template, and finally, plain HTML is generated by the template engine and sends it back to the browser. So the Thymeleaf template is processed on the server.
JAVA,Software Development,Technology,Programming,Thymeleaf,Spring Boot,


👉 Now we create a Thymeleaf template with an HTML table to bind data using Thymeleaf expressions. To do this, we create a Customer class, the CustomerController class, and the Thymeleaf template.

Customer Class

Create a package of name model under the root package. Inside this model package, create a class: Customer, and then add the following code snippet:
package com.raven.springbootthymeleafdemo.model;

public class Customer {
	private int id;
	private String fullName;
	private String phone;
	private String email;
	private String address;

	public Customer() {
	}

	public Customer(int id, String fullName, 
			String phone, String email, 
			String address) {
		this.id = id;
		this.fullName = fullName;
		this.phone = phone;
		this.email = email;
		this.address = address;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getFullName() {
		return fullName;
	}

	public void setFullName(String fullName) {
		this.fullName = fullName;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public String getEmail() {
		return email;
	}

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

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	@Override
	public String toString() {
		return "Customer [id=" + id + ", fullName=" + fullName + 
				", phone=" + phone + ", email=" + email + ", address="
				+ address + "]";
	}

}
We use this customer class in the controller.

Customer Controller

Inside this controller package, create a class: CustomerController and add the following code snippet:
package com.raven.springbootthymeleafdemo.controller;
// imports are omitted ...

@Controller
@RequestMapping("/customers")
public class CustomerController {
	private List<Customer> customers;

	@PostConstruct
	private void loadCustomers() {
		this.customers = new ArrayList<>();

		Customer customer = new Customer(1, "Schwartz J. Wright", "(000) 666-6666", "schwartz@example.com",
				"5659 Heavner AvenueAtlanta, GAUnited States");
		this.customers.add(customer);

		customer = new Customer(2, "Patricia L. Dubose", "(098) 765-5411", "patricia@example.com",
				"1462 Brown AvenueEnoree, SC, 41231United States");
		this.customers.add(customer);

		customer = new Customer(3, "Patricia L. Dubose", "(098) 765-5411", "patricia@example.com",
				"1462 Brown AvenueEnoree, SC, 41231United States");
		this.customers.add(customer);

		customer = new Customer(4, "Raquel M. Morgan", "(123) 333-3333", "raquel@example.com",
				"1333 Plainfield AvenueNY, 1234United States");
		this.customers.add(customer);

		customer = new Customer(5, "Jill J. Morris", "(123) 555-5555", "jill@example.com",
				"2508 Timber Oak DriveRiverside, CA, 75421United States");
		this.customers.add(customer);
	}

	@GetMapping("/list")
	public ModelAndView listCustomers() {
		ModelAndView modelAndView = new ModelAndView("customers/customerlist");
		modelAndView.addObject("customers", this.customers);

		return modelAndView;
	}
}
You can see inside the loadCustomers() method, we have created a customer list, and using @PostConstruct annotation we are loading the customer list in the memory.

Inside the listCustomers() method, we have used ModelAndView class which holds both Model and View in the Spring Web MVC Framework. We have created an object of ModelAndView by passing the template name (customers/customerlist) in its constructor. Then we put our customer list object in the model with the attribute name customers using the addObject() method. We will use this attribute in the Thymeleaf template to access the customer list.

Here is the template name: customers/customerlist. So, we have to create customerlist.html in the customers directory.
 

Customer Table View

Create a directory of customers in the /resources/templates directory. Now create an HTML file named customerlist.html in /resources/templates/customers and add this code snippet:
<!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Customers</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
</head>
<body>
	<div class="container">
		<hr>
		<h3>Customers</h3>
		<hr>
		<table class="table table-striped table-hover">
			<thead class="thead-dark">
				<tr>
					<th>Name</th>
					<th>Phone</th>
					<th>Email</th>
					<th>Address</th>
				</tr>
			</thead>
			<tbody>
				<tr th:each="customer : ${customers}">
					<td th:text="${customer.fullName}" />
					<td th:text="${customer.phone}" />
					<td th:text="${customer.email}" />
					<td th:text="${customer.address}" />
				</tr>
			</tbody>
		</table>
		<hr>
	</div>
</body>
</html>
We receive the customer list data from the MVC model in the customers attribute. Using the looping expression (th:each="customer : ${customers}") of Thymeleaf, we iterate the customer list. Then binds the customer properties one by one in the table.
 
Restart the application and put this URL http://localhost:8082/customers/list in the browser. Here is the output:
JAVA,Software Development,Technology,Programming,Thymeleaf,Spring Boot,


👉 Now we will learn how to use HTML form in Thymeleaf template to bind data. To do this, we will update the CustomerController class, and then create a new Thymeleaf template to bind the data with the HTML form controls.
 

Customer Controller

Open the CustomerController class and update it with this code snippet:
package com.raven.springbootthymeleafdemo.controller;
// imports are omitted ...

@Controller
@RequestMapping("/customers")
public class CustomerController {
	// ...
  // existing codes
	// ...
  
	@GetMapping("/getCustomerDetails")
	public ModelAndView getCustomerDetails() {
		ModelAndView modelAndView = new ModelAndView("customers/customer_details");

		Customer customer = new Customer(4, "Raquel M. Morgan", "(123) 333-3333", "raquel@example.com",
				"1333 Plainfield AvenueNY, 1234United States");
		modelAndView.addObject("customer", customer);

		return modelAndView;
	}
}
As you can see inside the getCustomerDetails() method, we have created an object of ModelAndView by passing the template name (customers/customer_details) in its constructor. Then we put our customer object in the model with the attribute name customer using the addObject() method. We will use this attribute in the Thymeleaf template to access the customer.
 

Customer Details Form View

Create an HTML file named customer-details.html in /resources/templates/customers and add this code snippet:
<!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Customer details</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
</head>
<body>
	<div class="container">
		<hr>
		<h3>Customers details</h3>
		<hr>
		<form action="#" th:object="${customer}">
			<div class="row mb-3">
				<label class="col-sm-2 col-form-label">Name</label>
				<div class="col-sm-4">
					<input type="text" class="form-control" th:field="*{fullName}">
				</div>
			</div>
			<div class="row mb-3">
				<label class="col-sm-2 col-form-label">Phone</label>
				<div class="col-sm-4">
					<input type="text" class="form-control" th:field="*{phone}">
				</div>
			</div>
			<div class="row mb-3">
				<label class="col-sm-2 col-form-label">Email</label>
				<div class="col-sm-4">
					<input type="text" class="form-control" th:field="*{email}">
				</div>
			</div>
			<div class="row mb-3">
				<label class="col-sm-2 col-form-label">Address</label>
				<div class="col-sm-8">
					<input type="text" class="form-control" th:field="*{address}">
				</div>
			</div>
		</form>
		<hr>
	</div>
</body>
</html>
As you can see, in the th:object expression we have passed our model attribute (customer) to bind the customer data with the HTML form. Then in the input fields, we bind the customer properties one by one using th:field expression. In th:field, we have used the selection value or asterisk expression (*{...}) to select the properties of the referenced object. In the expression, we have passed fullName, phone, email, and address property of the customer (model attribute).

Restart the application and put this URL http://localhost:8082/customers/getCustomerDetails in the browser. Here is the output:
JAVA,Software Development,Technology,Programming,Thymeleaf,Spring Boot,


You can download the source code from here.
Happy coding!!! 😊
in

References:

No comments:

Post a Comment

Popular posts