Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 23

Thiết kế Quy trình với XOR và AND Gateway

Recommended resources

Chào bạn,

Trong những bài học vừa qua, chúng ta đã lần lượt tìm hiểu về từng loại gateway riêng lẻ: Exclusive (XOR) để lựa chọn, Parallel (AND) để thực thi song song, và Inclusive (OR) cho các kịch bản phức hợp. Sức mạnh thực sự của BPMN và Camunda được thể hiện khi chúng ta kết hợp các công cụ này để mô hình hóa những quy trình nghiệp vụ phức tạp của thế giới thực.

Bài học hôm nay sẽ giúp bạn thực hiện chính xác điều đó. Mục tiêu của chúng ta là 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ể. Bạn sẽ học cách thiết kế và triển khai một luồng công việc trong đó các hoạt động diễn ra đồng thời, và bên trong một trong những luồng song song đó lại chứa một quyết định rẽ nhánh.

Tóm tắt nhanh: AND và XOR Gateway

Trước khi bắt đầu, hãy cùng nhắc lại nhanh:

  • Parallel Gateway (AND): Khi một luồng đi vào, nó sẽ tạo ra các luồng song song cho tất cả các nhánh đi ra. Gateway hợp nhất sẽ chờ tất cả các luồng song song hoàn thành rồi mới đi tiếp.
  • Exclusive Gateway (XOR): Đánh giá các điều kiện và chỉ chọn một và chỉ một nhánh đi ra để thực thi.

Bây giờ, hãy xem làm thế nào để kết hợp chúng.


1. Phân tích một quy trình mẫu

Để hiểu rõ cách kết hợp các gateway, chúng ta sẽ phân tích một ví dụ thực tế từ tài liệu "BPMN 2.0 by Example". Ví dụ này mô tả quy trình chuẩn bị vận chuyển của một nhà bán lẻ, một kịch bản rất phổ biến trong các hệ thống thương mại điện tử.

[PDF] BPMN 2.0 by Example Version 1.0

Tài liệu 'BPMN 2.0 by Example' cung cấp một ví dụ xuất sắc về việc kết hợp các gateway. Việc đọc và phân tích nó sẽ cho bạn một nền tảng vững chắc trước khi chúng ta bắt tay vào code.

Hãy đọc phần 5.1 Shipment Process of a Hardware Retailer (bắt đầu ở cuối trang 2). Đặc biệt chú ý đến đoạn văn giải thích về Parallel Gateway và Exclusive Gateway: 'Right after the instantiation of the process, there are two things done in parallel, as the parallel gateway indicates: While the clerk has to decide whether this is a normal postal or a special shipment..., the warehouse worker can already start packaging the goods. [...] The gateway only works as a router, which is based on the result of the previous task, and provides alternative paths.' Phần này mô tả chính xác logic mà chúng ta sắp xây dựng: thực hiện song song việc đóng gói và việc ra quyết định về phương thức vận chuyển.

Từ ví dụ trên, chúng ta có thể rút ra một mô hình logic rất hữu ích:

  1. Bắt đầu một công việc lớn (chuẩn bị đơn hàng).
  2. Sử dụng Parallel Gateway để tách ra các công việc có thể làm đồng thời:
    • Nhánh 1: Một công việc độc lập (ví dụ: đóng gói hàng hóa).
    • Nhánh 2: Một chuỗi các công việc tuần tự, bao gồm việc ra quyết định (ví dụ: xác định phương thức vận chuyển, sau đó chuẩn bị giấy tờ tương ứng).
  3. Sử dụng Exclusive Gateway bên trong Nhánh 2 để xử lý việc ra quyết định.
  4. Sử dụng Parallel Gateway để hợp nhất các nhánh lại, đảm bảo mọi việc đã hoàn tất trước khi chuyển sang bước cuối cùng.
BPMN Process Combining Exclusive (XOR) and Parallel (AND) Gateways
Một sơ đồ trừu tượng minh họa việc kết hợp gateway. Sau khi `Do A`, một XOR gateway đưa ra quyết định. Sau `Do C`, một AND gateway bắt đầu các tác vụ song song `Do D` và `Do E`. Quy trình chúng ta xây dựng sẽ có cấu trúc lồng ghép phức tạp hơn: một XOR gateway nằm *bên trong* một trong các nhánh của AND gateway.

2. Thực hành: Xây dựng quy trình vận đơn

