Mustache is a template template system that supports with different programming languages.

In this article, we will learn how to use Mustache templates with Spring Boot to build a Web application.

We will create a web application that performs CRUD operation on an entity using Spring Boot and Mustache.

Technologies used in this article are:

  • Spring Boot version : 2.3.0.RELEASE
  • Java version 1.8.

Create Spring Boot application

Create a Spring Boot application with required dependencies. We will use spring-boot-starter-web, spring-boot-starter-mustache, spring-boot-starter-data-jpa Lombok(To reduce boilerplate code) and H2(H2 Embedded database) maven dependencies.

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-mustache</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
	<groupId>com.h2database</groupId>
	<artifactId>h2</artifactId>
	<scope>runtime</scope>
</dependency>
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<optional>true</optional>
</dependency>

Configure H2 Database and Mustache

Add the below properties to the Spring Boot application’s application.properties configuration file under the /src/main/resources directory.

spring.datasource.url=jdbc:h2:~/asbdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.data-username=sa
spring.datasource.data-password=

spring.mustache.prefix=classpath:/templates/
spring.mustache.suffix=.html

We are setting the data source URL, username, and password of the H2 database.

We have also set the configuration that helps spring boot to locate the mustache template files. We will soon add the HTML template pages under the src/main/resources/templates directory.

Creating the Repository, Service, and Controller layers

We will create CRUD functionality to save, update, fetch, and delete the employee object.

Create Entity class and Repository layer

Create a JPA entity class with the name Employee.java.

This class maps id and name columns of the Employee table to the entity class.

package com.asbnotebook.employee;

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

import lombok.Data;

@Data
@Entity
public class Employee {

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private Integer id;
	
	@Column(name="name")
	private String name;
}

Create a JPA repository with the name EmployeeRepository.java interface by extending the Spring Boot’s JpaRepository interface.

Spring JPA starter dependency provides built-in support to perform CRUD operation on our Employee entity.

package com.asbnotebook.employee;

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

public interface EmployeeRepository extends JpaRepository<Employee, Integer> {

}

Create Service layer

Create a service layer by creating an EmployeeService.java class. This class will handle all the CRUD operations related to the Employee entity.

package com.asbnotebook.employee;

import java.util.List;

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

@Service
public class EmployeeService {

	@Autowired
	private EmployeeRepository employeeRepository;

	public List<Employee> getAllEmployees() {
		return employeeRepository.findAll();
	}

	public Employee createEmployee(Employee employee) {
		return employeeRepository.save(employee);
	}

	public Employee updateEmployee(Employee employee, Integer id) {
		Employee emp = employeeRepository.getOne(id);
		emp.setName(employee.getName());
		return employeeRepository.save(emp);
	}

	public String deleteEmployee(Integer id) {
		employeeRepository.deleteById(id);
		return "Employee deleted successfully";
	}

	public Employee getEmployee(Integer id) {
		return employeeRepository.getOne(id);
	}
}

Create Controller layer

Create the controller layer by creating a Spring web MVC controller class with the name EmployeeController.java

package com.asbnotebook.employee;

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.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
public class EmployeeController {

	@Autowired
	private EmployeeService employeeService;

	@GetMapping("/")
	public String getAllEmployees(Model model) {
		List<Employee> employees = employeeService.getAllEmployees();
		model.addAttribute("employees", employees);
		return "home";
	}

	@GetMapping("/create")
	public String createEmployeePage(Model model) {
		Employee employee = new Employee();
		model.addAttribute("employee", employee);
		model.addAttribute("isUpdate", false);
		return "create-update";
	}

	@GetMapping("/update/{id}")
	public String updateEmployeePage(Model model, @PathVariable("id") Integer id) {
		Employee employee = employeeService.getEmployee(id);
		model.addAttribute("employee", employee);
		model.addAttribute("isUpdate", true);
		return "create-update";
	}

	@PostMapping("/update/{id}")
	public String createEmployee(@ModelAttribute("employee") Employee employee, @PathVariable("id") Integer id) {
		employeeService.updateEmployee(employee, id);
		return "redirect:/";
	}

	@PostMapping("/create")
	public String createEmployee(@ModelAttribute("employee") Employee employee) {
		employeeService.createEmployee(employee);
		return "redirect:/";
	}

