Quarkus + Qute + MongoDB CRUD example

Hello everyone, today we will learn how to develop a basic User Management Application using QuarkusQute template, MongoDB, and Panache.
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
  • MongoDB
  • JDK 11
  • Qute 2.2.3.Final
  • MongoDB Panache 2.2.3.Final

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.
<?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-mongodb-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-mongodb-panache</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-qute</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:

quarkus.mongodb.connection-string = mongodb://localhost:27017
quarkus.mongodb.database = quarku-user-data

Create the Model class:

package com.knf.dev.model;

import io.quarkus.mongodb.panache.PanacheMongoEntity;
import org.bson.types.ObjectId;

public class User {

public ObjectId id;
private String firstName;
private String lastName;
private String emailId;

public ObjectId getId() {
return id;
}

public void setId(ObjectId 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 getEmailId() {
return emailId;
}

public void setEmailId(String emailId) {
this.emailId = emailId;
}

public User(ObjectId id, String firstName, String lastName, String emailId) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.emailId = emailId;
}

public User() {
super();
}

}

Create CRUD Repository:

package com.knf.dev.repository;

import com.knf.dev.model.User;
import io.quarkus.mongodb.panache.PanacheMongoRepository;

import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class UserRepository implements PanacheMongoRepository<User> {

}

Create the UserEndPoint class:

package com.knf.dev.Resource;

import com.knf.dev.model.User;
import com.knf.dev.repository.UserRepository;
import io.quarkus.qute.Template;
import io.quarkus.qute.TemplateException;
import io.quarkus.qute.TemplateInstance;
import org.bson.types.ObjectId;
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 {

private final UserRepository userRepository;

@Inject
Template home;

@Inject
Template createupdate;

@Inject
public UserEndpoint(UserRepository userRepository) {
this.userRepository = userRepository;
}


@GET
@Produces(MediaType.TEXT_HTML)
public TemplateInstance getAllUserView()
throws TemplateException {
List<User> users = userRepository.listAll();
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("emailId") String emailId)
throws TemplateException {
User usr = new User();
usr.setEmailId(emailId);
usr.setFirstName(firstName);
usr.setLastName(lastName);
userRepository.persist(usr);
return getAllUserView();
}

@GET
@Produces(MediaType.TEXT_HTML)
@Path("/update/{id}")
public TemplateInstance updateUser
(@PathParam("id") String id)
throws TemplateException {
User user = userRepository.findById(new ObjectId(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 updateUser
(@FormParam("firstName") String firstName,
@FormParam("lastName") String lastName,
@FormParam("emailId") String emailId,
@PathParam("id") String id)
throws TemplateException {
User usr = new User();
usr.setEmailId(emailId);
usr.setFirstName(firstName);
usr.setLastName(lastName);
usr.setId(new ObjectId(id));
userRepository.update(usr);
return getAllUserView();
}

@GET
@Produces(MediaType.TEXT_HTML)
@Path("/delete/{id}")
public TemplateInstance deleteUser(@PathParam("id")
String id)
throws TemplateException, IOException {
User user = userRepository.findById(new ObjectId(id));
userRepository.delete(user);
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>
<style type="text/css">
body { background: purple !important; }
h2,th,td {
color: #f3f3f3;
}
</style>
<body>
<div class="container">
<h2 class="text-light" >User CRUD operation with Quarkus + Qute + MongoDB</h2>
<a href="/create" class="btn btn-primary" role="button">Create New User</a>
<table class="table">
<thead >
<tr>
<th class="text-light bg-dark" scope="col">Id</th>
<th class="text-light bg-dark" scope="col">First Name</th>
<th class="text-light bg-dark" scope="col">Last Name</th>
<th class="text-light bg-dark" scope="col">Email</th>
<th class="text-light bg-dark" scope="col"></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
{#for user in users}
<tr>
<th class="text-light bg-dark" scope="row">{user.id}</th>
<td class="text-light bg-dark">{user.firstName}</td>
<td class="text-light bg-dark">{user.lastName}</td>
<td class="text-light bg-dark">{user.emailId}</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>
<style type="text/css">
body { background: purple !important; }
h2,th {
color: #f3f3f3;
}
</style>
<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="emailId" type="text"
value="{#if user.emailId}{user.emailId}{/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

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

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