脈絡:從一個系統送訊息到另一個系統時,目標系統常需要比來源系統所能提供的更多資訊。
- 進站的 Address 訊息可能只含郵遞區號,因為設計者覺得再存一個州碼是多餘的;但另一套系統很可能同時要州碼與郵遞區號欄位,再另一套系統甚至不用州碼,而是把州名拼出來(因為它用自由格式地址來支援國際地址)。
- 一套系統給我們客戶 ID,但接收端實際需要的是客戶姓名與地址。
- 訂單管理系統送來的訂單訊息可能只含訂單號碼,但我們得找出對應的客戶 ID 才能交給客戶管理系統。
這是 Message Translator 的一個特例,但略有不同:Message Translator 假設接收端所需的資料已經在進站訊息裡了,只是格式不對;而這裡不是重排欄位這麼簡單,我們真的需要注入額外資訊。
醫院排程系統的例子#
醫院排程系統發布一則訊息,宣告某位病患已完成一次看診。訊息含有病患的名字、病患 ID 與看診日期。
但會計系統要記錄這次看診並通知保險公司,需要的是完整病患姓名、保險承保人與病患的社會安全號碼——而排程系統並不存這些資訊,它們在客戶照護系統裡。
選項 A:讓排程系統也存這些額外資訊#
當客戶資訊在客戶照護系統中變動(例如病患換了保險),變更就複寫到排程系統,排程系統於是能送出含全部必要資訊的訊息。
兩個重大缺點:
- 需要修改排程系統的內部結構。多數情況下排程系統是套裝應用,未必允許這類修改。
- 即使可以客製,我們是依「另一個系統的特定需求」在改動這個系統。若之後還想寄確認信給病患,就得再改一次排程系統來容納郵寄地址。
若能把排程系統與「消費『看診』訊息的那些應用程式的細節」解耦,整合方案會好維護得多。
選項 B:排程系統送訊息前先去要資料#
排程系統在送出「看診」訊息之前,先向客戶照護系統索取社會安全號碼與承保人資料。這解決了第一個問題——不必改儲存結構。
但第二個問題還在:排程系統仍得知道「為了通知會計系統,需要 SSN 與承保人資訊」。這則訊息的語意於是更接近「通知保險公司」而不是「看診」。
在鬆散耦合的系統中,我們不希望一個系統去指示下一個系統該做什麼——我們寧可送出 Event Message,讓其他系統自行決定要做什麼。
此外這個方案讓排程系統與客戶照護系統耦合得更緊(它現在得知道去哪裡取缺漏的資料),同時綁住了會計系統與客戶照護系統——這種耦合會造就脆弱的整合方案。
選項 C:先送給客戶照護系統#
先把訊息送給客戶照護系統,由它取齊所需資訊後再送一則完整訊息給會計系統。這把排程系統與後續訊息流漂亮地解耦了。
但這樣一來,「病患看診後保險公司收到帳單」這條業務規則就被實作在客戶照護系統裡,得修改該系統的邏輯——若它是套裝應用,這可能很困難甚至不可能。
而且即使改得動,我們也讓客戶照護系統間接負責寄帳單訊息。若會計系統所需的資料項不全在客戶照護系統裡,我們又回到原點了。
選項 D:改造會計系統#
讓會計系統只要客戶 ID,自己去客戶照護系統取 SSN 與承保人資訊。
兩個缺點:會計系統與客戶照護系統耦合了;而且這同樣假設我們能控制會計系統——它多半也是客製選項有限的套裝應用。

圖 8-6:會計系統需要的資訊多於排程系統所能提供

圖 8-7:Enricher 問題的幾種可能解法
解法#
Content Enricher 用進站訊息中的資訊(例如鍵欄位)從外部來源取出資料,再把資料附加到訊息上。
進站訊息的原始資訊可能被帶進結果訊息,也可能不再需要——取決於接收端的具體需求。

圖 8-5:Content Enricher 解法示意
新資料從哪來#
- 計算(Computation)——Content Enricher 或許能自己算出缺漏的資訊,此時演算法本身就含有那份額外資訊。例如接收端要州碼、進站訊息只有郵遞區號;或接收端要求的格式需要指明訊息總長度,Enricher 就把所有欄位長度加起來。
這種形式的 Content Enricher 非常接近基本的 Message Translator,因為它不需要外部資料來源。
- 環境(Environment)——從運行環境取得,最常見的例子是時間戳:若接收端要求每則訊息帶時間戳而送件系統沒放,Enricher 就從作業系統取得當前時間補上。
- 另一個系統(Another System)——最常見的一種。資料來源可以是資料庫、檔案、LDAP 目錄、某個系統,甚至是手動輸入缺漏資料的使用者。
通訊機制的選擇#
外部資源常常位於另一個系統、甚至企業之外,因此 Content Enricher 與資源之間的通訊可以走訊息通道,也可以走任何其他機制。
但因為 Content Enricher 與資料來源之間的互動在定義上就是同步的(拿不到資料就送不出增補後的訊息),使用同步協定(如 HTTP 或到資料庫的 ODBC 連線)效能可能比非同步訊息更好。
Content Enricher 與資料來源在本質上就是緊密耦合的,所以「透過 Message Channel 達成鬆散耦合」在這裡沒那麼重要。
回到例子#
我們插入一個 Content Enricher 去客戶照護系統取額外資料。於是:
- 排程系統漂亮地擺脫了「必須處理保險資訊或客戶照護系統」的負擔——它只要發布「看診」訊息就好
- Content Enricher 負責取得所需資料
- 會計系統也仍然獨立於客戶照護系統之外

圖 8-8:把 Enricher 套用到病患看診的例子
用來解析參考#
Content Enricher 常被用來解析訊息中所含的參考。為了讓訊息小而好管理,我們常選擇傳遞簡單的物件參考(鍵或唯一 ID)而不是完整物件;當訊息需要被某個系統處理時,就依這些參考取回所需的資料項。
這裡有明顯的取捨:用參考能減少原始訊息的資料量,但需要對資源做額外查詢。
使用參考是否改善效能,取決於有多少元件能單純靠參考運作、又有多少元件需要用 Content Enricher 還原部分原始內容。例如若訊息在抵達最終接收者前要經過一長串中介者,用物件參考能顯著降低訊息流量——我們可以在最終接收者之前插入一個 Content Enricher,把缺漏資訊載回訊息。
反過來說,若訊息已經含有我們不想一路揹著的資料,就用 Claim Check 把資料存起來、換一個參考。
範例:與外部單位通訊

圖 8-9:與外部單位通訊時搭配使用 Content Enricher 與 Content Filter
Content Enricher 也常用於「與要求訊息符合特定標準(例如 ebXML)的外部單位」通訊。
這些標準多半要求龐大的訊息與一長串資料。
我們通常可以大幅簡化內部運作:把內部訊息保持得盡量簡單,只在把訊息送出組織之外時才用 Content Enricher 補上缺漏欄位;同樣地,用 Content Filter 把進站訊息中不必要的資訊剝掉——形成一組 Content Enricher/Content Filter 的搭配。