Chào bạn,
Trong các bài học trước, chúng ta đã khám phá hai cách cơ bản để điều khiển luồng quy trình:
- Exclusive Gateway (XOR): Chọn một và chỉ một con đường, giống như câu lệnh
if-else if-else. - Parallel Gateway (AND): Thực thi tất cả các con đường cùng một lúc, không cần điều kiện.
Tuy nhiên, thực tế thường phức tạp hơn. Sẽ ra sao nếu bạn cần một quy trình có thể thực hiện một hoặc nhiều hành động tùy thuộc vào các điều kiện khác nhau? Ví dụ, khi xử lý một đơn hàng, tùy thuộc vào các mặt hàng trong đó, bạn có thể cần thực hiện thêm bước kiểm tra gian lận, hoặc chuẩn bị bao bì đặc biệt, hoặc cả hai, hoặc không cần làm gì cả.
Đây chính là lúc Inclusive Gateway (OR) phát huy tác dụng. Mục tiêu của bài học hôm nay là giúp bạn implement Inclusive Gateway (OR) cho các kịch bản rẽ nhánh phức hợp. Bạn sẽ học cách mô hình hóa và triển khai một gateway vừa có tính điều kiện của XOR, vừa có khả năng thực thi song song của AND.
1. Inclusive Gateway (OR) là gì?
Inclusive Gateway, hay OR Gateway, là một điểm quyết định trong quy trình cho phép kích hoạt một hoặc nhiều nhánh luồng đi ra.
Khi luồng quy trình đi đến một Inclusive Gateway phân nhánh (diverging), nó sẽ đánh giá tất cả các điều kiện trên các luồng đi ra. Mọi luồng có điều kiện được đánh giá là true sẽ được kích hoạt và thực thi. Điều này khác biệt rõ rệt với:
- XOR Gateway: Chỉ kích hoạt luồng đầu tiên có điều kiện
true. - AND Gateway: Kích hoạt tất cả các luồng mà không cần điều kiện.
Ký hiệu của Inclusive Gateway là một hình thoi với một vòng tròn bên trong (chữ 'O' tượng trưng cho 'OR').
Để hiểu rõ hơn sự khác biệt, hãy xem video so sánh trực tiếp giữa XOR và OR gateway.
BPMN XOR vs OR Gateway - How and When to use Them
Video này của kênh Stefano - The Agile Business Analyst sẽ làm rõ sự khác biệt giữa XOR và OR gateway thông qua các ví dụ đời thực.
Hãy xem các phần sau: Từ 02:44 đến 04:10: Tập trung vào ví dụ về đặt đồ ăn (food ordering) để hiểu cách OR gateway cho phép chọn một, hai, hoặc cả ba lựa chọn. Từ 04:10 đến 04:43: Xem phần so sánh nhanh để củng cố sự khác biệt chính về logic và cách các 'token' được tạo ra.
2. Các quy tắc quan trọng của Inclusive Gateway
Trước khi bắt tay vào thực hành, bạn cần nắm vững các quy tắc hoạt động của nó, đặc biệt là cách nó phân nhánh và hợp nhất.
Inclusive gateway - Camunda 8 Docs
Tài liệu chính thức của Camunda cung cấp một lời giải thích chi tiết và chính xác về Inclusive Gateway. Việc đọc tài liệu này rất quan trọng để bạn hiểu sâu về cách engine xử lý nó.
Hãy đọc các phần sau trong tài liệu: Phần đầu tiên (Inclusive gateway): Chú ý đến cách gateway phân nhánh (diverging) và hợp nhất (converging). Đặc biệt quan trọng là khái niệm Default Flow, được sử dụng khi không có điều kiện nào được đáp ứng. Điều này giúp tránh lỗi trong quy trình. Phần giải thích về converging gateway: Đọc kỹ để hiểu rằng gateway hợp nhất sẽ chờ cho đến khi tất cả các nhánh đã được kích hoạt hoàn thành. Đây là một điểm khác biệt tinh tế so với Parallel Gateway. Phần Conditions: Xem qua các ví dụ về cú pháp biểu thức điều kiện. Mặc dù tài liệu này dành cho Camunda 8 (sử dụng FEEL), cú pháp logic cơ bản vẫn tương tự với JUEL mà chúng ta đang dùng trong Camunda 7. Ví dụ: totalPrice > 100.
Từ video và tài liệu trên, đây là những điểm cốt lõi bạn cần ghi nhớ:
- Diverging (Phân nhánh): Đánh giá tất cả các điều kiện, kích hoạt tất cả các nhánh có điều kiện là
true. - Converging (Hợp nhất): Chờ tất cả các nhánh đã được kích hoạt trước đó hoàn thành rồi mới đi tiếp. Nếu chỉ có một nhánh được kích hoạt, nó sẽ đi qua ngay lập tức. Nếu ba nhánh được kích hoạt, nó sẽ chờ cả ba hoàn thành.
- Default Flow: Nếu không có điều kiện nào đúng và không có luồng mặc định (default flow), Camunda sẽ tạo ra một sự cố (incident). Do đó, việc xác định một default flow là một thực hành tốt để đảm bảo quy trình không bị "kẹt".

