- การพัฒนา REST API ด้วย Micronaut
- 1. สิ่งที่จะสร้าง
- 2. Architecture
- 3. เตรียมเครื่องมือ
- 4. สร้าง Project
- 5. โครงสร้าง Project
- 6. ตั้งค่า Database
- 7. สร้าง Database Migration
- 8. สร้าง Product Entity
- 9. สร้าง Request DTO และ Validation
- 10. สร้าง Repository
- 11. สร้าง REST Controller
- 12. HTTP Method และ Status Code
- 13. รัน Application
- 14. ทดสอบ API ด้วย curl
- 15. ทดลอง Validation
- 16. เพิ่ม OpenAPI และ Swagger UI
- 17. เขียน Integration Test
- 18. เพิ่ม Custom Query
- 19. เปลี่ยนจาก H2 เป็น PostgreSQL
- 20. Environment Variable
- 21. Error Handling
- 22. Security
- 23. Production Architecture
- 24. Dockerfile ตัวอย่าง
- 25. แนวทางจัด Layer สำหรับ Project ขนาดใหญ่
- 26. Best Practices
- 27. Micronaut กับ Spring Boot ต่างกันอย่างไรในมุม REST API
- 28. Roadmap การเรียนรู้ Micronaut REST API
- 29. สรุป
- References
#การพัฒนา REST API ด้วย Micronaut
Micronaut เป็น JVM framework สำหรับพัฒนา Web Application, REST API และ Microservices โดยออกแบบให้ทำงานจำนวนมากในช่วง compile time แทนการพึ่ง reflection ใน runtime มากเกินไป จึงเหมาะกับระบบที่ให้ความสำคัญกับ startup time, memory footprint, cloud-native deployment และ GraalVM Native Image
บทความนี้สาธิตการสร้าง Product REST API ด้วย Java โดยครอบคลุม CRUD, Validation, Micronaut Data JDBC, H2 Database, Flyway และ OpenAPI/Swagger UI
เนื้อหาอ้างอิง Micronaut Framework 5.x โดย ณ วันที่ 21 กันยายน 2026 มี Micronaut Framework 5.1.5 เป็นรุ่นล่าสุดที่ประกาศบนเว็บไซต์ Micronaut และคู่มือ Micronaut 5 ใช้ JDK 21 ขึ้นไป
#1. สิ่งที่จะสร้าง
API ตัวอย่างมี endpoint ดังนี้
| Method | Endpoint | หน้าที่ |
|---|---|---|
GET |
/api/products |
แสดงสินค้าทั้งหมด |
GET |
/api/products/{id} |
ค้นหาสินค้าตาม ID |
POST |
/api/products |
เพิ่มสินค้า |
PUT |
/api/products/{id} |
แก้ไขสินค้า |
DELETE |
/api/products/{id} |
ลบสินค้า |
ตัวอย่าง JSON
{
"name": "Mechanical Keyboard",
"price": 2590.00
}
#2. Architecture
flowchart LR
Client["Client / Postman / Frontend"]
Controller["ProductController"]
Validation["Bean Validation"]
Repository["ProductRepository"]
DB[("H2 / PostgreSQL / MySQL")]
Client -->|"HTTP + JSON"| Controller
Controller --> Validation
Controller --> Repository
Repository --> DB
DB --> Repository
Repository --> Controller
Controller -->|"HTTP Response + JSON"| Client
โครงสร้างหลักแบ่งเป็น
- Controller รับ HTTP Request และสร้าง HTTP Response
- DTO รับและตรวจสอบข้อมูลจาก client
- Entity แทนข้อมูลที่จัดเก็บในฐานข้อมูล
- Repository ทำ CRUD ผ่าน Micronaut Data
- Database ตัวอย่างนี้ใช้ H2 เพื่อทดลองได้ง่าย
- Flyway จัดการ schema migration
- OpenAPI / Swagger UI สร้างเอกสาร API
#3. เตรียมเครื่องมือ
ควรมีเครื่องมือดังนี้
JDK 21+
Micronaut CLI
Git
IDE เช่น IntelliJ IDEA หรือ VS Code
curl หรือ Postman
ตรวจสอบ Java
java -version
ตรวจสอบ Micronaut CLI
mn --version
#4. สร้าง Project
สร้างโปรเจกต์ด้วย Maven
mn create-app example.micronaut.productapi \
--features=data-jdbc,jdbc-hikari,h2,serialization-jackson,validation,flyway,openapi,swagger-ui \
--build=maven \
--lang=java \
--test=junit
เข้า directory ของ project
cd productapi
Feature สำคัญที่ใช้คือ
| Feature | หน้าที่ |
|---|---|
data-jdbc |
ใช้ Micronaut Data JDBC |
jdbc-hikari |
Connection Pool ด้วย HikariCP |
h2 |
In-memory database สำหรับทดลอง |
serialization-jackson |
แปลง Java Object ↔ JSON |
validation |
Bean Validation |
flyway |
Database migration |
openapi |
สร้าง OpenAPI specification |
swagger-ui |
สร้าง Swagger UI |
สำหรับ production สามารถเปลี่ยน H2 เป็น PostgreSQL หรือ MySQL ได้
#5. โครงสร้าง Project
ตัวอย่างโครงสร้างที่เราจะใช้
productapi/
├── openapi.properties
├── pom.xml
└── src/
├── main/
│ ├── java/
│ │ └── example/micronaut/productapi/
│ │ ├── Application.java
│ │ ├── Product.java
│ │ ├── ProductController.java
│ │ ├── ProductRepository.java
│ │ └── ProductRequest.java
│ └── resources/
│ ├── application.properties
│ └── db/migration/
│ └── V1__create_products.sql
└── test/
└── java/
└── example/micronaut/productapi/
└── ProductControllerTest.java
#6. ตั้งค่า Database
ไฟล์
src/main/resources/application.properties
เพิ่ม configuration
micronaut.application.name=product-api
datasources.default.url=jdbc:h2:mem:productdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
datasources.default.username=sa
datasources.default.password=
datasources.default.driver-class-name=org.h2.Driver
datasources.default.dialect=H2
flyway.datasources.default.enabled=true
micronaut.router.static-resources.swagger-ui.paths=classpath:META-INF/swagger/views/swagger-ui
micronaut.router.static-resources.swagger-ui.mapping=/swagger-ui/**
สำหรับ tutorial นี้ H2 จะทำงานแบบ in-memory ทำให้ไม่ต้องติดตั้ง Database Server เพิ่ม
#7. สร้าง Database Migration
สร้างไฟล์
src/main/resources/db/migration/V1__create_products.sql
CREATE TABLE products (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
name VARCHAR(255) NOT NULL,
price DECIMAL(12, 2) NOT NULL
);
Flyway จะรัน migration เมื่อ application เริ่มทำงาน
ข้อดีคือ schema ถูกจัดการเป็น version และสามารถเก็บไว้ใน Git ได้
#8. สร้าง Product Entity
สร้างไฟล์
src/main/java/example/micronaut/productapi/Product.java
package example.micronaut.productapi;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.data.annotation.GeneratedValue;
import io.micronaut.data.annotation.Id;
import io.micronaut.data.annotation.MappedEntity;
import io.micronaut.serde.annotation.Serdeable;
import java.math.BigDecimal;
@Serdeable
@MappedEntity("products")
public class Product {
@Id
@GeneratedValue
@Nullable
private Long id;
private String name;
private BigDecimal price;
public Product() {
}
public Product(@Nullable Long id, String name, BigDecimal price) {
this.id = id;
this.name = name;
this.price = price;
}
@Nullable
public Long getId() {
return id;
}
public void setId(@Nullable Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
}
Annotation สำคัญ
@MappedEntityระบุว่า class นี้เป็น persistent entity@Idระบุ primary key@GeneratedValueให้ database สร้าง ID@Serdeableเปิดให้ Micronaut Serialization แปลง object เป็น/จาก JSON
#9. สร้าง Request DTO และ Validation
ไม่ควรผูก request body เข้ากับ Entity โดยตรงในระบบจริง เพราะ API contract และ database model มีเหตุผลในการเปลี่ยนแปลงต่างกัน
สร้างไฟล์
src/main/java/example/micronaut/productapi/ProductRequest.java
package example.micronaut.productapi;
import io.micronaut.serde.annotation.Serdeable;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import java.math.BigDecimal;
@Serdeable
public record ProductRequest(
@NotBlank String name,
@NotNull @Positive BigDecimal price
) {
}
Validation ที่กำหนดคือ
nameต้องไม่เป็นค่าว่างpriceต้องไม่เป็นnullpriceต้องมากกว่า 0
#10. สร้าง Repository
สร้างไฟล์
src/main/java/example/micronaut/productapi/ProductRepository.java
package example.micronaut.productapi;
import io.micronaut.data.jdbc.annotation.JdbcRepository;
import io.micronaut.data.model.query.builder.sql.Dialect;
import io.micronaut.data.repository.CrudRepository;
@JdbcRepository(dialect = Dialect.H2)
public interface ProductRepository extends CrudRepository<Product, Long> {
}
การ extends CrudRepository<Product, Long> ทำให้เราได้ method พื้นฐาน เช่น
findAll()
findById(id)
save(entity)
update(entity)
deleteById(id)
existsById(id)
count()
Micronaut Data สร้าง implementation และ query ที่ต้องใช้ในช่วง compile time
#11. สร้าง REST Controller
สร้างไฟล์
src/main/java/example/micronaut/productapi/ProductController.java
package example.micronaut.productapi;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Delete;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Post;
import io.micronaut.http.annotation.Put;
import io.micronaut.scheduling.TaskExecutors;
import io.micronaut.scheduling.annotation.ExecuteOn;
import io.micronaut.validation.Validated;
import jakarta.validation.Valid;
@Validated
@ExecuteOn(TaskExecutors.BLOCKING)
@Controller("/api/products")
public class ProductController {
private final ProductRepository repository;
public ProductController(ProductRepository repository) {
this.repository = repository;
}
@Get
public Iterable<Product> list() {
return repository.findAll();
}
@Get("/{id}")
public HttpResponse<Product> findById(Long id) {
return repository.findById(id)
.map(HttpResponse::ok)
.orElseGet(HttpResponse::notFound);
}
@Post
public HttpResponse<Product> create(@Body @Valid ProductRequest request) {
Product product = new Product(
null,
request.name(),
request.price()
);
Product saved = repository.save(product);
return HttpResponse.created(saved);
}
@Put("/{id}")
public HttpResponse<Product> update(
Long id,
@Body @Valid ProductRequest request
) {
return repository.findById(id)
.map(product -> {
product.setName(request.name());
product.setPrice(request.price());
Product updated = repository.update(product);
return HttpResponse.ok(updated);
})
.orElseGet(HttpResponse::notFound);
}
@Delete("/{id}")
public HttpResponse<?> delete(Long id) {
if (!repository.existsById(id)) {
return HttpResponse.notFound();
}
repository.deleteById(id);
return HttpResponse.noContent();
}
}
#ทำไมใช้ @ExecuteOn(TaskExecutors.BLOCKING)
Micronaut Data JDBC เป็น blocking I/O ดังนั้นการแยกงาน database ออกจาก event-loop thread ช่วยป้องกันการ block thread ที่ใช้รับ HTTP request
ถ้าต้องการ reactive database access สามารถพิจารณา Micronaut Data R2DBC แทน JDBC
#12. HTTP Method และ Status Code
API ที่ดีควรใช้ HTTP semantics ให้ชัดเจน
| Operation | Method | Success |
|---|---|---|
| List | GET |
200 OK |
| Find by ID | GET |
200 OK |
| Create | POST |
201 Created |
| Update | PUT |
200 OK |
| Delete | DELETE |
204 No Content |
| Resource ไม่พบ | - | 404 Not Found |
| Validation ไม่ผ่าน | - | 400 Bad Request |
#13. รัน Application
ด้วย Maven Wrapper
./mvnw mn:run
Windows
mvnw.cmd mn:run
โดยทั่วไป application จะเปิดที่
http://localhost:8080
#14. ทดสอบ API ด้วย curl
#14.1 Create Product
curl -i \
-X POST http://localhost:8080/api/products \
-H "Content-Type: application/json" \
-d '{
"name": "Mechanical Keyboard",
"price": 2590.00
}'
ผลลัพธ์ตัวอย่าง
{
"id": 1,
"name": "Mechanical Keyboard",
"price": 2590.00
}
#14.2 List Products
curl http://localhost:8080/api/products
#14.3 Get Product by ID
curl http://localhost:8080/api/products/1
#14.4 Update Product
curl -i \
-X PUT http://localhost:8080/api/products/1 \
-H "Content-Type: application/json" \
-d '{
"name": "Mechanical Keyboard Pro",
"price": 3290.00
}'
#14.5 Delete Product
curl -i \
-X DELETE http://localhost:8080/api/products/1
#15. ทดลอง Validation
ส่งข้อมูลไม่ถูกต้อง
curl -i \
-X POST http://localhost:8080/api/products \
-H "Content-Type: application/json" \
-d '{
"name": "",
"price": -100
}'
เพราะ name ถูกกำหนดด้วย @NotBlank และ price ด้วย @Positive request จะไม่ผ่าน validation
แนวทางนี้ช่วยให้ validation rule อยู่ใกล้กับ API contract และลด business logic ที่ซ้ำใน controller
#16. เพิ่ม OpenAPI และ Swagger UI
สร้างไฟล์ที่ root ของ project
openapi.properties
ใส่ค่า
swagger-ui.enabled=true
จากนั้น compile หรือ run application ใหม่
./mvnw clean compile
./mvnw mn:run
เปิด
http://localhost:8080/swagger-ui/index.html
Swagger UI ช่วยให้ทีมพัฒนาและผู้ใช้ API
- ดู endpoint
- ดู request/response schema
- ทดลองส่ง HTTP request
- ใช้ OpenAPI specification เป็น API contract
- นำ specification ไป generate client SDK หรือ documentation ต่อได้
#17. เขียน Integration Test
Micronaut มี @MicronautTest สำหรับเริ่ม Application Context และ embedded server ระหว่าง test
ตัวอย่าง
package example.micronaut.productapi;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.client.HttpClient;
import io.micronaut.http.client.annotation.Client;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import jakarta.inject.Inject;
import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
import static org.junit.jupiter.api.Assertions.assertEquals;
@MicronautTest
class ProductControllerTest {
@Inject
@Client("/")
HttpClient client;
@Test
void canCreateProduct() {
ProductRequest request =
new ProductRequest(
"Mechanical Keyboard",
new BigDecimal("2590.00")
);
var response = client.toBlocking().exchange(
HttpRequest.POST("/api/products", request),
Product.class
);
assertEquals(HttpStatus.CREATED, response.status());
}
}
รัน test
./mvnw test
#18. เพิ่ม Custom Query
Micronaut Data สามารถสร้าง query จากชื่อ method ได้
ตัวอย่างค้นหาสินค้าจากชื่อ
package example.micronaut.productapi;
import io.micronaut.data.jdbc.annotation.JdbcRepository;
import io.micronaut.data.model.query.builder.sql.Dialect;
import io.micronaut.data.repository.CrudRepository;
import java.util.List;
@JdbcRepository(dialect = Dialect.H2)
public interface ProductRepository
extends CrudRepository<Product, Long> {
List<Product> findByNameContains(String name);
}
เพิ่ม endpoint
@Get("/search{?q}")
public Iterable<Product> search(String q) {
return repository.findByNameContains(q);
}
เรียก
GET /api/products/search?q=Keyboard
จุดเด่นคือเราไม่ต้องเขียน SQL สำหรับ query พื้นฐานทุกครั้ง
#19. เปลี่ยนจาก H2 เป็น PostgreSQL
H2 เหมาะกับการเรียนรู้และ prototype แต่ production มักใช้ฐานข้อมูลจริง เช่น PostgreSQL
แนวคิดการเปลี่ยนคือ
- เปลี่ยน dependency จาก
h2เป็น PostgreSQL driver - เปลี่ยน datasource URL
- เปลี่ยน dialect เป็น
POSTGRES - เปลี่ยน
@JdbcRepository(dialect = Dialect.H2)เป็นDialect.POSTGRES - ให้ Flyway migration รองรับ SQL ของ PostgreSQL
- เก็บ credential ใน environment variable หรือ secret manager
ตัวอย่าง configuration
datasources.default.url=${JDBC_URL:`jdbc:postgresql://localhost:5432/productdb`}
datasources.default.username=${DB_USERNAME:postgres}
datasources.default.password=${DB_PASSWORD:postgres}
datasources.default.driver-class-name=org.postgresql.Driver
datasources.default.dialect=POSTGRES
repository
@JdbcRepository(dialect = Dialect.POSTGRES)
public interface ProductRepository
extends CrudRepository<Product, Long> {
}
#20. Environment Variable
อย่า hard-code password ใน source code
ตัวอย่าง
datasources.default.url=${JDBC_URL}
datasources.default.username=${DB_USERNAME}
datasources.default.password=${DB_PASSWORD}
Linux/macOS
export JDBC_URL=jdbc:postgresql://localhost:5432/productdb
export DB_USERNAME=postgres
export DB_PASSWORD=secret
Windows PowerShell
$env:JDBC_URL="jdbc:postgresql://localhost:5432/productdb"
$env:DB_USERNAME="postgres"
$env:DB_PASSWORD="secret"
#21. Error Handling
ใน project ที่ใหญ่ขึ้นควรสร้าง exception และ handler แยกจาก controller เช่น
ProductNotFoundException
ProductNotFoundExceptionHandler
DuplicateProductException
DuplicateProductExceptionHandler
เป้าหมายคือให้ error response มีรูปแบบคงที่ เช่น
{
"code": "PRODUCT_NOT_FOUND",
"message": "Product 99 was not found"
}
ไม่ควรส่ง stack trace หรือ internal exception message ที่ไม่จำเป็นกลับไปยัง client ใน production
#22. Security
REST API production ควรพิจารณา Micronaut Security เช่น
security-jwt
OAuth 2.0 / OpenID Connect
Role-based access control
ตัวอย่างแนวคิด
POST /login
|
v
Authentication
|
v
JWT
|
v
Authorization: Bearer <token>
|
v
Protected REST API
และควรกำหนด
- HTTPS
- CORS อย่างเหมาะสม
- input validation
- rate limiting ที่ API Gateway / reverse proxy
- secret management
- least privilege สำหรับ database account
- dependency/security scanning
#23. Production Architecture
flowchart TB
Client["Web / Mobile / External Client"]
Proxy["Load Balancer / API Gateway"]
API["Micronaut REST API"]
DB[("PostgreSQL")]
Cache[("Redis")]
Metrics["Metrics / Tracing / Logs"]
Client --> Proxy
Proxy --> API
API --> DB
API --> Cache
API --> Metrics
Micronaut เหมาะกับการนำไป deploy ในหลายรูปแบบ เช่น
JAR
Docker
Kubernetes
Serverless
GraalVM Native Image
#24. Dockerfile ตัวอย่าง
เมื่อ build JAR แล้ว สามารถ package เป็น container ได้
FROM eclipse-temurin:21-jre
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
build
./mvnw clean package
docker build -t micronaut-product-api .
run
docker run --rm -p 8080:8080 micronaut-product-api
ชื่อและตำแหน่ง JAR อาจแตกต่างตาม build configuration ของ project ให้ตรวจสอบใน
target/ก่อนสร้าง image
#25. แนวทางจัด Layer สำหรับ Project ขนาดใหญ่
ตัวอย่าง structure ที่เหมาะกับระบบจริงมากขึ้น
src/main/java/example/product/
├── controller/
│ └── ProductController.java
├── dto/
│ ├── ProductCreateRequest.java
│ ├── ProductUpdateRequest.java
│ └── ProductResponse.java
├── entity/
│ └── Product.java
├── repository/
│ └── ProductRepository.java
├── service/
│ └── ProductService.java
├── exception/
│ ├── ProductNotFoundException.java
│ └── ProductNotFoundExceptionHandler.java
└── Application.java
flow
HTTP Request
↓
Controller
↓
Service
↓
Repository
↓
Database
Controller ควรรับผิดชอบด้าน HTTP ส่วน Service รับผิดชอบ business logic และ Repository รับผิดชอบ data access
#26. Best Practices
#แยก DTO ออกจาก Entity
ไม่ควร expose database entity เป็น API contract โดยไม่จำเป็น
#ใช้ Migration Tool
ใช้ Flyway หรือ Liquibase แทนการสร้าง schema ด้วยมือใน production
#Validate ทุก Input
ใช้ jakarta.validation กับ request DTO
#จัดการ Blocking I/O
JDBC เป็น blocking ดังนั้นควรจัด execution model ให้เหมาะสม เช่น @ExecuteOn(TaskExecutors.BLOCKING)
#ใช้ HTTP Status Code ให้ถูกต้อง
เช่น 201, 204, 400, 404, 409
#มี API Documentation
ใช้ OpenAPI และ Swagger UI
#ทดสอบหลายระดับ
อย่างน้อยควรมี
Unit Test
Repository Test
Controller / Integration Test
API Test
#ใช้ Testcontainers กับฐานข้อมูลจริงในการทดสอบ
การใช้ PostgreSQL/MySQL ผ่าน Testcontainers ช่วยลดความต่างระหว่าง test environment กับ production
#ใช้ Pagination
endpoint ที่คืนข้อมูลจำนวนมากไม่ควร findAll() ตลอดไป ควรใช้ PageableRepository
#เพิ่ม Observability
production ควรมี
Health Check
Metrics
Distributed Tracing
Structured Logging
#27. Micronaut กับ Spring Boot ต่างกันอย่างไรในมุม REST API
ทั้งสอง framework ใช้สร้าง REST API บน JVM ได้ดี แต่แนวทางภายในแตกต่างกันบางส่วน
| หัวข้อ | Micronaut | Spring Boot |
|---|---|---|
| Dependency Injection | เน้น compile-time | ใช้ runtime mechanisms มากกว่าในหลายส่วน |
| Reflection | ลดการพึ่ง reflection | ecosystem ดั้งเดิมมีการใช้ reflection มากกว่า |
| Startup | เน้น startup เร็ว | ดีขึ้นมากในรุ่นปัจจุบัน |
| Memory | ออกแบบให้ footprint ต่ำ | ขึ้นกับ stack และ configuration |
| Native Image | รองรับ GraalVM | รองรับ GraalVM เช่นกัน |
| Ecosystem | เล็กกว่า | ใหญ่มาก |
| Cloud/Microservices | จุดเด่นหลัก | รองรับครบเช่นกัน |
การเลือกควรขึ้นกับ ecosystem, team skill, library compatibility, deployment target และ non-functional requirements ของระบบ
#28. Roadmap การเรียนรู้ Micronaut REST API
1. Controller + Routing
↓
2. JSON Serialization
↓
3. Validation
↓
4. Micronaut Data
↓
5. Database + Flyway
↓
6. Error Handling
↓
7. OpenAPI / Swagger UI
↓
8. Testing
↓
9. Security JWT / OAuth2
↓
10. Docker / Kubernetes
↓
11. Metrics / Tracing
↓
12. GraalVM Native Image
#29. สรุป
การสร้าง REST API ด้วย Micronaut มีองค์ประกอบหลักไม่ต่างจาก modern backend framework อื่น คือ Routing, Validation, Data Access, Error Handling, Testing, Security และ API Documentation
สิ่งที่เป็นจุดเด่นของ Micronaut คือแนวทาง compile-time dependency injection, introspection และ data access generation ซึ่งช่วยลดงานบางส่วนที่มักเกิดใน runtime และเหมาะกับ cloud-native workloads
สำหรับการเริ่มต้น สามารถใช้ stack ดังนี้
Java 21+
Micronaut 5.x
Micronaut HTTP Server
Micronaut Serialization
Bean Validation
Micronaut Data JDBC
Flyway
PostgreSQL
OpenAPI / Swagger UI
JUnit
Docker
เมื่อระบบเติบโต ควรแยก Controller, Service, Repository, DTO และ Entity ออกจากกัน เพิ่ม security, observability, pagination และ integration testing ให้ครบก่อนนำขึ้น production
#References
-
Micronaut Guides — Creating your first Micronaut application
https://guides.micronaut.io/latest/creating-your-first-micronaut-app-maven-java.html -
Micronaut Guides — Access a database with Micronaut Data JDBC
https://guides.micronaut.io/latest/micronaut-data-jdbc-repository-maven-java.html -
Micronaut Guides — OpenAPI and Swagger UI
https://guides.micronaut.io/latest/micronaut-openapi-swagger-ui-maven-java.html -
Micronaut Guides — Error Handling
https://guides.micronaut.io/latest/micronaut-error-handling-gradle-java.html -
Micronaut Framework 5.1.5 release announcement
https://micronaut.io/2026/09/11/micronaut-framework-5-1-5/