Øvelse – opret et Quarkus-program

Fuldført

I dette undermodul skal du oprette et grundlæggende Quarkus-program. Du bruger Maven til at bootstrap programmet og et integreret udviklingsmiljø (IDE) efter eget valg for at redigere koden. Brug en terminal efter eget valg til at køre koden. Du kan bruge Docker til at starte en lokal PostgreSQL-database, så du kan køre og teste programmet lokalt.

Generér Quarkus-programmet ved hjælp af Maven

Der er flere måder at generere en Quarkus-projektstruktur på. Du kan bruge Quarkus-webgrænsefladen, en IDE-plug-in eller Quarkus Maven-plug-in'en. Lad os bruge Maven-plug-in'en til at generere projektstrukturen.

Du genererer dit program med flere afhængigheder:

  • Den resteasy afhængighed for at vise et REST-slutpunkt
  • Den jackson afhængighed for at serialisere og deserialisere JSON
  • Den hibernate afhængighed for at interagere med databasen
  • Den postgresql afhængighed, der skal oprettes forbindelse til PostgreSQL-databasen
  • Den docker afhængighed for at oprette et Docker-billede

Du behøver ikke at angive Azure-afhængigheder, fordi du først kører dit program lokalt og derefter udruller en objektbeholderversion af det i Azure Container Apps.

Opret to-do-programmet ved en kommandoprompt:

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"

Denne kommando opretter et nyt Quarkus-projekt. Den genererer en Maven-mappestruktur (src/main/java for kildekode og src/test/java til test). Det opretter nogle Java-klasser, nogle test og nogle Dockerfiles. Den genererer også en pom.xml fil med alle de nødvendige afhængigheder (Hibernate, RESTEasy, Jackson, PostgreSQL og 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>

Seddel

Alle afhængigheder i pom.xml-filen er defineret i Quarkus-styklisten (stykliste) io.quarkus.platform:quarkus-bom.

Kode programmet

Omdøb derefter den genererede MyEntity.java-klasse til Todo.java (placeret i samme mappe som TodoResource.java-filen). Erstat den eksisterende kode med følgende Java-kode. Den bruger Java Persistence API (jakarta.persistence.* pakke) til at gemme og hente data fra din PostgreSQL-server. Den bruger også dvale-ORM med Panache- (nedarvning fra io.quarkus.hibernate.orm.panache.PanacheEntity) til at forenkle persistenslaget.

Du kan bruge et JPA-objekt (@Entity) til at knytte Java Todo-objektet direkte til tabellen PostgreSQL Todo. Rest-slutpunktet TodoResource opretter derefter en ny Todo objektklasse og fortsætter. Denne klasse er en domænemodel, der er knyttet til tabellen Todo. Tabellen oprettes automatisk af JPA.

Hvis du forlænger PanacheEntity, får du en række generiske metoder til oprettelse, læsning, opdatering og sletning (CRUD) for din type. Så du kan f.eks. gemme og slette Todo objekter i blot én linje Java-kode.

Føj følgende kode til objektet 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 +
                '}';
    }
}

Hvis du vil administrere denne klasse, skal du opdatere TodoResource, så den kan publicere REST-grænseflader for at gemme og hente data ved hjælp af HTTP. Åbn klassen TodoResource, og erstat koden med følgende:

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

Kør programmet

Når du kører programmet i udviklingstilstand, skal Docker køre. Det skyldes, at Quarkus registrerer, at du har brug for en PostgreSQL-database (på grund af PostgreSQL-afhængigheden quarkus-jdbc-postgresql, der er erklæret i filen pom.xml), downloader PostgreSQL Docker-billedet og starter en objektbeholder med databasen. Derefter oprettes den Todo tabel automatisk i databasen.

Kontrollér, at Docker kører lokalt på computeren, og kør programmet to-do ved hjælp af denne kommando:

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

Quarkus-programmet skal starte og oprette forbindelse til databasen. Du bør kunne se følgende output:

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>

Hvis du vil teste programmet, kan du bruge cURL.

I en separat terminal skal du oprette et nyt to-do element i databasen med følgende kommando. Du bør kunne se loggen i Quarkus-konsollen:

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

Denne kommando skal returnere det oprettede element (med et id):

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

Opret endnu en to-do ved hjælp af følgende cURL-kommando:

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

Hent derefter dataene ved hjælp af en ny cURL-anmodning:

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

Denne kommando returnerer listen over to-do elementer, herunder de elementer, du har oprettet:

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

Test programmet

Hvis du vil teste programmet, kan du bruge den eksisterende TodoResourceTest klasse. Det skal teste REST-slutpunktet. Hvis du vil teste slutpunktet, bruges RESTAssured-. Erstat kode i klassen TodoResourceTest med følgende kode:

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

Når du tester programmet, skal Docker Desktop køre, fordi Quarkus registrerer, at det skal bruge PostgreSQL-databasen til test. Test programmet ved hjælp af denne kommando:

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

Du bør kunne se output, der ligner dette:

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