- การพัฒนา REST API ด้วย Quarkus: จากเริ่มต้นสู่ CRUD API
- Architecture
- เทคโนโลยีที่ใช้
- 1. ตรวจสอบ Java และ Maven
- 2. สร้าง Quarkus Project
- jdbc-postgresql PostgreSQL JDBC driver
- 3. สร้างฐานข้อมูล PostgreSQL
- 4. สร้าง Product Entity
- 5. สร้าง REST Resource
- 6. ทำความเข้าใจ Annotation
- 7. Endpoint ที่ได้
- 8. Run Quarkus แบบ Development Mode
- 9. ทดสอบ Create API
- 10. ทดสอบ Read API
- 11. ทดสอบ Update API
- 12. ทดสอบ Delete API
- 13. HTTP Status Code ที่ควรรู้
- 14. Architecture สำหรับระบบจริง
- 15. Active Record กับ Repository Pattern
- 16. สิ่งที่ควรเพิ่มก่อนนำไปใช้ Production
- 17. Quarkus กับ Microservices
- สรุป
- เอกสารอ้างอิง
#การพัฒนา REST API ด้วย Quarkus: จากเริ่มต้นสู่ CRUD API
Quarkus เป็น Java framework ที่ออกแบบมาสำหรับการพัฒนาแอปพลิเคชันแบบ Cloud Native, Microservices และ Container โดยเฉพาะ สามารถนำมาใช้สร้าง REST API ที่ทำงานร่วมกับ Jakarta REST, Hibernate ORM, PostgreSQL, Docker และ Kubernetes ได้
บทความนี้สาธิตการสร้าง REST API สำหรับจัดการข้อมูลสินค้า โดยใช้แนวคิด CRUD ได้แก่ Create, Read, Update และ Delete
#Architecture
Client / Postman / Frontend
|
| HTTP + JSON
v
+-------------------------+
| Quarkus REST |
| ProductResource |
+------------+------------+
|
v
+-------------------------+
| Hibernate ORM + Panache |
+------------+------------+
|
| JDBC
v
+-------------------------+
| PostgreSQL |
+-------------------------+
#เทคโนโลยีที่ใช้
- Java 17 หรือใหม่กว่า
- Quarkus
- Quarkus REST + Jackson
- Hibernate ORM with Panache
- PostgreSQL
- Maven
- cURL หรือ Postman
#1. ตรวจสอบ Java และ Maven
ตรวจสอบ Java:
java --version
ตรวจสอบ Maven:
mvn --version
สำหรับ Windows สามารถติดตั้ง Eclipse Temurin JDK 17 ผ่าน winget ได้:
winget install EclipseAdoptium.Temurin.17.JDK
หลังติดตั้งให้เปิด Terminal ใหม่แล้วตรวจสอบอีกครั้ง
java --version
#2. สร้าง Quarkus Project
หากติดตั้ง Quarkus CLI แล้ว สามารถสร้างโครงการด้วยคำสั่ง:
quarkus create app com.example:product-api \
--extension='rest-jackson,hibernate-orm-panache,jdbc-postgresql'
เข้าไปยัง project:
cd product-api
Extension สำคัญประกอบด้วย:
Extension หน้าที่
rest-jackson สร้าง REST endpoint และแปลง Java
Object ↔ JSON
hibernate-orm-panache ORM และช่วยลด boilerplate ใน
persistence layer
#jdbc-postgresql PostgreSQL JDBC driver
โครงสร้างที่เราจะใช้:
product-api/
├── pom.xml
└── src/
├── main/
│ ├── java/
│ │ └── com/example/
│ │ ├── entity/
│ │ │ └── Product.java
│ │ └── resource/
│ │ └── ProductResource.java
│ └── resources/
│ └── application.properties
└── test/
#3. สร้างฐานข้อมูล PostgreSQL
สร้างฐานข้อมูลชื่อ:
productdb
ตัวอย่างด้วย PostgreSQL CLI:
CREATE DATABASE productdb;
จากนั้นกำหนดค่าการเชื่อมต่อในไฟล์:
src/main/resources/application.properties
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=postgres
quarkus.datasource.password=postgres
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/productdb
quarkus.hibernate-orm.schema-management.strategy=update
ในระบบ Production ไม่ควรเก็บ username/password จริงไว้ใน source code ควรใช้ Environment Variables หรือ Secret Management
#4. สร้าง Product Entity
สร้างไฟล์:
src/main/java/com/example/entity/Product.java
package com.example.entity;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.Entity;
@Entity
public class Product extends PanacheEntity {
public String name;
public double price;
}
การสืบทอด PanacheEntity ทำให้ Entity มี id และ utility methods
สำหรับจัดการข้อมูล เช่น:
Product.listAll();
Product.findById(id);
product.persist();
product.delete();
จึงเหมาะสำหรับการเริ่มต้นเรียนรู้ Active Record Pattern ด้วย Quarkus
#5. สร้าง REST Resource
สร้างไฟล์:
src/main/java/com/example/resource/ProductResource.java
package com.example.resource;
import com.example.entity.Product;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.net.URI;
import java.util.List;
@Path("/api/products")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ProductResource {
@GET
public List<Product> getAll() {
return Product.listAll();
}
@GET
@Path("/{id}")
public Product getById(@PathParam("id") Long id) {
Product product = Product.findById(id);
if (product == null) {
throw new NotFoundException();
}
return product;
}
@POST
@Transactional
public Response create(Product product) {
product.persist();
return Response
.created(URI.create("/api/products/" + product.id))
.entity(product)
.build();
}
@PUT
@Path("/{id}")
@Transactional
public Product update(
@PathParam("id") Long id,
Product input) {
Product product = Product.findById(id);
if (product == null) {
throw new NotFoundException();
}
product.name = input.name;
product.price = input.price;
return product;
}
@DELETE
@Path("/{id}")
@Transactional
public Response delete(@PathParam("id") Long id) {
Product product = Product.findById(id);
if (product == null) {
throw new NotFoundException();
}
product.delete();
return Response.noContent().build();
}
}
#6. ทำความเข้าใจ Annotation
#@Path
กำหนด URL ของ Resource:
@Path("/api/products")
ดังนั้น endpoint หลักคือ:
http://localhost:8080/api/products
#@GET
ใช้สำหรับ HTTP GET:
@GET
public List<Product> getAll()
#@POST
ใช้เพิ่มข้อมูล:
@POST
@Transactional
public Response create(Product product)
#@PUT
ใช้แก้ไขข้อมูล:
@PUT
@Path("/{id}")
@Transactional
#@DELETE
ใช้ลบข้อมูล:
@DELETE
@Path("/{id}")
@Transactional
#@Transactional
Operation ที่มีการเปลี่ยนแปลงข้อมูลในฐานข้อมูลควรทำงานภายใน Transaction เช่น POST, PUT และ DELETE
#7. Endpoint ที่ได้
Method Endpoint รายละเอียด
GET /api/products แสดงสินค้าทั้งหมด
GET /api/products/{id} ค้นหาสินค้าตาม ID
POST /api/products เพิ่มสินค้า
PUT /api/products/{id} แก้ไขสินค้า
DELETE /api/products/{id} ลบสินค้า
#8. Run Quarkus แบบ Development Mode
macOS / Linux:
./mvnw quarkus:dev
Windows:
.\mvnw.cmd quarkus:dev
Quarkus จะเริ่มทำงานที่:
http://localhost:8080
จุดเด่นของ Development Mode คือรองรับ Live Coding ทำให้แก้ไข source code และทดสอบผลได้อย่างรวดเร็ว
#9. ทดสอบ Create API
ส่ง HTTP POST:
curl -X POST http://localhost:8080/api/products \
-H "Content-Type: application/json" \
-d '{
"name": "MacBook Pro",
"price": 69900
}'
ตัวอย่าง Response:
{
"id": 1,
"name": "MacBook Pro",
"price": 69900.0
}
#10. ทดสอบ Read API
อ่านสินค้าทั้งหมด:
curl http://localhost:8080/api/products
ตัวอย่าง:
[
{
"id": 1,
"name": "MacBook Pro",
"price": 69900.0
}
]
ค้นหาตาม ID:
curl http://localhost:8080/api/products/1
#11. ทดสอบ Update API
curl -X PUT http://localhost:8080/api/products/1 \
-H "Content-Type: application/json" \
-d '{
"name": "MacBook Pro M5",
"price": 74900
}'
#12. ทดสอบ Delete API
curl -X DELETE http://localhost:8080/api/products/1
หากสำเร็จ API จะตอบกลับด้วย HTTP Status:
204 No Content
#13. HTTP Status Code ที่ควรรู้
REST API ควรเลือก HTTP Status Code ให้สอดคล้องกับผลลัพธ์:
Status ความหมาย ตัวอย่าง
200 OK สำเร็จ GET, PUT
201 Created สร้าง resource สำเร็จ POST
204 No Content สำเร็จแต่ไม่มี response body DELETE
400 Bad Request Request ไม่ถูกต้อง Validation
404 Not Found ไม่พบ Resource ID ไม่มีในระบบ
500 Internal Server Error Server Error Exception ที่ไม่ได้จัดการ
#14. Architecture สำหรับระบบจริง
ตัวอย่างก่อนหน้านี้ใช้ Resource ติดต่อกับ Entity โดยตรง เหมาะกับการเรียนรู้และระบบขนาดเล็ก
สำหรับระบบขนาดกลางหรือใหญ่ แนะนำ:
HTTP Request
|
v
+------------+
| Resource | REST / HTTP
+-----+------+
|
v
+------------+
| Service | Business Logic
+-----+------+
|
v
+------------+
| Repository | Data Access / Panache
+-----+------+
|
v
+------------+
| PostgreSQL |
+------------+
โครงสร้าง package:
com.example
├── dto
│ ├── ProductRequest.java
│ └── ProductResponse.java
├── entity
│ └── Product.java
├── repository
│ └── ProductRepository.java
├── resource
│ └── ProductResource.java
├── service
│ └── ProductService.java
└── exception
└── ...
แนวทางนี้ช่วยแยกความรับผิดชอบของแต่ละ layer และทำให้ระบบทดสอบและบำรุงรักษาได้ง่ายขึ้น
#15. Active Record กับ Repository Pattern
Panache รองรับสองแนวทางหลัก
#Active Record
@Entity
public class Product extends PanacheEntity {
public String name;
}
ใช้งาน:
Product.listAll();
Product.findById(1L);
เหมาะกับระบบขนาดเล็กหรือการเรียนรู้
#Repository Pattern
@ApplicationScoped
public class ProductRepository
implements PanacheRepository<Product> {
}
จาก Service สามารถเรียก:
repository.listAll();
repository.findById(id);
repository.persist(product);
Repository Pattern เหมาะเมื่อระบบมี business logic และโครงสร้างหลาย layer มากขึ้น
#16. สิ่งที่ควรเพิ่มก่อนนำไปใช้ Production
CRUD API เป็นเพียงจุดเริ่มต้น ระบบจริงควรเพิ่มองค์ประกอบ เช่น:
- DTO แยก Request/Response ออกจาก Entity
- Bean Validation เช่น
@NotBlank,@Positive - Global Exception Handling
- Pagination / Filtering / Sorting
- OpenAPI และ Swagger UI
- Authentication / Authorization
- JWT หรือ OpenID Connect
- Unit Test และ Integration Test
- Database Migration ด้วย Flyway หรือ Liquibase
- Environment Variables / Secrets
- Health Check
- Logging และ Observability
- Docker
- CI/CD
- Kubernetes
ตัวอย่าง DTO ที่มี Validation:
public class ProductRequest {
@NotBlank
public String name;
@Positive
public double price;
}
จากนั้น endpoint สามารถใช้:
public Response create(@Valid ProductRequest request)
ช่วยป้องกันข้อมูลไม่ถูกต้องเข้าสู่ business layer
#17. Quarkus กับ Microservices
Quarkus ไม่ได้จำกัดอยู่แค่ CRUD API แต่สามารถใช้เป็น foundation ของ Microservices architecture เช่น:
API Gateway
|
+--------------+--------------+
| | |
v v v
+-------------+ +-------------+ +-------------+
| User Service| |Product | |Order Service|
| Quarkus | |Service | | Quarkus |
+-------------+ |Quarkus | +-------------+
+-------------+
| | |
+--------------+--------------+
|
Message Broker
สามารถต่อยอดร่วมกับ PostgreSQL, Kafka, Redis, OpenTelemetry, Prometheus, Docker และ Kubernetes ได้
#สรุป
การสร้าง REST API ด้วย Quarkus มีขั้นตอนหลักดังนี้:
Install Java
↓
Create Quarkus Project
↓
Add REST + Panache + PostgreSQL
↓
Create Entity
↓
Create REST Resource
↓
Configure Database
↓
Run quarkus:dev
↓
Test CRUD API
↓
Add Validation / DTO / Security / Tests
↓
Containerize & Deploy
Quarkus จึงเป็นอีกทางเลือกที่น่าสนใจสำหรับ Java Developer ที่ต้องการพัฒนา REST API, Microservices และ Cloud Native Application โดยยังคงใช้ ecosystem ของ Java/Jakarta และสามารถต่อยอดไปสู่ Container และ Kubernetes ได้โดยตรง
#เอกสารอ้างอิง
- Quarkus: https://quarkus.io/
- Getting Started: https://quarkus.io/guides/getting-started
- Writing REST JSON Services: https://quarkus.io/guides/rest-json
- Hibernate ORM with Panache: https://quarkus.io/guides/hibernate-orm-panache
- Datasources: https://quarkus.io/guides/datasource