Spring Boot + Mustache + JPA - CRUD example

Hello everyone, Today we will learn how to develop a Spring Boot CRUD web application, using Spring Boot, Mustache template, H2DB, and JPA.



Following technologies stack being used:
  • Spring Boot 2.5.5
  • Spring MVC 5.3.10
  • Maven 3
  • JDK 11
  • Mustache 1.15
  • H2DB 
  • Bootstrap

Project Structure:


Dependency Management-Maven-Pom.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.5.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.knf.dev.demo</groupId>
<artifactId>springbootjpamustachecrud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springbootjpamustachecrud</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-data-jpa</artifactId>
</dependency>
<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>com.h2database</groupId>
<artifactId>h2</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>

Configure the Entity class

package com.knf.dev.demo.springbootjpamustachecrud.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;

@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "first_name")
private String first_name;
@Column(name = "last_name")
private String last_name;
@Column(name = "email", nullable = false, length = 200)
private String email;

public User() {
super();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirst_name() {
return first_name;
}
public void setFirst_name(String first_name) {
this.first_name = first_name;
}
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

Create CRUD Repository

package com.knf.dev.demo.springbootjpamustachecrud.repository;

import com.knf.dev.demo.springbootjpamustachecrud.model.User;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends CrudRepository<User, Long> {
}

Create the Service class

package com.knf.dev.demo.springbootjpamustachecrud.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import com.knf.dev.demo.springbootjpamustachecrud.model.User;
import com.knf.dev.demo.springbootjpamustachecrud.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.persistence.EntityNotFoundException;

@Service
public class UserService {
@Autowired
UserRepository repository;

public List<User> getAllusers() {
List<User> result = (List<User>) repository.findAll();
if (result.size() > 0) {
return result;
} else {
return new ArrayList<User>();
}
}

public User getUserById(Long id) throws EntityNotFoundException {
Optional<User> user = repository.findById(id);
if (user.isPresent()) {
return user.get();
} else {
throw new EntityNotFoundException("No user record exist for given id");
}
}

public User createOrUpdateUser(User entity) {
if (entity.getId() == null) {
entity = repository.save(entity);
return entity;
} else {
Optional<User> user = repository.findById(entity.getId());
if (user.isPresent()) {
User newEntity = user.get();
newEntity.setEmail(entity.getEmail());
newEntity.setFirst_name(entity.getFirst_name());
newEntity.setLast_name(entity.getLast_name());
newEntity = repository.save(newEntity);
return newEntity;
} else {
entity = repository.save(entity);
return entity;
}
}
}

public void deleteUserById(Long id) throws EntityNotFoundException {
Optional<User> user = repository.findById(id);
if (user.isPresent()) {
repository.deleteById(id);
} else {
throw new EntityNotFoundException("No user record exist for given id");
}
}
}

Create the Web Controller class

package com.knf.dev.demo.springbootjpamustachecrud.controller;

import com.knf.dev.demo.springbootjpamustachecrud.model.User;
import com.knf.dev.demo.springbootjpamustachecrud.service.UserService;
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 javax.persistence.EntityNotFoundException;
import java.util.List;

@Controller
public class UserController {

@Autowired
private UserService userService;
@GetMapping("/")
public String getAllUserView(Model model) {
List<User> users = userService.getAllusers();
model.addAttribute("users", users);
return "home";
}
@GetMapping("/create")
public String createUserView(Model model) {
User user = new User();
model.addAttribute("user", user);
model.addAttribute("isUpdate", false);
return "create-update";
}
@PostMapping("/update/{id}")
public String createUser(@ModelAttribute("user") User user,
@PathVariable("id") Long id) {
user.setId(id);
userService.createOrUpdateUser(user);
return "redirect:/";
}
@GetMapping("/update/{id}")
public String updateUser(Model model, @PathVariable("id") Long id)
throws EntityNotFoundException {
User user = userService.getUserById(id);
model.addAttribute("user", user);
model.addAttribute("isUpdate", true);
return "create-update";
}
@PostMapping("/create")
public String createUser(@ModelAttribute("user") User user) {
userService.createOrUpdateUser(user);
return "redirect:/";
}
@GetMapping("/delete/{id}")
public String deleteUser(@PathVariable("id") Long id)
throws EntityNotFoundException {
userService.deleteUserById(id);
return "redirect:/";
}
}

Creating Mustache templates

home.mustache

<!doctype html>
<head>
<title>Mustache Example</title>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1" name="viewport">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js">
</script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js">
</script>
</head>
<body>
<div class="container">
<h2>User CRUD operation with Mustache Template</h2>
<a href="/create" class="btn btn-primary" role="button">Create New User</a>
<table class="table">
<thead >
<tr>
<th scope="col">Id</th>
<th scope="col">First Name</th>
<th scope="col">Last Name</th>
<th scope="col">Email</th>
<th scope="col"></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
{{#users}}
<tr>
<th scope="row">{{id}}</th>
<td>{{first_name}}</td>
<td>{{last_name}}</td>
<td>{{email}}</td>
<td><a href="/update/{{id}}" class="btn btn-warning" role="button">
Update</a></td>
<td><a href="/delete/{{id}}" class="btn btn-danger" role="button">
Delete</a></td>
</tr>
{{/users}}
</tbody>
</table>
</div>
</body>
</html>

create-update.mustache

<!doctype html>
<head>
<title>Mustache Example</title>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1" name="viewport">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js">
</script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js">
</script>
</head>
<body>
<div class="container">
<h1>{{^isUpdate}}Create{{/isUpdate}}
{{#isUpdate}}Update{{/isUpdate}}User</h1>
<div>
<form action="{{#isUpdate}}/update/{{user.id}}
{{/isUpdate}}{{^isUpdate}}/create{{/isUpdate}}"
name="user" 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">{{user.id}}</div></td>
</tr>
{{/isUpdate}}
{{#user}}
<tr>
<th>First Name</th>
<td><input type="text" name="first_name"
value="{{#first_name}}{{first_name}}{{/first_name}}" /></td>
</tr>
<tr>
<th>Last Name</th>
<td><input type="text" name="last_name"
value="{{#last_name}}{{last_name}}{{/last_name}}" /></td>
</tr>
<tr>
<th>Email</th>
<td><input type="text" name="email"
value="{{#email}}{{email}}{{/email}}" /></td>
</tr>
{{/user}}
</tbody>
</table>
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
</div>
</body>
</html>

Spring Boot Main Class

package com.knf.dev.demo.springbootjpamustachecrud;

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

@SpringBootApplication
public class SpringbootjpamustachecrudApplication {

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

}

Run

$ mvn spring-boot:run

Access the URL in  the browser: http://localhost:8080/

Create User:

List all Users:

Update User:

Popular posts from this blog

Spring boot video streaming example-HTML5

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Spring Boot + Mockito simple application with 100% code coverage

Spring Boot + OpenCSV Export Data to CSV Example

Custom Exception Handling in Quarkus REST API

DataTable-Pagination example with Spring boot, jQuery and ajax

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Node JS mini projects with source code - free download

Spring boot web project free download:User Registration System

Java - Blowfish Encryption and decryption Example