Bây giờ, chúng ta sẽ áp dụng mẫu logic trên để xây dựng một phiên bản đơn giản của quy trình vận đơn bằng Camunda.

Kịch bản:
Khi một đơn hàng được xác nhận, hai việc cần được thực hiện song song:

  1. Nhân viên kho tiến hành đóng gói hàng hóa.
  2. Nhân viên vận hành phải xác định phương thức vận chuyển là "tiêu chuẩn" (standard) hay "hỏa tốc" (express). Dựa trên quyết định này, hệ thống sẽ tự động thực hiện các bước chuẩn bị tương ứng.

Cả hai luồng công việc trên phải hoàn tất thì đơn hàng mới được coi là "Sẵn sàng để giao".

Bước 1: Vẽ sơ đồ trên Camunda Modeler

Hãy mở Camunda Modeler và tạo một sơ đồ BPMN mới với logic như sau:

  1. Start Event: "Đơn hàng được xác nhận".
  2. Parallel Gateway (AND - Phân nhánh).
  3. Từ gateway này, kéo ra hai nhánh:
    • Nhánh 1: Dẫn đến một User Task tên là "Đóng gói hàng hóa".
    • Nhánh 2: Dẫn đến một User Task tên là "Xác định phương thức vận chuyển".
  4. Sau User Task "Xác định phương thức vận chuyển", thêm một Exclusive Gateway (XOR - Rẽ nhánh) với câu hỏi "Phương thức vận chuyển?".
  5. Từ XOR Gateway, kéo ra hai nhánh:
    • Nhánh 2a: Dẫn đến một Service Task tên là "Chuẩn bị vận chuyển hỏa tốc".
    • Nhánh 2b: Dẫn đến một Service Task tên là "Chuẩn bị vận chuyển tiêu chuẩn".
  6. Thêm một Exclusive Gateway (XOR - Hợp nhất) và nối hai Service Task trên vào đó.
  7. Thêm một Parallel Gateway (AND - Hợp nhất).
  8. Nối User Task "Đóng gói hàng hóa" (từ Nhánh 1) và XOR Gateway hợp nhất (từ Nhánh 2) vào Parallel Gateway hợp nhất này.
  9. End Event: "Sẵn sàng để giao".

Sơ đồ của bạn sẽ trông tương tự như thế này:

Sơ đồ quy trình vận đơn kết hợp Parallel và Exclusive Gateway. Luồng xử lý được tách ra để thực hiện song song việc đóng gói và quyết định phương thức vận chuyển.

Bước 2: Cấu hình các thành phần

  1. Cấu hình XOR Gateway rẽ nhánh:

    • Chọn luồng đi đến Service Task "Chuẩn bị vận chuyển hỏa tốc".
    • Trong Properties Panel, tab General, đặt Condition Type là Expression.
    • Trong ô Expression, nhập: #{shippingMethod == 'express'}. Biến shippingMethod sẽ được tạo ra khi hoàn thành User Task "Xác định phương thức vận chuyển".
    • Chọn luồng đi đến Service Task "Chuẩn bị vận chuyển tiêu chuẩn" và đặt nó làm Default Flow.
  2. Cấu hình các Service Task:

    • Chọn Service Task "Chuẩn bị vận chuyển hỏa tốc".
    • Trong Properties Panel, tab General, đặt Implementation là Delegate Expression.
    • Trong ô Delegate Expression, nhập: ${prepareExpressShippingDelegate}.
    • Làm tương tự cho Service Task "Chuẩn bị vận chuyển tiêu chuẩn" với Delegate Expression là ${prepareStandardShippingDelegate}.

Bước 3: Implement Java Delegates

Trong dự án Spring Boot của bạn, hãy tạo hai lớp JavaDelegate mới để giả lập logic nghiệp vụ.

// File: com/example/camunda/delegate/PrepareExpressShippingDelegate.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("prepareExpressShippingDelegate")
public class PrepareExpressShippingDelegate implements JavaDelegate {

    private final Logger log = LoggerFactory.getLogger(PrepareExpressShippingDelegate.class);

    @Override
    public void execute(DelegateExecution execution) throws Exception {
        String orderId = (String) execution.getVariable("orderId");
        log.info("THỰC HIỆN: Chuẩn bị vận chuyển HỎA TỐC cho đơn hàng {}", orderId);
        // Logic thực tế có thể là gọi API của đơn vị vận chuyển, in nhãn...
    }
}
// File: com/example/camunda/delegate/PrepareStandardShippingDelegate.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("prepareStandardShippingDelegate")
public class PrepareStandardShippingDelegate implements JavaDelegate {