	@GetMapping("/delete/{id}")
	public String deleteEmployee(@PathVariable("id") Integer id) {
		employeeService.deleteEmployee(id);
		return "redirect:/";
	}
}

Important points to notice here are:

  • The URL path “/” is will render the home.html page and displays all the available employees. The “employees” model attribute contains all available employees.
  • The GET URL mapping with path “/create” returns the create employee page. This path will add a new Employee object to the model attribute and renders the create-update.html page.
  • The URL path “/update/{id}” GET mapping will render existing employee details and enables updating the employee name.
  • The model attribute “isUpdate” determines the type of operation.
  • The POST URL mappings with path “/create” and “/update/{id}” are used to create and update the employee details, respectively.
  • The GET URL path “/delete/{id}” deletes a particular employee entity.
  • After create, update, and delete operations, the displays the updated list of employees by redirecting to the home page URL path.

Using the Mustache Templates

Create a home.html page under the /src/main/resources/templates directory.

The home.html page is the home page of our application. This page will display the list of available employee details.

<!doctype html>
<head>
<link rel="stylesheet" 	href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script 
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
<script 	src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
</head>
<body>
	<div class="container">
		<h1>Employee CRUD operation with Mustache</h1>
		<a href="/create">Create New Employee</a>
		<table class="table">
			<thead>
				<tr>
					<th scope="col">Id</th>
					<th scope="col">Name</th>
					<th scope="col"></th>
					<th scope="col"></th>
				</tr>
			</thead>
			<tbody>
				{{#employees}}
				<tr>
					<th scope="row">{{id}}</th>
					<td>{{name}}</td>
					<td><a href="/update/{{id}}">Update</a></td>
					<td><a href="/delete/{{id}}">Delete</a></td>
				</tr>
				{{/employees}}
			</tbody>
		</table>
	</div>
</body>
</html>

Few of the important points here are:

  • We have used bootstrap to give some styling to the application.
  • The mustache’s {{#employees}} and {{/employees}} tag iterate through the Spring model attribute employees. Each iteration repeats the HTML block inside the Mustache tag.
  • We are printing the id and name attributes of each employee object in a table.

Create an HTML page with the name create-update.html.

Create and update employee operation renders this page.

<!doctype html>
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script 
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
<script 
src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
</head>
<body>
	<div class="container">
		<h1>{{^isUpdate}}Create{{/isUpdate}}{{#isUpdate}}Update{{/isUpdate}}Employee</h1>
		<div>
			<form action="{{#isUpdate}}/update/{{employee.id}}{{/isUpdate}}{{^isUpdate}}/create{{/isUpdate}}"
				name="employee" method="post">
				<table class="table">
					<tbody>
					<thead>
						<tr>
							<th>Field</th>
							<th>Value</th>
						</tr>
					</thead>
					<tbody>
						{{#isUpdate}}
						<tr>
							<td>ID</td>
							<td><div name="id">{{employee.id}}</div></td>
						</tr>
						{{/isUpdate}}
						<tr>
							<th>Name</th>
							<td><input type="text" name="name"
								value="{{#employee.name}}{{employee.name}}{{/employee.name}}" /></td>
						</tr>
					</tbody>
				</table>
				<button type="submit" class="btn btn-primary">Save</button>
			</form>
		</div>
	</div>
</body>
</html>

Few of the relevant points are:

  • The {{#isUpdate}} checks the boolean model attribute to determine whether the create operation or an update. The {{^isUpdate}} Mustache tag is the inverted version.
  • The id field will be auto-generated by JPA during the create employee operation.
  • For update operation, existing employee id, and name parameters will be populated. The id field can not be updated.
  • Mustache’s tag {{employee.name}} maps the input field name‘s value to the employee model attribute.

Testing the application

Run the Spring Boot application. We should be able to perform CRUD operation on the Employee object.

Spring boot Mustache CRUD example

Conclusion

In this article, we learned how to use Mustache with Spring Boot.

We have created CRUD operation on a JPA entity using Spring Data JPA and H2 embedded database.

The complete example code is available on GitHub.

Subscribe to my mailing list to get the latest posts on your mailbox. 🙂

Processing…
Success! You're on the list.

You may also be interested in