Quarkus + Qute CRUD example

Hello everyone, today we will learn how to develop a basic User Management Application using Quarkus, Qute template and RDBMS.
GitHub repository link is provided at the end of this tutorial. You can download the source code.

Following technologies stack being used:

  • Quarkus 2.2.3.Final
  • Hibernate 5.5.7.Final
  • Maven 3
  • JDK 11
  • Qute 2.2.3.Final
  • H2DB 

After completing this tutorial what we will build? 

We will build a full-stack web application  with CRUD features:
• Create User
• List User
• Update User 
• Delete User 

User Interface

Add User:

Retrieve All Users:

Update User:

Final Project Directory:


Maven[pom.xml]

A Project Object Model or POM is the fundamental unit of work in Maven. It is an XML file that contains information about the project and configuration details utilized by Maven to build the project. It contains default values for most projects. Some of the configurations that can be designated in the POM is the project dependencies, the plugins or goals that can be executed, the build profiles, and so on. Other information such as the project version, description, developers, mailing lists and such can withal be designated.

If you want to use Qute you need to add the quarkus-resteasy-qute extension. In your pom.xml file.
<?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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<
modelVersion>4.0.0</modelVersion>

<
groupId>com.knf.dev</groupId>
<
artifactId>quarkus-qute-crud</artifactId>
<
version>1.0</version>

<
properties>
<
compiler-plugin.version>3.8.1</compiler-plugin.version>
<
maven.compiler.parameters>true</maven.compiler.parameters>
<
maven.compiler.source>11</maven.compiler.source>
<
maven.compiler.target>11</maven.compiler.target>
<
project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<
project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<
quarkus-plugin.version>2.2.3.Final</quarkus-plugin.version>
<
quarkus.platform.artifact-id>quarkus-universe-bom</quarkus.platform.artifact-id>
<
quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id>
<
quarkus.platform.version>2.2.3.Final</quarkus.platform.version>
<
surefire-plugin.version>2.22.1</surefire-plugin.version>
</
properties>

<
dependencyManagement>
<
dependencies>
<
dependency>
<
groupId>${quarkus.platform.group-id}</groupId>
<
artifactId>${quarkus.platform.artifact-id}</artifactId>
<
version>${quarkus.platform.version}</version>
<
type>pom</type>
<
scope>import</scope>
</
dependency>
</
dependencies>
</
dependencyManagement>

<
dependencies>
<
dependency>
<
groupId>io.quarkus</groupId>
<
artifactId>quarkus-resteasy-jsonb</artifactId>
</
dependency>

<
dependency>
<
groupId>io.quarkus</groupId>
<
artifactId>quarkus-hibernate-orm</artifactId>
</
dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-qute</artifactId>
</dependency>

<
dependency>
<
groupId>io.quarkus</groupId>
<
artifactId>quarkus-jdbc-h2</artifactId>
</
dependency>
<
dependency>
<
groupId>io.quarkus</groupId>
<
artifactId>quarkus-junit5</artifactId>
<
scope>test</scope>
</
dependency>
<
dependency>
<
groupId>io.rest-assured</groupId>
<
artifactId>rest-assured</artifactId>
<
scope>test</scope>
</
dependency>
</
dependencies>

<
build>
<
plugins>
<
plugin>
<
groupId>io.quarkus</groupId>
<
artifactId>quarkus-maven-plugin</artifactId>
<
version>${quarkus-plugin.version}</version>
<
executions>
<
execution>
<
goals>
<
goal>build</goal>
</
goals>
</
execution>
</
executions>
</
plugin>
<
plugin>
<
artifactId>maven-compiler-plugin</artifactId>
<
version>${compiler-plugin.version}</version>
</
plugin>
<
plugin>
<
artifactId>maven-surefire-plugin</artifactId>
<
version>${surefire-plugin.version}</version>
<
configuration>
<
systemProperties>
<
java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
</
systemProperties>
</
configuration>
</
plugin>
</
plugins>
</
build>

<
profiles>
<
profile>
<
id>native</id>
<
activation>
<
property>
<
name>native</name>
</
property>
</
activation>
<
build>
<
plugins>
<
plugin>
<
artifactId>maven-failsafe-plugin</artifactId>
<
version>${surefire-plugin.version}</version>
<
executions>
<
execution>
<
goals>
<
goal>integration-test</goal>
<
goal>verify</goal>
</
goals>
<
configuration>
<
systemProperties>
<
native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
</
systemProperties>
</
configuration>
</
execution>
</
executions>
</
plugin>
</
plugins>
</
build>
<
properties>
<
quarkus.package.type>native</quarkus.package.type>
</
properties>
</
profile>
</
profiles>
</
project>

application.properties:

# datasource configuration
quarkus.datasource.db-kind = h2
quarkus.datasource.username = sa
# quarkus.datasource.password =
quarkus.datasource.jdbc.url = jdbc:h2:mem:test

# drop and create the database at startup (use `update` to only update the schema)
quarkus.hibernate-orm.database.generation=drop-and-create

Create the Entity class:

package com.knf.dev;

import javax.persistence.*;
import java.io.Serializable;

@Table(name = "users")
@Entity
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
private String email;


public User(Long id, String firstName, String lastName, String email) {
super();
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}