3. Thực hành: Xử lý đơn hàng với các yêu cầu đặc biệt
Bây giờ, chúng ta sẽ mở rộng quy trình xử lý đơn hàng của mình với một kịch bản phức tạp hơn, nơi Inclusive Gateway là lựa chọn lý tưởng.
Kịch bản:
Sau khi đơn hàng được chấp thuận, hệ thống cần thực hiện các kiểm tra bổ sung tùy thuộc vào nội dung và giá trị đơn hàng.
- Biến quy trình:
orderValue(double): Tổng giá trị đơn hàng.productCategories(List): Danh sách các loại sản phẩm trong đơn hàng (ví dụ: ["electronics", "books"]).
- Quy tắc nghiệp vụ:
- Nếu đơn hàng chứa mặt hàng
electronics, cần thực hiện "Kiểm tra gian lận bổ sung". - Nếu đơn hàng chứa mặt hàng
clothingVÀ có giá trị trên 500, cần "Gửi yêu cầu đóng gói cao cấp". - Nếu không có quy tắc nào ở trên được áp dụng, quy trình sẽ đi theo luồng xử lý thông thường.
- Nếu đơn hàng chứa mặt hàng
Bước 1: Cập nhật mô hình BPMN
- Mở file BPMN của bạn trong Camunda Modeler.
- Sau bước phê duyệt đơn hàng (có thể là sau Parallel Gateway đã tạo ở bài trước), hãy thêm một Inclusive Gateway (phân nhánh). Đặt tên cho nó, ví dụ: "Kiểm tra yêu cầu đặc biệt?".
- Từ gateway này, kéo ra 3 luồng:
- Luồng 1: Nối đến một Service Task mới, đặt tên là "Kiểm tra gian lận bổ sung".
- Luồng 2: Nối đến một Service Task khác, đặt tên là "Gửi yêu cầu đóng gói cao cấp".
- Luồng 3: Đây sẽ là luồng mặc định của chúng ta.
- Thêm một Inclusive Gateway thứ hai (hợp nhất). Nối cả 3 luồng trên vào gateway này.
- Từ gateway hợp nhất, kéo luồng đến bước tiếp theo của quy trình (ví dụ: "Thông báo cho kho" hoặc End Event).
Bước 2: Cấu hình điều kiện và Default Flow
Đây là bước quan trọng nhất. Chúng ta sẽ sử dụng Java Unified Expression Language (JUEL) để đặt điều kiện.
-
Cấu hình luồng "Kiểm tra gian lận":
- Chọn luồng nối từ gateway phân nhánh đến Service Task "Kiểm tra gian lận bổ sung".
- Trong Properties Panel, tab General, tìm mục Condition Type và chọn Expression.
- Trong ô Expression, nhập:
${productCategories.contains("electronics")} - Biểu thức này trả về
truenếu danh sáchproductCategorieschứa chuỗi "electronics".
-
Cấu hình luồng "Đóng gói cao cấp":
- Chọn luồng tương ứng.
- Trong ô Expression, nhập:
${productCategories.contains("clothing") && orderValue > 500} - Biểu thức này sử dụng toán tử
&&để kết hợp hai điều kiện.
-
Cấu hình Default Flow:
- Chọn luồng thứ ba (luồng không có tác vụ nào).
- Trong Properties Panel, tab General, bạn sẽ thấy một danh sách thả xuống ngay dưới tên gateway, hãy chọn luồng này làm Default Flow. Hoặc, bạn có thể click vào luồng và chọn biểu tượng gạch chéo nhỏ xuất hiện trên nó.
- Luồng mặc định không được có điều kiện. Nó sẽ được chọn khi không có điều kiện nào khác là
true.
Bước 3: Implement các Service Task
Trong project Spring Boot, hãy tạo hai lớp JavaDelegate mới.
// Trong file FraudCheckDelegate.java
package com.example.camunda.delegate;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component("fraudCheckDelegate")
public class FraudCheckDelegate implements JavaDelegate {
private final Logger log = LoggerFactory.getLogger(FraudCheckDelegate.class);
@Override
public void execute(DelegateExecution execution) throws Exception {
log.info("THỰC HIỆN: Kiểm tra gian lận bổ sung cho đơn hàng giá trị cao hoặc chứa đồ điện tử.");
}
}
// Trong file PremiumPackagingDelegate.java
package com.example.camunda.delegate;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component("premiumPackagingDelegate")
public class PremiumPackagingDelegate implements JavaDelegate {
private final Logger log = LoggerFactory.getLogger(PremiumPackagingDelegate.class);
@Override
public void execute(DelegateExecution execution) throws Exception {
log.info("THỰC HIỆN: Gửi yêu cầu đóng gói cao cấp cho đơn hàng giá trị > 500.");
}
}
Đừng quên liên kết các Service Task này trong Modeler với các Delegate Expression tương ứng: ${fraudCheckDelegate} và ${premiumPackagingDelegate}.
Bước 4: Deploy và kiểm tra
Bây giờ là lúc xem thành quả. Deploy và chạy lại ứng dụng Spring Boot. Sử dụng Postman hoặc một công cụ tương tự để khởi tạo các quy trình với các bộ biến khác nhau.
Kịch bản 1: Chỉ kiểm tra gian lận
- Payload:
{ "variables": { "orderValue": { "value": 300, "type": "Double" }, "productCategories": { "value": ["electronics", "books"], "type": "Object", "valueInfo": { "objectTypeName": "java.util.ArrayList", "serializationDataFormat": "application/json" } } } } - Kết quả mong đợi: Log từ
FraudCheckDelegatesẽ xuất hiện. Quy trình sẽ đi theo nhánh 1 và nhánh 3 (default, vì điều kiện 2 sai). Gateway hợp nhất sẽ chờ nhánh 1 hoàn thành rồi đi tiếp.
Kịch bản 2: Cả hai tác vụ
- Payload:
{ "variables": { "orderValue": { "value": 600, "type": "Double" }, "productCategories": { "value": ["electronics", "clothing"], "type": "Object", "valueInfo": { "objectTypeName": "java.util.ArrayList", "serializationDataFormat": "application/json" } } } } - Kết quả mong đợi: Log từ cả
FraudCheckDelegatevàPremiumPackagingDelegatesẽ xuất hiện. Trong Cockpit, bạn sẽ thấy hai token được tạo ra và chạy song song qua hai nhánh. Gateway hợp nhất sẽ chờ cả hai hoàn thành.
Kịch bản 3: Luồng mặc định
- Payload:
{ "variables": { "orderValue": { "value": 40, "type": "Double" }, "productCategories": { "value": ["books", "stationery"], "type": "Object", "valueInfo": { "objectTypeName": "java.util.ArrayList", "serializationDataFormat": "application/json" } } } } - Kết quả mong đợi: Không có log nào từ hai delegate trên. Quy trình sẽ đi thẳng qua luồng mặc định.
Tổng kết
Qua bài học này, bạn đã thêm vào "hộp công cụ" BPMN của mình một gateway rất mạnh mẽ và linh hoạt.
Những điểm chính cần nhớ:
- Inclusive Gateway (OR) kích hoạt một hoặc nhiều nhánh dựa trên các điều kiện, cho phép tạo ra các luồng xử lý phức hợp.
- Nó là sự kết hợp giữa logic có điều kiện của XOR Gateway và khả năng chạy song song của AND Gateway.
- Gateway hợp nhất (converging) sẽ chờ tất cả các nhánh đã được kích hoạt hoàn thành.
- Sử dụng Default Flow là một best practice để xử lý các trường hợp không có điều kiện nào đúng và tránh làm quy trình bị lỗi.
Xem trước bài học tiếp theo
Chúng ta đã tìm hiểu riêng lẻ về Exclusive, Parallel và Inclusive Gateway. Sức mạnh thực sự của BPMN nằm ở việc kết hợp chúng một cách thông minh để mô hình hóa các quy trình nghiệp vụ phức tạp trong thực tế.
Trong bài học tiếp theo, chúng ta sẽ thực hiện chính xác điều đó: Xây dựng một quy trình kết hợp XOR và AND gateway cho một trường hợp sử dụng cụ thể, giúp bạn thấy cách các loại gateway tương tác với nhau để tạo ra một luồng logic hoàn chỉnh.