Cvičení – vytvoření aplikace Quarkus
V této lekci vytvoříte základní aplikaci Quarkus. Maven slouží ke spuštění aplikace a integrovaného vývojového prostředí (IDE) podle vašeho výběru k úpravě kódu. Ke spuštění kódu použijte prostředí Bash nakonfigurované v předpokladech. Pomocí Dockeru spustíte místní databázi PostgreSQL, abyste mohli aplikaci spustit a otestovat místně.
Generování aplikace Quarkus pomocí Mavenu
Existuje několik způsobů, jak vygenerovat strukturu projektu Quarkus. Můžete použít webové rozhraní Quarkus, modul plug-in IDE nebo modul plug-in Quarkus Maven. K vygenerování struktury projektu použijeme modul plug-in Maven.
Vygenerujete aplikaci s několika závislostmi:
- Závislost
resteasypro zpřístupnění REST endpointu - Závislost
jacksonpro serializaci a deserializaci JSON. - Závislost
hibernatepro interakci s databází - Závislost
postgresqlpro připojení k databázi PostgreSQL - Závislost
quarkus-container-image-dockerpro sestavení Docker image
Závislosti Azure nemusíte zadávat, protože aplikaci spouštíte místně a pak nasadíte kontejnerizovanou verzi do Azure Container Apps.
Poznámka
Příkazy v tomto modulu používají syntaxi Bash. Nevkládejte je beze změny do PowerShellu ani do příkazového řádku systému Windows. Na Windows spusťte příkazy Bash v nakonfigurované distribuci WSL. V době, kdy je aplikace spuštěná, použijte jiný místní terminál Bash pro požadavky HTTP.
Před generováním projektu zkontrolujte, jestli vaše prostředí Bash používá Java 17 a Maven 3.9.9:
java -version
mvn --version
Příkaz počátečního generátoru používá nainstalovaný Maven. Maven wrapper projektu se vytvoří poté, takže tento předpoklad nenahradí. Než budete pokračovat, vyberte požadované verze Java a Maven.
V adresáři, ve kterém chcete projekt vytvořit, vygenerujte to-do aplikaci:
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, io.quarkus:quarkus-container-image-docker"
Tento příkaz vytvoří nový projekt Quarkus v adresáři s názvem todo. Generuje adresářovou strukturu Maven (src/main/java pro zdrojový kód a src/test/java pro testy). Vytvoří některé třídy Java, některé testy a některé soubory Dockerfile. Vygeneruje také souborpom.xml se všemi potřebnými závislostmi (Hibernate, RESTEasy, Jackson, PostgreSQL a 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>
Poznámka
Všechny závislosti v souboru pom.xml jsou definovány v Quarkus BOM (kusovník) io.quarkus.platform:quarkus-bom.
Kódování aplikace
Potom přejmenujte vygenerovanou třídu MyEntity.java na Todo.java (nachází se ve stejné složce jako soubor TodoResource.java ). Nahraďte stávající kód následujícím kódem Java. K ukládání a načítání dat ze serveru PostgreSQL používá rozhraní Java Persistence API (balíčekjakarta.persistence.*). Používá také Hibernate ORM s Panache (zděděné z io.quarkus.hibernate.orm.panache.PanacheEntity) ke zjednodušení přetrvávací vrstvy.
Pomocí entity JPA (@Entity) namapujete objekt java Todo přímo na tabulku Todo PostgreSQL. Koncový bod REST TodoResource pak vytvoří novou třídu entity Todo a zachová ji. Tato třída je doménový model mapovaný v tabulce Todo. Tabulka je automaticky vytvořena JPA.
Rozšířením PanacheEntity získáte řadu obecných metod vytvoření, čtení, aktualizace a odstranění (CRUD) pro váš typ. Můžete tak dělat věci, jako je ukládání a odstraňování objektů Todo jenom na jednom řádku kódu Java.
Do entity Todo přidejte následující kód:
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 +
'}';
}
}
Pokud chcete tuto třídu spravovat, aktualizujte TodoResource, aby bylo možné publikovat rozhraní REST pro ukládání a načítání dat pomocí protokolu HTTP. Otevřete třídu TodoResource a nahraďte kód následujícím kódem:
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.NotFoundException;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
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();
}
@GET
@Path("/{id}")
public Todo getTodo(@PathParam("id") Long id) {
Todo todo = id == null ? null : Todo.findById(id);
if (todo == null) {
throw new NotFoundException();
}
return todo;
}
}
Metoda POST vrátí URI nové položky v hlavičce Location. Metoda GET položky obsluhuje tento identifikátor URI a vrací HTTP 404, pokud položka není nalezena. Ochrana null také zpracovává hodnoty cesty, které RESTEasy převede na identifikátor null bez předání hodnoty null Panache.
Spuštění aplikace
Když aplikaci spustíte ve vývojovém režimu, musí být Docker spuštěný. Je to proto, že Quarkus zjistí, že potřebujete databázi PostgreSQL (kvůli závislosti quarkus-jdbc-postgresql PostgreSQL deklarované v souboru pom.xml ), stáhne image Dockeru PostgreSQL a spustí kontejner s databází. Potom automaticky vytvoří tabulku Todo v databázi.
Poznámka
Připnutá platforma Quarkus 3.18.4 používá Testcontainers 1.20.4, jejichž Java klient Dockeru ve výchozím nastavení používá rozhraní API 1.32.
Docker Engine 29.x už ve výchozím nastavení nepřijímá verzi rozhraní API. Pokud používáte Engine 29.x, spusťte docker version a ověřte, že podporovaný rozsah rozhraní API serveru zahrnuje verzi 1.44. Pouze pokud k tomu dojde, spusťte v tomto prostředí Bash následující příkaz před spuštěním Quarkus nebo testů:
export JDK_JAVA_OPTIONS="${JDK_JAVA_OPTIONS:+$JDK_JAVA_OPTIONS }-Dapi.version=1.44"
Toto nastavení ponechte ve stejném shellu pro příkazy testování a pozdějšího zabalení.
JDK_JAVA_OPTIONS předává systémovou vlastnost Java procesům spouštěče Java beze změny připnutých verzí Quarkus. Nastavení DOCKER_API_VERSION samotné nenakonfiguruje tuto verzi klienta Java Dockeru. Nevynucujte rozhraní API 1.44 na server, jehož podporovaný rozsah ho vylučuje; místo toho použijte samostatně validovanou kompatibilní konfiguraci Dockeru a klienta.
Ujistěte se, že je Docker spuštěný a přístupný z nakonfigurovaného prostředí Bash. V terminálu, kde jste projekt vygenerovali, přejděte do adresáře todo a spusťte aplikaci:
cd todo
./mvnw quarkus:dev
Spusťte všechny následující příkazy Mavenu z tohoto vygenerovaného todo adresáře.
Aplikace Quarkus by se měla spustit a připojit se k vaší databázi. Měl by se zobrazit následující výstup:
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>
K otestování aplikace můžete použít cURL.
V druhém místním terminálu Bash vytvořte v databázi novou položku to-do pomocí následujícího příkazu. V konzole Quarkus by se měl zobrazit protokol:
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
Tento příkaz by měl vrátit vytvořenou položku (s identifikátorem):
{"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"}
Pomocí následujícího příkazu cURL vytvořte druhý to-do:
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
Potom načtěte data pomocí nového požadavku cURL:
curl http://127.0.0.1:8080/api/todos
Tento příkaz vrátí seznam to-do položek, včetně položek, které jste vytvořili. Každá položka také obsahuje createdAt; následující příklad vynechá tato časová razítka pro stručnost:
[
{"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}
]
Otestování aplikace
Po kontrole PROTOKOLU HTTP se vraťte do terminálu, na kterém běží Quarkus, a stisknutím kláves Ctrl+C zastavte režim vývoje. Nechte toto prostředí Bash otevřené a zůstaňte v todo adresáři pro testovací příkaz.
K otestování aplikace můžete použít existující třídu TodoResourceTest. Musí otestovat koncový bod REST. K otestování koncového bodu se používá restAssured. Testy uchovávají kontrolu kolekce, sledují odkaz vrácený požadavkem Location POST a kontrolují chybějící a neplatné identifikátory položek. Nahraďte kód ve třídě TodoResourceTest následujícím kódem:
package com.example.demo;
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.response.Response;
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 static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
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;
Response created = given().body(todo)
.header(CONTENT_TYPE, APPLICATION_JSON)
.when().post("/api/todos")
.then()
.statusCode(201)
.extract().response();
String location = created.getHeader("Location");
assertNotNull(location);
long createdId = created.jsonPath().getLong("id");
Response retrieved = given()
.when().get(location)
.then()
.statusCode(200)
.extract().response();
assertEquals(createdId, retrieved.jsonPath().getLong("id"));
assertEquals(todo.description, retrieved.jsonPath().getString("description"));
}
@Test
void shouldReturnNotFoundForMissingTodo() {
given()
.when().get("/api/todos/-1")
.then().statusCode(404);
}
@Test
void shouldRejectInvalidTodoIds() {
given()
.when().get("/api/todos/not-a-number")
.then().statusCode(404);
given().urlEncodingEnabled(false)
.when().get("/api/todos/%20")
.then().statusCode(404);
}
}
Test vytvoření přečte vygenerovaný identifikátor z odpovědi POST a porovná oba identifikátory jako hodnoty long. Test neplatného identifikátoru zakáže automatické kódování adresy URL pro %20, aby požadavek obsahoval záměrně zakódovanou mezeru.
Při testování aplikace musí Být Docker spuštěný a přístupný ze stejného prostředí Bash, protože Quarkus spustí pro testování samostatnou službu PostgreSQL Dev Service. V terminálu, kde jste zastavili Quarkus, otestujte aplikaci pomocí tohoto příkazu:
./mvnw clean test
Měl by se zobrazit výstup podobný tomuto:
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.example.demo.TodoResourceTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 4, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
Nechte tento shell Bash otevřený pro cvičení s databází. Nastavíte AZ_POSTGRES_JDBC_URL, AZ_POSTGRES_USERNAME a AZ_POSTGRES_PASSWORD, pak restartujte Quarkus v tomto shellu. Před následnými kroky a kroky nasazení zastavte proces vzdáleného vývoje pomocí ./mvnw clean package+. Zachovejte proměnné a neopakujte nastavení názvu prostředku a hesla mezi moduly.
Proces dědí své prostředí při spuštění. Exportování proměnných v jiném terminálu neaktualizuje již spuštěný proces Quarkus. Úpravy application.properties a spoléhání se na opětovné načítání za provozu nestačí pro přepnutí na Azure; restartujte aplikaci z prostředí, ve kterém jste nastavili proměnné.