public Long getId() {
return id;
}

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

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public String getEmail() {
return email;
}

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

public User() {
super();
}

}

Create CRUD Repository:

package com.knf.dev;

import javax.inject.Inject;
import javax.inject.Singleton;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
import java.util.List;

@Singleton
public class UserResource {

@Inject
EntityManager entityManager;

public List<User> getUsers() {
return entityManager.createQuery("SELECT c FROM User c").getResultList();
}

public User getUser(Long id) {
return entityManager.find(User.class, id);
}

@Transactional(Transactional.TxType.REQUIRED)
public User addUser(User user) {
entityManager.persist(user);
return user;
}

@Transactional(Transactional.TxType.REQUIRED)
public void updateUser(User user) {
entityManager.merge(user);
}

@Transactional(Transactional.TxType.REQUIRED)
public void deleteUser(Long id) {
User user = getUser(id);
entityManager.remove(user);
}
}

Create the UserEndPoint class:

package com.knf.dev;

import io.quarkus.qute.Template;
import io.quarkus.qute.TemplateException;
import io.quarkus.qute.TemplateInstance;
import javax.inject.Inject;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Path("/")
public class UserEndpoint {

@Inject
Template home;

@Inject
Template createupdate;

@Inject
UserResource userResource;

@GET
@Produces(MediaType.TEXT_HTML)
public TemplateInstance getAllUserView()
throws TemplateException {
List<User> users = userResource.getUsers();
return home.data(Map.of("users", users));
}

@GET
@Path("/create")
@Produces(MediaType.TEXT_HTML)
public TemplateInstance createUserView()
throws TemplateException, IOException {
User user = new User();
Map<String, Object> obj = new HashMap<>();
obj.put("user", user);
obj.put("isUpdate", false);
return createupdate.data(obj);
}

@POST
@Produces(MediaType.TEXT_HTML)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/create")
public TemplateInstance createUser
(@FormParam("firstName") String firstName,
@FormParam("lastName") String lastName,
@FormParam("email") String email)
throws TemplateException {
User usr = new User();
usr.setEmail(email);
usr.setFirstName(firstName);
usr.setLastName(lastName);
userResource.addUser(usr);
return getAllUserView();
}

@GET
@Produces(MediaType.TEXT_HTML)
@Path("/update/{id}")
public TemplateInstance updateUser
(@PathParam("id") Long id)
throws TemplateException {
User user = userResource.getUser(id);
Map<String, Object> obj = new HashMap<>();
obj.put("user", user);
obj.put("isUpdate", true);
return createupdate.data(obj);
}

@POST
@Path("/update/{id}")
@Produces(MediaType.TEXT_HTML)
public TemplateInstance createUser
(@FormParam("firstName") String firstName,
@FormParam("lastName") String lastName,
@FormParam("email") String email,
@PathParam("id") Long id)
throws TemplateException {
User usr = new User();
usr.setEmail(email);
usr.setFirstName(firstName);
usr.setLastName(lastName);
usr.setId(id);
userResource.updateUser(usr);
return getAllUserView();
}

@GET
@Produces(MediaType.TEXT_HTML)
@Path("/delete/{id}")
public TemplateInstance deleteUser(@PathParam("id")
Long id)
throws TemplateException, IOException {
userResource.deleteUser(id);
return getAllUserView();
}
}

Creating Qute templates

home.html

<!doctype html>
<head>
<title>Qute 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 Quarkus + Qute 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>
{#for user in users}
<tr>
<th scope="row">{user.id}</th>
<td>{user.firstName}</td>
<td>{user.lastName}</td>
<td>{user.email}</td>
<td><a href="/update/{user.id}" class="btn btn-warning" role="button">
Update</a></td>
<td><a href="/delete/{user.id}" class="btn btn-danger" role="button">
Delete</a></td>
</tr>
{/for}
</tbody>
</table>
</div>
</body>
</html>

createupdate.html

<!doctype html>
<head>
<title>Qute 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>
{#if !isUpdate}Create {/if}
{#if isUpdate} Update {/if}
User
</h2>
<div>
<form action="{#if isUpdate} /update/{user.id}{/if}{#if !isUpdate} /create {/if}"
method="post" name="user">
<table class="table">
<tbody>
<thead>
<tr>
<th>Field</th>
<th>Value</th>
</tr>
</thead>
<tbody>
{#if isUpdate}
<tr>
<th>ID</th>
<td>
<div name="id">{user.id}</div>
</td>
</tr>
{/if}
<tr>
<th>First Name</th>
<td><input name="firstName" type="text"
value="{#if user.firstName}{user.firstName}{/if}"/>
</td>
</tr>
<tr>
<th>Last Name</th>
<td><input name="lastName" type="text"
value="{#if user.lastName}{user.lastName}{/if}"/></td>
</tr>
<tr>
<th>Email</th>
<td><input name="email" type="text"
value="{#if user.email}{user.email}{/if}"/></td>
</tr>
</tbody>
</table>
<button class="btn btn-primary" type="submit">Save</button>
</form>
</div>
</div>
</body>
</html>

Run the Application

Build application  jar file: mvn clean package

Start the applicationjava -jar quarkus-run.jar

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


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