    private final Logger log = LoggerFactory.getLogger(PrepareStandardShippingDelegate.class);

    @Override
    public void execute(DelegateExecution execution) throws Exception {
        String orderId = (String) execution.getVariable("orderId");
        log.info("THỰC HIỆN: Chuẩn bị vận chuyển TIÊU CHUẨN cho đơn hàng {}", orderId);
    }
}

Bước 4: Deploy và kiểm thử

  1. Lưu file BPMN của bạn trong Modeler.
  2. Khởi động lại ứng dụng Spring Boot để Camunda Engine deploy phiên bản mới của quy trình.
  3. Mở Postman và khởi tạo một quy trình mới.

Kịch bản 1: Vận chuyển Hỏa tốc

  1. Khởi tạo quy trình: Gửi yêu cầu POST đến http://localhost:8080/engine-rest/process-definition/key/{YOUR_PROCESS_ID}/start với payload:
    {
      "variables": {
        "orderId": { "value": "DH-123", "type": "String" }
      }
    }
    
  2. Kiểm tra trong Tasklist: Truy cập http://localhost:8080/camunda/app/tasklist/. Bạn sẽ thấy 2 task đang hoạt động: "Đóng gói hàng hóa" và "Xác định phương thức vận chuyển". Điều này chứng tỏ Parallel Gateway đã hoạt động.
  3. Hoàn thành Task quyết định: Claim và Complete task "Xác định phương thức vận chuyển". Khi complete, hãy thêm một biến shippingMethod với kiểu String và giá trị express.
  4. Quan sát Console: Bạn sẽ thấy log "THỰC HIỆN: Chuẩn bị vận chuyển HỎA TỐC...".
  5. Kiểm tra trong Cockpit: Quay lại Cockpit, bạn sẽ thấy quy trình đang chờ ở Parallel Gateway hợp nhất, vì task "Đóng gói hàng hóa" vẫn chưa xong.
  6. Hoàn thành Task còn lại: Quay lại Tasklist, complete task "Đóng gói hàng hóa".
  7. Kết quả: Quy trình hoàn tất.

Kịch bản 2: Vận chuyển Tiêu chuẩn
Lặp lại các bước trên, nhưng khi hoàn thành task "Xác định phương thức vận chuyển", hãy đặt giá trị biến shippingMethod là standard (hoặc không cung cấp biến này, vì chúng ta đã có default flow). Bạn sẽ thấy log của PrepareStandardShippingDelegate và quy trình cũng sẽ chạy đúng như mong đợi.


Tổng kết

Qua bài thực hành hôm nay, bạn đã học được cách kết hợp hai trong số các gateway quan trọng nhất của BPMN để tạo ra các quy trình phức tạp và thực tế hơn.

Những điểm chính cần nhớ:

  • Kết hợp các gateway cho phép bạn mô hình hóa các kịch bản trong đó các luồng công việc song song lại chứa các quyết định nội bộ.
  • Cấu trúc của các gateway là rất quan trọng: một gateway phân nhánh (splitting) phải được khớp với một gateway hợp nhất (merging) cùng loại để đảm bảo luồng đi chính xác (AND-split với AND-join, XOR-split với XOR-join).
  • Parallel Gateway cho phép bạn tối ưu hóa thời gian xử lý bằng cách thực hiện các công việc không phụ thuộc lẫn nhau một cách đồng thời.
  • Exclusive Gateway cung cấp các điểm quyết định có điều kiện bên trong các luồng công việc đó.

Xem trước bài học tiếp theo

Bạn đã thấy các điều kiện hoạt động trơn tru khi chúng ta nhập đúng tên biến và giá trị. Nhưng trong thực tế, lỗi rất dễ xảy ra: gõ sai tên biến (shippinMethod thay vì shippingMethod), sai kiểu dữ liệu, hoặc logic điều kiện phức tạp bị lỗi.

Trong bài học tiếp theo, chúng ta sẽ khám phá chủ đề: Debug và xử lý các lỗi logic trong điều kiện của gateway. Bạn sẽ học cách Camunda Engine báo cáo các sự cố (incidents) và cách sử dụng Camunda Cockpit như một công cụ gỡ lỗi mạnh mẽ để chẩn đoán và khắc phục những lỗi này.