تمرين - إنشاء تطبيق Quarkus

مكتمل

في هذه الوحدة، يمكنك إنشاء تطبيق Quarkus أساسي. يمكنك استخدام Maven لتمهيد تشغيل التطبيق وبيئة تطوير متكاملة (IDE) من اختيارك لتحرير التعليمات البرمجية. استخدم محطة طرفية من اختيارك لتشغيل التعليمات البرمجية. يمكنك استخدام Docker لبدء قاعدة بيانات PostgreSQL محلية حتى تتمكن من تشغيل التطبيق واختباره محليا.

إنشاء تطبيق Quarkus باستخدام Maven

هناك عدة طرق لإنشاء بنية مشروع Quarkus. يمكنك استخدام واجهة الويب Quarkusأو مكون IDE الإضافي أو المكون الإضافي Quarkus Maven. دعونا نستخدم المكون الإضافي Maven لإنشاء بنية المشروع.

يمكنك إنشاء التطبيق الخاص بك مع العديد من التبعيات:

  • resteasy التبعية لعرض نقطة نهاية REST
  • تبعية jackson لتسلسل وإلغاء تسلسل JSON
  • تبعية hibernate للتفاعل مع قاعدة البيانات
  • تبعية postgresql للاتصال بقاعدة بيانات PostgreSQL
  • docker التبعية لإنشاء صورة Docker

لا تحتاج إلى تحديد تبعيات Azure لأنك تقوم بتشغيل التطبيق محليا أولا ثم نشر إصدار حاوية منه إلى Azure Container Apps.

في موجه الأوامر، قم بإنشاء تطبيق 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"

ينشئ هذا الأمر مشروع Quarkus جديدا. يقوم بإنشاء بنية دليل Maven (src/main/java للتعليمات البرمجية المصدر src/test/java للاختبارات). يقوم بإنشاء بعض فئات Java وبعض الاختبارات وبعض ملفات Dockerfiles. كما أنه ينشئ ملف pom.xml مع جميع التبعيات المطلوبة (الإسبات وRESTEasy وPostgreSQL و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>

ملاحظه

يتم تعريف جميع التبعيات في ملف pom.xml في Quarkus BOM (فاتورة المواد) io.quarkus.platform:quarkus-bom.

ترميز التطبيق

بعد ذلك، أعد تسمية فئة MyEntity.java التي تم إنشاؤها إلى Todo.java (الموجودة في نفس المجلد كملف TodoResource.java). استبدل التعليمات البرمجية الموجودة بالتعليمة البرمجية Java التالية. يستخدم Java Persistence API (حزمةjakarta.persistence.*) لتخزين البيانات واستردادها من خادم PostgreSQL. كما يستخدم ORM الإسبات مع Panache (الوراثة من io.quarkus.hibernate.orm.panache.PanacheEntity) لتبسيط طبقة الاستمرار.

يمكنك استخدام كيان JPA (@Entity) لتعيين كائن java Todo مباشرة إلى جدول Todo PostgreSQL. ثم تنشئ نقطة نهاية REST TodoResource فئة كيان Todo جديدة وتستمر فيها. هذه الفئة هي نموذج مجال تم تعيينه على جدول Todo. يتم إنشاء الجدول تلقائيا بواسطة JPA.

يؤدي توسيع PanacheEntity إلى الحصول على عدد من أساليب الإنشاء والقراءة والتحديث والحذف (CRUD) العامة لنوعك. لذلك يمكنك القيام بأشياء مثل حفظ وحذف كائنات Todo في سطر واحد فقط من التعليمات البرمجية ل Java.

أضف التعليمات البرمجية التالية إلى كيان 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 +
                '}';
    }
}

لإدارة هذه الفئة، قم بتحديث TodoResource حتى تتمكن من نشر واجهات REST لتخزين البيانات واستردادها باستخدام HTTP. افتح فئة TodoResource واستبدل التعليمات البرمجية بالآتي:

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

تشغيل التطبيق

عند تشغيل التطبيق في وضع التطوير، يجب تشغيل Docker. وذلك لأن Quarkus يكتشف أنك بحاجة إلى قاعدة بيانات PostgreSQL (بسبب quarkus-jdbc-postgresql إعلان تبعية PostgreSQL في ملف pom.xml)، وتنزيل صورة PostgreSQL Docker، وبدء حاوية مع قاعدة البيانات. ثم يقوم تلقائيا بإنشاء جدول Todo في قاعدة البيانات.

تأكد من تشغيل Docker محليا على جهازك وتشغيل تطبيق to-do باستخدام هذا الأمر:

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

يجب أن يبدأ تطبيق Quarkus ويتصل بقاعدة البيانات الخاصة بك. يجب أن تشاهد الإخراج التالي:

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>

لاختبار التطبيق، يمكنك استخدام cURL.

في محطة طرفية منفصلة، قم بإنشاء عنصر to-do جديد في قاعدة البيانات باستخدام الأمر التالي. يجب أن تشاهد السجل في وحدة تحكم 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

يجب أن يرجع هذا الأمر العنصر الذي تم إنشاؤه (مع معرف):

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

إنشاء to-do ثان باستخدام الأمر 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

بعد ذلك، قم باسترداد البيانات باستخدام طلب cURL جديد:

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

يقوم هذا الأمر بإرجاع قائمة عناصر to-do، بما في ذلك العناصر التي قمت بإنشائها:

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

اختبار التطبيق

لاختبار التطبيق، يمكنك استخدام فئة TodoResourceTest الموجودة. يحتاج إلى اختبار نقطة نهاية REST. لاختبار نقطة النهاية، فإنه يستخدم RESTAssured. استبدل التعليمات البرمجية في فئة TodoResourceTest بالتعليمات البرمجية التالية:

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

عند اختبار التطبيق، يجب تشغيل Docker Desktop لأن Quarkus يكتشف أنه يحتاج إلى قاعدة بيانات PostgreSQL للاختبار. اختبر التطبيق باستخدام هذا الأمر:

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

يجب أن تشاهد الإخراج الذي يبدو مشابها لهذا:

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