Nhảy đến nội dung chính

2. API Design & Response Standard

2.1. Mục tiêuTiêu chương

Chương

Chương này quy định cấu trúc chuẩn của mỗi moduleintegration flow và trách nhiệm của từng artifact layer nhằm:

  • Tách biệt rõ ràng các tầng xử lý

    trong luồng tích hợp
  • Giảm phụ thuộc giữa các thành phần

    artifact
  • Dễ bảo trì, mở rộng và test

    kiểm thử từng layer độc lập
  • Đảm bảo tính nhất quán giữa các moduleflow trong toàn hệ thống

2.2. Khái niệmNiệm / phạmPhạm viVi ápÁp dụng

Dụng

Quy tắc này áp dụng cho:

  • Tất cả các moduleintegration flow trong thư mục modules/artifacts/**

  • Cả Core Team và Partner Team

  • Tất cả các chứcluồng năngtích hợp mới được phát triển

Cấu trúcTrúc chuẩnArtifact mỗi module

Chuẩn

modules/<module-name>/

Mỗi

integration controller/flow

gồm

  service/

  repository/

  entity/

  dto/

Ý nghĩa từngcác thành phần

sau:image.png

Ý Nghĩa Từng Artifact Layer

Layer

response

public

Layer Artifact

Vai trò

dụ 

API

controller

Layer
apis/*.xml Nhận request từ client và trả  response

@PostMapping

publicKafkaProducerApi.xml, ApiResponse<PlanningResponse> create(@Valid

@RequestBody PlanningCreateRequest req) {

   return ApiResponse.ok(service.create(req));

}


PlanningDirectApi.xml
Mediation

service

Layer
sequences/*-inboundSequence.xmlXử lý logic, điều phối luồng

Xử

lý logic nghiệp vụ

public PlanningResponse get(Long id) {

   PlanningEntity e = repo.findById(id).orElseThrow(() ->

           new AppException(ErrorCode.NOT_FOUND, HttpStatus.NOT_FOUND, "Planning not found: " + id)

   );

   return toResponse(e);

}

Load_balance_example-inboundSequence.xml
Error

repository

Layer
sequences/*-inboundErrorSequence.xmlXử lý và cô lập lỗi

Truy

cập và thao tác dữ liệu

public interface PlanQueryRepository {

   long count(PlanListFilter filter);

   List<PlanListItem> list(PlanListFilter filter);

}


Load_balance_example-inboundErrorSequence.xml
Consumer

entity

Layer
inbound-endpoints/*.xmlNhận message từ Kafka topic

Mapping

bảng database

public class PlanningEntity {

   @Id

   @GeneratedValue(strategy = GenerationType.IDENTITY)

   private Long id;

}

Load_balance_example.xml
Connection

dto

Layer
local-entries/*.xmlCấu hình kết nối dùng chung

Model

requestKafkaConnection.xml
Endpoint Layer endpoints/*.xml Định classnghĩa PlanListFilterbackend {

endpoint
Backend privateAPI String keyword;

   private Integer page = 1; // 1-based

   private Integer size = 20;

   private String sortBy = "created_at";

   private String sortDir = "desc";


   public String getKeyword() { return keyword; }

   public void setKeyword(String keyword) { this.keyword = keyword; }

   public Integer getPage() { return page; }

   public void setPage(Integer page) { this.page = page; }

   public Integer getSize() { return size; }

   public void setSize(Integer size) { this.size = size; }

   public String getSortBy() { return sortBy; }

   public void setSortBy(String sortBy) { this.sortBy = sortBy; }

   public String getSortDir() { return sortDir; }

   public void setSortDir(String sortDir) { this.sortDir = sortDir; }

}

address

2.3. Quy địnhĐịnh chínhChính

Trách Nhiệm Từng Layer

TráchAPI nhiệmLayer từng layer(apis/)

Controller
  • Nhận request HTTP từ client

    (hoặc từ WSO2 APIM Gateway)
  • Gọi servicebackend tươngtrực ứng

    tiếp hoặc publish message lên Kafka
  • Trả response chuẩn về client

  • Không xử lý logic nghiệp vụ

Service
  • Xử lý logic nghiệp vụ

  • Điều phối repository

  • Chuyển đổi entity ↔ DTO

Repository
  • Truy cập database

  • Thực hiện các thao tác CRUD

  • Không chứa logic nghiệp vụ

Entity
  • Mapping với bảng database

  • Không chứa logic nghiệp vụ phức tạp

DTO

Mediation Layer (sequences/*-inboundSequence.xml)

  • Xử

    Modellý message nhận từ Kafka consumer

  • Điều phối lời gọi đến backend API
  • Phân loại kết quả theo HTTP status code (2xx / 4xx / 5xx)
  • Publish kết quả vào processed_topic hoặc error_topic
  • Không xử lý lỗi kỹ thuật (dành cho request/response

    Error
  • Không gắn trực tiếp với entity

    Layer)

Error Layer (sequences/*-inboundErrorSequence.xml)

  • Bắt lỗi kỹ thuật khi consume message từ Kafka
  • Log đầy đủ thông tin: ERROR_CODEERROR_MESSAGEORIGINAL_PAYLOAD
  • Đóng gói và publish message lỗi vào error_topic
  • Không retry — chỉ ghi nhận và chuyển sang error topic

Consumer Layer (inbound-endpoints/)

  • Kết nối đến Kafka broker và subscribe topic
  • Khai báo sequence (luồng thành công) và onError (luồng lỗi)
  • Không chứa logic xử lý

Connection Layer (local-entries/)

  • Lưu thông tin kết nối Kafka dùng chung toàn hệ thống
  • Chỉ Core Team được phép chỉnh sửa

Quy tắcTắc bắtBắt buộc

  1. Buộc

    Controller API Layer không được chứa logic nghiệp vụ

     phức tạp

  2. Mọi

  3. Khôngresponse trả trựcvề tiếpclient Entityphải ratheo cấu trúc JSON chuẩn

    Error sequence phải luôn publish message vào error_topic

    Mediation sequence phải phân loại HTTP status (2xx / 4xx / 5xx)

    Cấu Trúc Response Chuẩn

    Thành công:

    Thành công kèm data:

    Lỗi từ API

     Layer:

  4. Lỗi

  5. kỹ

    Luônthuật dùng(Error DTOSequence choghi request/response

    vào error_topic):

  6. Response chuẩn toàn hệ thống: ApiResponse<T>

2.4. Cách Thực Hiện / Quy Trình

Quy Trình Phát Triển Một Integration Flow Mới

Bước 1: Khai báo Connection (nếu chưa có)

Tạo hoặc tái sử dụng 

Chỉ Core Team thực hiện /bước quy trình

Quy trình phát triển một chức năng mới

Bước 1: Tạo DTOnày.

Ví dụ:

UserCreateRequest

UserResponse

Bước 2: Tạo EntityInbound Endpoint

MappingTạo vớifile bảng database:inbound-endpoints/<flow-name>.xml:

UserEntity

Bước 3: Tạo RepositoryError Sequence

UserRepositoryTạo file sequences/<flow-name>-inboundErrorSequence.xml:

Bước 4: Tạo ServiceInbound Sequence

UserServiceTạo file sequences/<flow-name>-inboundSequence.xml:

Xử lý logic:

  • Validate dữ liệu

  • Gọi repository

  • Mapping entity → DTO

Bước 5: Tạo ControllerAPI (nếu cần điểm vào HTTP)

UserControllerTạo file apis/<flow-name>Api.xml:

  • Nhận request

  • Gọi service

image.pngho-so-core-flow (1).jpg

2.5. Ví dụ minh họa

Ví dụ sai (vi phạm quy tắc)

Controller chứa logic:

@GetMapping("/users")

public List<UserEntity> getAll() {

 return userRepository.findAll();Dụ Đúng — Inbound Sequence phân loại HTTP Status

}Đúng vì:

Ví Dụ Đúng — Error Sequence đóng gói lỗi chuẩn

 Ví Dụ Sai — Không phân loại HTTP Status

Sai vì:

  • Trả Entity trực tiếp

  • Không dùng Service

  • Không dùng ApiResponse


Ví dụ đúng

@GetMapping("/users")

public ApiResponse<List<UserResponse>> getAll() {

    return ApiResponse.ok(userService.getAll());

}

Service:

public List<UserResponse> getAll() {

    return userRepository.findAll()

        .stream()

        .map(this::toResponse)

        .toList();

}

 Ví Dụ Sai — API trả về raw data không theo chuẩn

Sai vì:

[Chỗ này thêm ảnh: Screenshot log WSO2 MI cho thấy STATUS, HTTP_STATUS, PAYLOAD được log đúng chuẩn]

2.6. Checklist ápÁp dụng

Dụng

Trước khi commit moduleintegration flow mới:

    Tài

  • liệu

    này đủ:

    thuộc phạm vi quản lý của Core Team — mọi thay đổi phải được Core Team phê duyệt.

    • controller/

    • service/

    • repository/

    • entity/

    • dto/

  • Controller không chứa logic nghiệp vụ

  • Không trả Entity ra API

  • Tất cả API trả về ApiResponse<T>

  • DTO tách biệt với Entity