Ć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. Kod zostanie uruchomiony za pomocą wybranego przez Ciebie terminalu. 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 deserializowania danych JSON
  • Zależność hibernate do interakcji z bazą danych
  • Zależność do nawiązywania postgresql połączenia z bazą danych PostgreSQL
  • Zależność docker do kompilowania obrazu platformy 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ę do wykonania:

mvn -U io.quarkus:quarkus-maven-plugin:3.7.3:create \
    -DplatformVersion=3.7.3 \
    -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 strukturę katalogów Maven (src/main/java dla kodu źródłowego i src/test/java 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>

Uwaga

Wszystkie zależności w pliku pom.xml są zdefiniowane w pliku Quarkus BOM (rachunek materiałów) io.quarkus.platform:quarkus-bom.

Kodowanie 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 (jakarta.persistence.* pakietu) do przechowywania i pobierania danych z serwera PostgreSQL. Używa również hibernacji ORM z Panache (dziedzicząc z io.quarkus.hibernate.orm.panache.PanacheEntity) w celu uproszczenia warstwy trwałości.

Jednostka JPA (@Entity) służy do mapowania obiektu Java Todo bezpośrednio do tabeli PostgreSQL Todo . Następnie TodoResource punkt końcowy REST tworzy nową Todo klasę jednostki i utrwala ją. Ta klasa jest modelem domeny mapowanym na tabelę Todo. Tabela jest tworzona automatycznie przez jpa.

PanacheEntity Rozszerzenie powoduje pobranie wielu ogólnych metod tworzenia, odczytu, aktualizacji i usuwania (CRUD) dla danego typu. Dzięki temu możesz wykonywać takie czynności, jak zapisywanie i usuwanie Todo obiektów w jednym wierszu kodu Java.

Dodaj następujący kod do Todo jednostki:

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 element 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, używając 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:

[io.qua.dat.dep.dev.DevServicesDatasourceProcessor] Dev Services for the default datasource (postgresql) started.
[io.qua.hib.orm.dep.HibernateOrmProcessor] Setting quarkus.hibernate-orm.database.generation=drop-and-create to initialize Dev Services managed database
__  ____  __  _____   ___  __ ____  ______ 
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \   
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/   
[org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) SQL Warning Code: 0, SQLState: 00000

[org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) table "todo" does not exist, skipping
[org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) SQL Warning Code: 0, SQLState: 00000
[org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) sequence "hibernate_sequence" does not exist, skipping
[io.quarkus] (Quarkus Main Thread) todo 1.0.0-SNAPSHOT on JVM (powered by Quarkus) started in 4.381s. Listening on: http://localhost:8080
[io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
[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 [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>

Do przetestowania aplikacji możesz użyć narzędzia cURL.

W osobnym terminalu utwórz nowy element do wykonania 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":"2022-12-30T15:17:20.280203Z"}

Utwórz drugą czynność do wykonania 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 do wykonania, 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 TodoResourceTest klasy. Musi przetestować punkt końcowy REST. Aby przetestować punkt końcowy, używa on interfejsu RESTAssured. Zastąp TodoResourceTest kod w klasie 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

Wyświetlone dane wyjściowe powinny wyglądać mniej więcej tak:

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