Friday, March 4, 2022

Quarkus Spring Data API PostgreSQL CRUD

Quarkus A Kubernetes Native Java stack tailored for OpenJDK HotSpot and GraalVM, crafted from the best of breed Java libraries and standards.

CREATING A Quarkus APPLICATION

In this example we're integration Quarkus + Spring Data API + PostgreSQL.

  • Configuration Quarkus, Spring Data and PostgreSQL.
  • Define Datas models, Repository and Services.
  • Quarkus Resource.

Quarkus Rest  CRUD API 

These are APIs that we need to provide:

Methods Urls
GET /users
GET /users/age/{age}
POST /users/name/{name}/age/{age}
PUT /users/id/{id}/age/{age}
DELETE /users/{id}

Technology

  • Java 17
  • Quarkus 2.7.3.Final
  • PostgreSQL 14.1 
  • Maven 
  • Postman v9.0.8
  • IntelliJ IDEA 2021.2.3 
  • Docker

Project Structure


























Configuration  Quarkus Spring Data PostgreSQL


pom.xml


<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.henry</groupId>
<artifactId>demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<compiler-plugin.version>3.8.1</compiler-plugin.version>
<failsafe.useModulePath>false</failsafe.useModulePath>
<maven.compiler.release>11</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
<quarkus.platform.version>2.7.3.Final</quarkus.platform.version>
<surefire-plugin.version>3.0.0-M5</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>
<repositories>
<repository>
<id>JBoss repository</id>
<url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>2.2.1.GA</version>
</dependency>

<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
<version>2.2.0.GA</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<version>3.6.2.Final</version>
</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>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-spring-data-jpa</artifactId>
</dependency>


<!-- JDBC driver dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.platform.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>build</goal>
<goal>generate-code</goal>
<goal>generate-code-tests</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compiler-plugin.version}</version>
<configuration>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<configuration>
<systemPropertyVariables>
<java.util.logging.manager>
org.jboss.logmanager.LogManager
</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
</systemPropertyVariables>
</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>
<systemPropertyVariables>
<native.image.path>
${project.build.directory}/${project.build.finalName}-runner
</native.image.path>
<java.util.logging.manager>org.jboss.logmanager.LogManager
</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<quarkus.package.type>native</quarkus.package.type>
</properties>
</profile>
</profiles>
</project>
  

application.properties


quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=quarkus_test
quarkus.datasource.password=quarkus_test
quarkus.datasource.jdbc.url=jdbc:postgresql:quarkus_test
quarkus.datasource.jdbc.max-size=8
quarkus.datasource.jdbc.min-size=2
quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.http.port=9000

Set up PostgreSQL


docker run -it --rm=true --name quarkus_test -e POSTGRES_USER=quarkus_test -e POSTGRES_PASSWORD=quarkus_test -e POSTGRES_DB=quarkus_test -p 5432:5432 postgres:14.1

Data class model


package com.henry.model;

import javax.persistence.*;

@Entity
@Table(name="USERS")
public class User {

@Id
@SequenceGenerator(name = "USERS_id", sequenceName = "USERS_id", initialValue = 1, allocationSize = 1)
@GeneratedValue(generator = "USERS_id")
private Long id;

private String name;
private Integer age;

public User(){}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}

public Long getId() {
return id;
}

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

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}
}

Repository Interface


package com.henry.repository;

import com.henry.model.User;
import org.springframework.data.repository.CrudRepository;

import java.util.List;

public interface UserRepository extends CrudRepository<User, Long> {

List<User> findByAge(Integer age);
}

Service Interface



package com.henry.service;

import com.henry.model.User;

import java.util.List;
import java.util.Optional;

public interface UserService {

public Iterable<User> findAll();
public Optional<User> findById(long id);
public void delete(long id);
public User create(String name,Integer age);
public User changeAge(Long id,Integer age);
public List<User> findByAge(Integer age);
}

Service Class

package com.henry.service.impl;

import com.henry.model.User;
import com.henry.repository.UserRepository;
import com.henry.service.UserService;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class UserServiceImpl implements UserService {

private final UserRepository userRepository;

public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}

@Override
public Iterable<User> findAll() {
return userRepository.findAll();
}

@Override
public Optional<User> findById(long id) {
return userRepository.findById(id);
}

@Override
public void delete(long id) {
userRepository.deleteById(id);
}

@Override
public User create(String name, Integer age) {
return userRepository.save(new User(name, age));
}

@Override
public User changeAge(Long id, Integer age) {
Optional<User> optional = userRepository.findById(id);
if (optional.isPresent()) {
User user = optional.get();
user.setAge(age);
return userRepository.save(user);
}

throw new IllegalArgumentException("No User with id " + id + " exists");
}

@Override
public List<User> findByAge(Integer age) {
return userRepository.findByAge(age);
}
}

Quarkus Rest APIs Resource


package com.henry.resource;

import com.henry.model.User;
import com.henry.service.UserService;
import org.jboss.resteasy.annotations.jaxrs.PathParam;

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.List;

@Path("/users")
public class UserResource {

private final UserService userService;

public UserResource(UserService userService) {
this.userService = userService;
}

@GET
@Produces(MediaType.APPLICATION_JSON)
public Iterable<User> findAll() {
return userService.findAll();
}


@DELETE
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public void delete(@PathParam long id) {
userService.delete(id);
}

@POST
@Path("/name/{name}/age/{age}")
@Produces(MediaType.APPLICATION_JSON)
public User create(@PathParam String name, @PathParam Integer age) {

return userService.create(name, age);
}

@PUT
@Path("/id/{id}/age/{age}")
@Produces(MediaType.APPLICATION_JSON)
public User changeAge(@PathParam Long id, @PathParam Integer age) {
return userService.changeAge(id, age);
}

@GET
@Path("/age/{age}")
@Produces(MediaType.APPLICATION_JSON)
public List<User> findByAge(@PathParam Integer age) {

return userService.findByAge(age);
}
}

Run & Test


Run Quarkus application with next maven command :
./mvnw compile quarkus:dev or ./mvnw test (Run test class) by console or IntelliJ.




GET.










 














GET.



























POST.


























PUT.






















DELETE.























Source Code


Here on Github.



References.



https://quarkus.io/guides/spring-data-jpa














No comments:

Post a Comment

Virtual Threads in Java 21: Simplified Concurrency for Modern Applications

  With Java 21, Virtual Threads have redefined how we approach concurrency, offering a lightweight and efficient way to handle parallel and ...