業務場景:倉庫入庫作業需同時在 **自建 Java Web 系統** 與 **標準 SAP (無倉位管理)** 記錄相同條碼資料,條碼槍掃描一次,兩邊輸入框自動填入,避免雙重操作。核心挑戰在於 **異構系統即時同步** 且 **不修改 SAP 標準代碼**。
掃描槍 → 瀏覽器/手持終端 → Java Web Controller → 中介同步服務 → (並行) Java Web DB + SAP BAPI/RFC
| 方案 | 技術細節 | 優點 | 缺點/風險 |
|---|---|---|---|
| 1. Java 端雙寫 (同步 RPC) | Controller 內先存本地 DB,再呼叫 JCo/SAP RFC/BAPI 寫入 SAP,事務邊界由 Java 管理 | 邏輯集中、易除錯、強一致性 | SAP 回應慢導致前端卡頓;SAP 掛點造成本地回滾;需處理分散式事務補償 |
| 2. 訊息佇列異步解耦 (推薦) | Controller 存本地 DB → 發送訊息至 Kafka/RabbitMQ/ActiveMQ → 消費者端呼叫 SAP BAPI,重試/死信佇列保障最終一致性 | 前端秒回、削峰填谷、SAP 維護窗口不影響前端、可重放 | 引入 MQ 運維成本;極短暫延遲 (通常 <1s);需設計冪等鍵 (條碼+時間戳) |
| 3. SAP IDoc/PI/PO 中介 | Java 端產生標準 IDoc (如 MATMAS, WMTO) → 傳送至 SAP PI/PO 或直接 RFC → SAP 標準 IDoc 處理流程入庫 | 符合 SAP 架構規範、可複用標準流程、支援變更記錄 | 需 BASIS 配合配置 PI/PO;開發調試週期長;IDoc 結構複雜 |
@RestController
@RequestMapping("/api/inbound")
public class InboundController {
@Autowired private InboundService localService;
@Autowired private KafkaTemplate kafka;
@PostMapping("/scan")
public Result scan(@RequestBody ScanDTO dto) {
// 1. 本地入庫 (本地事務)
InboundRecord rec = localService.createInbound(dto.getBarcode(), dto.getQty());
// 2. 發送同步事件 (非阻塞)
InboundEvent evt = new InboundEvent(rec.getId(), dto.getBarcode(), dto.getQty(), dto.getPlant());
kafka.send("sap-inbound-sync", evt.getBarcode(), evt); // Key 為條碼,保證分區有序
return Result.ok(rec.getId());
}
}
@Service
@RequiredArgsConstructor
public class SapSyncConsumer {
private final SapBapiClient sapClient; // 封裝 JCo 呼叫 BAPI_GOODSMVT_CREATE 等
private final InboundRepository repo;
@KafkaListener(topics = "sap-inbound-sync", groupId = "sap-sync")
public void handle(InboundEvent evt) {
try {
// 冪等檢查
if (repo.existsBySapDocNumAndBarcode(evt.getSapDocNum(), evt.getBarcode())) return;
// 呼叫 SAP BAPI
String sapDoc = sapClient.postGoodsMovement(evt);
// 回寫 SAP 單號
repo.updateSapDocNum(evt.getLocalId(), sapDoc);
} catch (Exception e) {
// 記錄失敗、進入重試/死信流程
log.error("SAP sync failed", e);
throw e; // 觸發 Kafka 重試
}
}
}
barcode + plant + movement_date 組合唯一鍵,SAP 端同樣檢查避免重複過帳。lag、error_rate、sap_latency_p99;超閾值發送企業微信/釘釘告警。總結:**訊息佇列異步雙寫** 是平衡即時性、穩定性、擴展性的最佳選擇。先在 Java 端落地本地入庫,再以事件驅動方式可靠同步至 SAP,既滿足「掃一次、雙同步」的業務目標,又為未來接入更多下游系統 (WMS、MES、BI) 預留擴展點。