Ćwiczenie — tworzenie aplikacji Quarkus

Ukończone

W tej lekcji utworzysz podstawową aplikację Quarkus. Narzędzie Maven służy do uruchamiania aplikacji i wybranego zintegrowanego środowiska projektowego (IDE), aby edytować kod. Użyj wybranego terminalu, aby uruchomić kod. Użyj platformy Docker, aby uruchomić lokalną bazę danych PostgreSQL, aby można było uruchamiać i testować aplikację lokalnie.

Generowanie aplikacji Quarkus przy użyciu narzędzia Maven

Istnieje kilka sposobów generowania struktury projektu Quarkus. Możesz użyć interfejsu internetowego Quarkus, wtyczki IDE lub wtyczki Quarkus Maven. Użyjmy wtyczki Maven, aby wygenerować strukturę projektu.

Aplikacja jest generowana z kilkoma zależnościami:

  • Zależność resteasy uwidacznia punkt końcowy REST
  • Zależność jackson do serializacji i deserializacji danych JSON
  • Zależność hibernate do interakcji z bazą danych
  • Zależność postgresql do nawiązania połączenia z bazą danych PostgreSQL
  • Zależność docker do zbudowania obrazu Docker

Nie musisz określać zależności platformy Azure, ponieważ uruchamiasz aplikację lokalnie, a następnie wdrażasz konteneryzowaną wersję tej aplikacji w usłudze Azure Container Apps.

W wierszu polecenia wygeneruj aplikację to-do:

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"

To polecenie tworzy nowy projekt Quarkus. Generuje on strukturę katalogów Maven (src/main/java dla kodu źródłowego i src/test/java do testów). Tworzy ona niektóre klasy języka Java, niektóre testy i niektóre pliki Dockerfile. Generuje również plik pom.xml ze wszystkimi wymaganymi zależnościami (Hibernate, RESTEasy, Jackson, PostgreSQL i 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>

Notatka

Wszystkie zależności w pliku pom.xml są zdefiniowane w Quarkus BOM (bill of materials) io.quarkus.platform:quarkus-bom.

Kod aplikacji

Następnie zmień nazwę wygenerowanej klasy MyEntity.java na Todo.java (znajdującej się w tym samym folderze co plik TodoResource.java ). Zastąp istniejący kod następującym kodem Java. Używa on interfejsu API trwałości języka Java (pakietjakarta.persistence.*) do przechowywania i pobierania danych z serwera PostgreSQL. Używa również Hibernate ORM z Panache (dziedzicząc po io.quarkus.hibernate.orm.panache.PanacheEntity), aby uprościć warstwę persistence.

Do mapowania obiektu Java @Entity bezpośrednio do tabeli PostgreSQL Todo używa się encji JPA (Todo). Punkt końcowy REST TodoResource następnie tworzy nową klasę jednostek Todo i utrwala ją. Ta klasa jest modelem domeny mapowanym na tabelę Todo. Tabela jest tworzona automatycznie przez jpa.

Rozszerzanie PanacheEntity umożliwia szereg ogólnych metod tworzenia, odczytu, aktualizacji i usuwania (CRUD) dla danego typu. Możesz więc wykonywać takie czynności, jak zapisywanie i usuwanie obiektów Todo w jednym wierszu kodu Java.

Dodaj następujący kod do jednostki 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 +
                '}';
    }
}

Aby zarządzać tą klasą, zaktualizuj TodoResource, aby umożliwić publikowanie interfejsów REST w celu przechowywania i pobierania danych przy użyciu protokołu HTTP. Otwórz klasę TodoResource i zastąp kod następującym kodem:

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();
    }
}

Uruchamianie aplikacji

Po uruchomieniu aplikacji w trybie programowania platforma Docker musi być uruchomiona. Dzieje się tak, ponieważ aplikacja Quarkus wykrywa, że potrzebna jest baza danych PostgreSQL (ze względu na zależność quarkus-jdbc-postgresql PostgreSQL zadeklarowaną w pliku pom.xml ), pobiera obraz platformy Docker postgreSQL i uruchamia kontener z bazą danych. Następnie automatycznie tworzy tabelę Todo w bazie danych.

Upewnij się, że platforma Docker działa lokalnie na maszynie i uruchom aplikację to-do przy użyciu następującego polecenia:

cd todo
./mvnw quarkus:dev    # On Mac or Linux
mvnw.cmd quarkus:dev  # On Windows

Aplikacja Quarkus powinna uruchomić bazę danych i nawiązać z nią połączenie. Powinny zostać wyświetlone następujące dane wyjściowe:

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>

Aby przetestować aplikację, możesz użyć biblioteki cURL.

W osobnym terminalu utwórz nowy element to-do w bazie danych za pomocą następującego polecenia. Powinien zostać wyświetlony dziennik w konsoli 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

To polecenie powinno zwrócić utworzony element (z identyfikatorem):

{"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"}

Utwórz drugą to-do przy użyciu następującego polecenia cURL:

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

Następnie pobierz dane przy użyciu nowego żądania cURL:

curl http://127.0.0.1:8080/api/todos

To polecenie zwraca listę elementów to-do, w tym utworzonych elementów:

[ 
  {"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}
]

Testowanie aplikacji

Aby przetestować aplikację, możesz użyć istniejącej klasy TodoResourceTest. Musi przetestować punkt końcowy REST. Aby przetestować punkt końcowy, używa RESTAssured. Zastąp kod w klasie TodoResourceTest następującym kodem:

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);
    }
}

Podczas testowania aplikacji program Docker Desktop musi być uruchomiony, ponieważ aplikacja Quarkus wykrywa, że do testowania potrzebuje bazy danych PostgreSQL. Przetestuj aplikację przy użyciu tego polecenia:

./mvnw clean test    # On Mac or Linux
mvnw.cmd clean test  # On Windows

Powinny zostać wyświetlone dane wyjściowe podobne do następujących:

[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] ------------------------------------------------------------------------