Esercizio - Creare un'applicazione Quarkus
In questa unità si creerà un'applicazione Quarkus di base. Per avviare l'applicazione si userà Maven e per modificare il codice si userà un ambiente di sviluppo integrato (IDE) di propria scelta. Usare un terminale di propria scelta per eseguire il codice. Per avviare un database PostgreSQL locale, si usa Docker, in modo da poter eseguire e testare l'applicazione attività in locale.
Generare l'applicazione Quarkus usando Maven
Esistono diversi modi per generare una struttura di progetto Quarkus. È possibile usare l'interfaccia Web Quarkus, un plug-in IDE o il plug-in Quarkus Maven. Si userà ora il plug-in Maven per generare la struttura del progetto.
L'applicazione viene generata con diverse dipendenze:
- La dipendenza
resteasyper esporre un endpoint REST - La dipendenza
jacksonper serializzare e deserializzare JSON - La dipendenza
hibernateper interagire con il database - La dipendenza
postgresqlper connettersi al database PostgreSQL - La dipendenza
dockerper compilare un'immagine Docker
Non è necessario specificare le dipendenze di Azure, perché prima si esegue l'applicazione in locale e poi si distribuisce una versione in contenitori in App contenitore di Azure.
Al prompt dei comandi, generare l'attività di applicazione:
mvn -U io.quarkus:quarkus-maven-plugin:3.19.0:create \
-DplatformVersion=3.18.4 \
-DprojectGroupId=com.example.demo \
-DprojectArtifactId=todo \
-DclassName="com.example.demo.TodoResource" \
-Dpath="/api/todos" \
-DjavaVersion=17 \
-Dextensions="resteasy-jackson, hibernate-orm-panache, jdbc-postgresql, docker"
Questo comando crea un nuovo progetto Quarkus. Genera una struttura di directory Maven (src/main/java per il codice sorgente e src/test/java per i test). Crea alcune classi Java, alcuni test e alcuni Dockerfile. Genera anche un filepom.xml con tutte le dipendenze necessarie (Hibernate, RESTEasy, Jackson, PostgreSQL e Docker):
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm-panache</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-image-docker</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</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>
Nota
Tutte le dipendenze nel file pom.xml sono definite nella distinta base (BOM) di Quarkus io.quarkus.platform:quarkus-bom.
Scrivere il codice dell'applicazione
Rinominare quindi la classe MyEntity.java generata in Todo.java (che si trova nella stessa cartella del file TodoResource.java ). Sostituire il codice esistente con il codice Java seguente. Il codice usa Java Persistence API (pacchettojakarta.persistence.*) per archiviare e recuperare dati dal server PostgreSQL. Usa anche Hibernate ORM con Panache (che eredita da io.quarkus.hibernate.orm.panache.PanacheEntity) per semplificare il livello di persistenza.
Si userà un’entità (@Entity) per eseguire il mapping dell’oggettoTodo Java direttamente sulla tabella Todo di PostgreSQL. Quindi, l’endpoint REST TodoResource crea una nuova classe di entità Todo e la rende persistente. Questa classe è un modello di dominio con mapping alla tabella Todo. La tabella viene creata automaticamente da JPA.
Estendendo PanacheEntity si ottengono diversi metodi generici di creazione, lettura, aggiornamento ed eliminazione (CRUD, Create, Read, Update, Delete) per il tipo. In questo modo è possibile eseguire operazioni come il salvataggio e l'eliminazione di oggetti Todo in una sola riga di codice Java.
Aggiungere il codice seguente all’entità Todo:
package com.example.demo;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.Entity;
import java.time.Instant;
@Entity
public class Todo extends PanacheEntity {
public String description;
public String details;
public boolean done;
public Instant createdAt = Instant.now();
@Override
public String toString() {
return "Todo{" +
"id=" + id + '\'' +
", description='" + description + '\'' +
", details='" + details + '\'' +
", done=" + done +
", createdAt=" + createdAt +
'}';
}
}
Per gestire tale classe, aggiornare il TodoResource in modo che possa pubblicare interfacce REST per archiviare e recuperare i dati tramite HTTP. Aprire la classe TodoResource e sostituire il codice con il seguente:
package com.example.demo;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriBuilder;
import jakarta.ws.rs.core.UriInfo;
import org.jboss.logging.Logger;
import java.util.List;
@Path("/api/todos")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public class TodoResource {
@Inject
Logger logger;
@Inject
UriInfo uriInfo;
@POST
@Transactional
public Response createTodo(Todo todo) {
logger.info("Creating todo: " + todo);
Todo.persist(todo);
UriBuilder uriBuilder = uriInfo.getAbsolutePathBuilder().path(todo.id.toString());
return Response.created(uriBuilder.build()).entity(todo).build();
}
@GET
public List<Todo> getTodos() {
logger.info("Getting all todos");
return Todo.listAll();
}
}
Eseguire l'applicazione
Quando si esegue l'applicazione in modalità di sviluppo, Docker deve essere in esecuzione. Questo perché Quarkus rileva che è necessario un database PostgreSQL (a causa della dipendenza quarkus-jdbc-postgresql PostgreSQL dichiarata nel file pom.xml ), scarica l'immagine Docker postgreSQL e avvia un contenitore con il database. Crea quindi automaticamente la tabella Todo nel database.
Assicurarsi che Docker sia in esecuzione in locale nel computer ed eseguire l'applicazione dell’attività usando il comando seguente:
cd todo
./mvnw quarkus:dev # On Mac or Linux
mvnw.cmd quarkus:dev # On Windows
L'applicazione Quarkus verrà avviata e connessa al database. Verrà visualizzato l'output seguente:
2025-02-28 08:38:33,418 INFO [io.qua.dat.dep.dev.DevServicesDatasourceProcessor] (build-28) Dev Services for default datasource (postgresql) started - container ID is ce37977203b0
2025-02-28 08:38:33,421 INFO [io.qua.hib.orm.dep.dev.HibernateOrmDevServicesProcessor] (build-6) Setting quarkus.hibernate-orm.database.generation=drop-and-create to initialize Dev Services managed database
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2025-02-28 08:38:35,278 INFO [io.quarkus] (Quarkus Main Thread) todo 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.18.4) started in 5.367s. Listening on: http://localhost:8080
2025-02-28 08:38:35,280 INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2025-02-28 08:38:35,280 INFO [io.quarkus] (Quarkus Main Thread) Installed features: [agroal, cdi, hibernate-orm, hibernate-orm-panache, jdbc-postgresql, narayana-jta, resteasy, resteasy-jackson, smallrye-context-propagation, vertx]
--
Tests paused
Press [e] to edit command line args (currently ''), [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>
Per testare l'applicazione, è possibile usare cURL.
In un terminale separato creare un nuovo elemento dell’attività nel database con il comando seguente. Verrà visualizzato il log nella console di Quarkus:
curl --header "Content-Type: application/json" \
--request POST \
--data '{"description":"Take Quarkus MS Learn","details":"Take the MS Learn on deploying Quarkus to Azure Container Apps","done": "true"}' \
http://127.0.0.1:8080/api/todos
Questo comando deve restituire l'elemento creato (con un identificatore):
{"id":1,"description":"Take Quarkus MS Learn","details":"Take the MS Learn on deploying Quarkus to Azure Container Apps","done":true,"createdAt":"2025-02-26T07:27:30.093447Z"}
Creare una seconda attività usando il comando cURL seguente:
curl --header "Content-Type: application/json" \
--request POST \
--data '{"description":"Take Azure Container Apps MS Learn","details":"Take the ACA Learn module","done": "false"}' \
http://127.0.0.1:8080/api/todos
Recuperare quindi i dati usando una nuova richiesta cURL:
curl http://127.0.0.1:8080/api/todos
Questo comando restituisce l'elenco delle attività, inclusa quella appena creata:
[
{"id":1,"description":"Take Quarkus MS Learn","details":"Take the MS Learn on deploying Quarkus to Azure Container Apps","done":true},
{"id":2,"description":"Take Azure Container Apps MS Learn","details":"Take the ACA Learn module","done":false}
]
Testare l'applicazione
Per testare l'applicazione, è possibile usare la classe TodoResourceTest esistente. Deve testare l'endpoint REST. Per testare l'endpoint, usa RESTAssured. Sostituire il codice nella classe TodoResourceTest con il codice seguente:
package com.example.demo;
import io.quarkus.test.junit.QuarkusTest;
import static io.restassured.RestAssured.given;
import static jakarta.ws.rs.core.HttpHeaders.CONTENT_TYPE;
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
import org.junit.jupiter.api.Test;
@QuarkusTest
class TodoResourceTest {
@Test
void shouldGetAllTodos() {
given()
.when().get("/api/todos")
.then()
.statusCode(200);
}
@Test
void shouldCreateATodo() {
Todo todo = new Todo();
todo.description = "Take Quarkus MS Learn";
todo.details = "Take the MS Learn on deploying Quarkus to Azure Container Apps";
todo.done = true;
given().body(todo)
.header(CONTENT_TYPE, APPLICATION_JSON)
.when().post("/api/todos")
.then()
.statusCode(201);
}
}
Per testare l'applicazione, è anche necessario che Docker Desktop sia in esecuzione, perché Quarkus rileva di aver bisogno del database PostgreSQL per i test. Testare l'applicazione usando questo comando:
./mvnw clean test # On Mac or Linux
mvnw.cmd clean test # On Windows
Verrà visualizzato un output simile a questo:
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.example.demo.TodoResourceTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------