Module 10 · Executable guide

Vert.x Web & Data

REST routing, WebClient, PostgreSQL client, transaction, validation, streaming và testing.


1. Router

Router router = Router.router(vertx);
router.route().handler(BodyHandler.create());
router.get("/users/:id").handler(this::getUser);
router.post("/orders").handler(this::createOrder);

2. RoutingContext

void getUser(RoutingContext ctx) {
    long id = Long.parseLong(ctx.pathParam("id"));
    service.findUser(id)
        .onSuccess(ctx::json)
        .onFailure(err -> fail(ctx, err));
}

3. Middleware

Request → BodyHandler → Correlation ID → Auth → Validation → Business Handler → Error Handler

4. WebClient

webClient.postAbs(paymentUrl)
    .sendJsonObject(payload)
    .compose(resp -> {
        if (resp.statusCode() >= 500)
            return Future.failedFuture("payment unavailable");
        return Future.succeededFuture(resp.bodyAsJsonObject());
    });

5. PostgreSQL Client

pool.preparedQuery(
    "SELECT id, user_id, status FROM orders WHERE id = $1")
    .execute(Tuple.of(id))
    .map(this::mapOrder);

6. Transaction

pool.withTransaction(conn ->
    conn.preparedQuery("UPDATE inventory SET reserved = reserved + $1 WHERE sku = $2")
        .execute(Tuple.of(qty, sku))
        .compose(v -> conn.preparedQuery("INSERT INTO orders(user_id,status) VALUES ($1,$2)")
            .execute(Tuple.of(userId, "CREATED")))
);

7. Validation

Phân biệt 400 validation, 404 missing, 409 conflict/idempotency và 503 downstream unavailable.

8. SSE

Theo dõi write queue và connection lifecycle; client chậm không được làm memory tăng vô hạn.

9. Testing

Deploy verticle thật trong integration test, setup DB fixture và gọi endpoint bằng WebClient.

10. Lab

  1. POST /orders validate JSON.
  2. Insert bằng prepared query.
  3. GET /orders/:id.
  4. Transaction reserve inventory + create order.
  5. WebClient timeout.
  6. Integration tests.