Spring Boot + Groovy Templates CRUD Example

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

The Groovy markup template engine provides an innovative templating system based on the builder syntax.
 
It offers various key features: 
  • hierarchical (builder) syntax to generate XML-like contents (in particular, HTML5) 
  • compilation of templates to bytecode for fast rendering
  • internationalization 
  • layout mechanism for sharing structural patterns 
  • optional type checking
and more! 


Following technologies stack being used:

  • Spring Boot 2.5.5
  • Spring MVC 5.3.10
  • Maven 3
  • JDK 11
  • Groovy templates 2.5.5
  • H2DB 
  • Bootstrap

Project Structure



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>springjpagroovycrud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springjpagroovycrud</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-groovy-templates</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>


Create the User Entity 

package com.knf.dev.demo.springjpagroovycrud.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 User Repository

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

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

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


Create the User Service 

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

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import com.knf.dev.demo.springjpagroovycrud.model.User;
import com.knf.dev.demo.springjpagroovycrud.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 User Controller 

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

import com.knf.dev.demo.springjpagroovycrud.model.User;
import com.knf.dev.demo.springjpagroovycrud.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("create", true);
model.addAttribute("actionUrl", "/create");
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("create", false);
model.addAttribute("actionUrl",
"/update/" + (user == null ? 0 : user.getId()) );
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 Groovy templates

home.tpl

yieldUnescaped '<!DOCTYPE html>'
html(lang: 'en') {
head {
meta('http-equiv': '"Content-Type" content="text/html; ' +
'charset=utf-8"')
title("Groovy example")
link(rel: "stylesheet", type: "text/css",
href: "https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css")

}
body {

div(class: 'container') {
h2("User CRUD operation with Groovy Template")
div {
nobr {
a(class: 'btn btn-primary', href: "/create", "Add User")
}
}
br()
br()
div {
table(class: 'table') {
tr {
th("Id")
th("First Name")
th("Last Name")
th("Email")
th("")
th("")
}
users.each { user ->
tr {
td("$user.id")
td("$user.first_name")
td("$user.last_name")
td("$user.email")
td {
a(class: 'btn btn-warning',
href: "/update/$user.id", "Edit")
}
td {
a(class: 'btn btn-danger',
href: "/delete/$user.id", "Delete")
}
}
}
}
}

}
}
}


create-update.tpl

yieldUnescaped '<!DOCTYPE html>'
html(lang: 'en') {
head {
meta('http-equiv': '"Content-Type" content="text/html; ' +
'charset=utf-8"')
title("Groovy example")
link(rel: "stylesheet", type: "text/css",
href: "https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css")
}
body {
div(class: 'container') {
if (create) {
h1("Create a User:")
} else {
h1("Edit User")
}
a(class: 'btn btn-primary', href: "/", "Back to User List")
br()
br()
form(id: "editForm", action: "$actionUrl", method: "POST") {
table(class: 'table') {
if (!create) {
tr {
td("Id")
td(":")
td(user.id ?: '')
}
}
tr {
td("First Name")
td(":")
td {
input(name: 'first_name', type: 'text',
value: user.last_name ?: '')
}
}
tr {
td("Last Name")
td(":")
td {
input(name: 'last_name', type: 'text',
value: user.last_name ?: '')
}
}
tr {
td("Email")
td(":")
td {
input(name: 'email', type: 'text',
value: user.email ?: '')
}
}
}
br()
if (create) {
input(class: 'btn btn-success', type: 'submit',
value: 'Create')
} else {
input(class: 'btn btn-success', type: 'submit',
value: 'Update')
}
}
}
}
}



Spring Boot Main Driver

package com.knf.dev.demo.springjpagroovycrud;

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

@SpringBootApplication
public class SpringjpagroovycrudApplication {

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


Download the complete source code - click here                               

Local Setup and Run the application

Step1: Download or clone the source code from GitHub to the local machine - Click here

Step 2: mvn clean install

Step 3: Run the Spring Boot application - mvn spring-boot:run


Popular posts from this blog

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

Java Stream API - How to convert List of objects to another List of objects using Java streams?

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Spring Boot + Mockito simple application with 100% code coverage

Top 5 Java ORM tools - 2024

Java - Blowfish Encryption and decryption Example

Spring boot video streaming example-HTML5

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete