Il supporto di Spring Boot in Quarkus è abbastanza esteso, ma esaminarlo nella sua completezza è al di fuori degli obiettivi di questa guida, ci limiteremo quindi a mostrare un ulteriore esempio di compatibilità riguardante la persistenza dei dati.
Sebbene gli utenti siano incoraggiati ad utilizzare Hibernate ORM con Panache per l'accesso a database relazionali, Spring Data JPA repositories è supportato attraverso l'estensione spring-data-jpa
all'interno di un'applicazione Quarkus.
Spring Data JPA in Quarkus
Utilizzando Intellij e il plug-in Quarkus vediamo come creare una semplice applicazione Spring Boot che utilizzi la persistenza dei dati. Creiamo un nuovo progetto Quarkus con impostazioni di default, definiamo successivamente i parametri Maven del progetto ispirandoci al precedente articolo.
Successivamente si deve prestare attenzione alla selezione delle estensioni necessarie per esporre le operazioni di persistenza attraverso un servizio Rest. Andiamo quindi a selezionare nell'area Compatibility l'estensione JPA per Spring Boot:
e RestEasy Jackson nell'area Web :
proseguimo nello step successivo e attendiamo il completamento della creazione del progetto.
Configurazione database Postgres
Partendo da un'installazione Postgres locale in esecuzione è possibile configurare l'accesso al database inserendo il seguente contenuto all'interno del file application.properties
nella sezione "resources" del progetto Maven:
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
fermo restando quanto aggiunto nel file di "properties" il modo più semplice per ottenere un database Postgres pronto all'uso è quello di lavorare con Docker in una macchina virtuale Linux sfruttando VMWARE Workstation Player. In questo articolo utilizziamo questa seconda modalità e Linux Ubuntu 18.04. Andiamo quindi ad installare Docker da terminale con i seguenti comandi:
sudo apt install docker.io
sudo systemctl enable –now docker
sudo usermod -aG docker $USER
avviamo il servizio Docker:
sudo systemctl start docker
sudo service docker start
ed eseguiamo il comando Docker per avere un'installazione Postgres immediatamente disponibile:
docker run --ulimit memlock=-1:-1 -it --rm=true --memory-swappiness=0 --name quarkus_test -e POSTGRES_USER=quarkus_test -e
POSTGRES_PASSWORD=quarkus_test -e POSTGRES_DB=quarkus_test -p 5432:5432 postgres:11.5
Creiamo all'interno della sezione "resources" di Maven il file import.sql
nel quale inserire le seguenti istruzioni SQL che verranno eseguite all'avvio dell'applicazione Quarkus:
INSERT INTO animal(id, name, type) VALUES (1, 'Tiger','Selvatic');
INSERT INTO animal(id, name, type) VALUES (2, 'Lion','Selvatic');
INSERT INTO animal(id, name, type) VALUES (3, 'Dog','Domestic');
Il codice Spring Boot
Prima di presentare il codice Spring Boot dell'applicazione aggiorniamo il file pom di Maven in modo da inserire le dipendenze per il driver JDBC e JUNIT per l'esecuzione atuomatica di test:
io.rest-assured
rest-assured
io.quarkus
quarkus-jdbc-postgresql
io.quarkus
quarkus-junit5
Il servzio Rest che andiamo a realizzare consentirà la gestione di entità di tipo Animal. Definiamo quindi preliminarmente l'entity JPA che rappresenta il concetto Animal:
package it.html.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Animal {
@Id
@GeneratedValue
private Long id;
private String name;
private String type;
public Animal() {
}
public Animal(String name, String type) {
this.name = name;
this.type = type;
}
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 String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
ed il repository Spring Data per il suo utilizzo:
package it.html.repository;
import it.html.entity.Animal;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface AnimalRepository extends CrudRepository {
List findByType(String type);
}
Siamo quindi pronti per definire il semplice servizio Rest che utilizzerà il repository Spring Data per la gestione di tipi Animal:
package it.html.rest;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import it.html.entity.Animal;
import it.html.repository.AnimalRepository;
import org.jboss.resteasy.annotations.jaxrs.PathParam;
import java.util.List;
@Path("/animals")
public class AnimalResource {
private final AnimalRepository fruitRepository;
public AnimalResource(AnimalRepository fruitRepository) {
this.fruitRepository = fruitRepository;
}
@GET
public Iterable findAll() {
return fruitRepository.findAll();
}
@DELETE
@Path("{id}")
public void delete(@PathParam long id) {
fruitRepository.deleteById(id);
}
@POST
@Path("/name/{name}/type/{type}")
public Animal create(@PathParam String name, @PathParam String type) {
return fruitRepository.save(new Animal(name, type));
}
@GET
@Path("/type/{type}")
public List findByType(@PathParam String type) {
return fruitRepository.findByType(type);
}
}
Avvio e test dell'applicazione
Per testare l'applicazione costruiamo una semplice classe di test che invochi i servizi esposti:
package it.html.test;
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.core.IsNot.not;
@QuarkusTest
class AnimalTest {
@Test
void testListAllAnimals() {
given()
.when().get("/animals")
.then()
.statusCode(200)
.body(
containsString("Tiger"),
containsString("Lion"),
containsString("Dog")
);
given()
.when().delete("/animals/1")
.then()
.statusCode(204);
given()
.when().get("/animals")
.then()
.statusCode(200)
.body(
not(containsString("Tiger")),
containsString("Lion"),
containsString("Dog")
);
given()
.when().post("/animals/name/Cat/type/Domestic")
.then()
.statusCode(200)
.body(containsString("Cat"))
.body("id", notNullValue())
.extract().body().jsonPath().getString("id");
given()
.when().get("/animals")
.then()
.statusCode(200)
.body(
not(containsString("Tiger")),
containsString("Lion"),
containsString("Dog"),
containsString("Cat")
);
}
}
Dalla sezione Maven di Intellij eseguiamo quarkus-dev
per avviare l'applicazione e lanciamo i test definiti dalla classe AnimalTest
. L'immagine che segue mostra l'avvio dell'applicazione ed il completamento dei test definiti in precedenza: