承接 第一部分,本文深入探討在 J/XFS 架構下開發銀行業裝置服務的關鍵要素。閱畢本文,您將掌握:
J/XFS 裝置服務是控制特定硬體裝置的 Java 物件。應用程式不直接向裝置服務發送訊息,而是將操作請求傳給 J/XFS 核心,核心確保訊息依序送達。通常由核心呼叫裝置服務物件上的方法(圖 1)。

回應傳回方式相同:裝置服務不直接發送訊息給應用程式,而是發給核心,再由核心分派給適當接收者(圖 2)。

此架構對開發者友善:只需遵循基本概念並實作正確的裝置服務介面即可。
J/XFS 介面分兩部分:
每種裝置類型已定義好介面集合,裝置服務僅實作符合其規格的介面。例如 ATM 裝置服務不會實作存摺印表機介面,因為兩者歸屬不同類型。
裝置服務封裝特定裝置邏輯與行為,對 J/XFS 環境隱藏所有裝置特性,僅暴露 J/XFS 標準定義的操作。
應用程式透過向核心發送訊息表達與某裝置服務通訊的意願。核心以回調物件向裝置服務註冊回應。裝置服務為每個回調物件指派唯一識別碼 (控制 ID),核心為該應用程式所有請求附加此 ID。
傳入的操作請求訊息即以此 ID 區分,要求開發者維護控制 ID 與事件回調物件的關聯。回調物件屬核心一部分,唯一目的讓裝置服務發送事件回報操作進度與結果。應用程式不再需要時,通知核心反註冊回調物件。
幾乎所有 J/XFS 裝置服務操作皆以非同步方式執行。收到請求時,裝置服務必須接受並分配唯一識別碼 (識別 ID),再於獨立執行緒執行操作。
區分控制 ID 與識別 ID 至關重要:
例:應用程式要求列印並吐紙,需發送兩個請求訊息,各自獲得識別 ID;但兩者同屬一個控制 ID。
操作結束時,透過操作完成事件回報結果與先前分配的 ID。若裝置服務忙碌時收到多個請求,依到達順序排隊執行(極少例外詳見規格書)。
取消操作時,應用程式請求核心取消,核心傳送含取消請求與識別 ID 的訊息給裝置服務。裝置服務須盡力停止操作並將裝置恢復操作前狀態(不一定總能做到)。
裝置服務執行期間呈現不同狀態,大多數狀態轉換會透過事件回報給單一或所有回調物件。核心隨時可查詢裝置服務目前狀態。
應用程式建立通訊基礎設施後,必須請求核心開啟裝置服務(含控制 ID)。核心發送為操作而開啟訊息,若硬體可操作,回應操作完成事件,裝置服務狀態轉為「開啟」可接收操作請求。
工作完成後,應用程式請求核心發送正式關閉訊息(含控制 ID),之後該控制 ID 不再接受任何操作請求。
多應用程式可註冊回調物件,操作請求通常依接收順序執行。但有時應用程式需確保請求執行期間不受干擾,便透過核心發送獨佔存取請求。裝置服務須管理此機制,確保特定期間僅一個控制 ID 擁有獨佔權。授權後,僅該控制 ID 的請求可執行,其餘排隊。任務完成後,核心代表應用程式發送移除獨佔狀態訊息。
理解基本需求後,熟悉 API 規格。本節針對標準版 1.0 及其核心實作,FDI for J/XFS 套件層次見後文。
所有可能狀態定義於狀態類。JxfsStatus 類彙整每個裝置服務可能呈現的布林狀態:
須隨時能從裝置服務取得狀態資訊。狀態間存在相依(如「聲明」依賴「開啟」),JxfsStatus 實例資訊必須前後一致,需同步機制保護。
部分裝置類型規格定義 JxfsStatus 子類擴充狀態資訊(如印表機的 JxfsPtrStatus 提供墨粉與供紙單元狀態)。通用狀態類還有 JxfsMediaStatus(介質處理狀態,如卡紙)與 JxfsThresholdStatus(可測量單元層級,如紙張滿/高/低/空)。
事件是裝置服務向應用程式傳遞資訊(經由核心)的唯一管道,分三類:
OperationCompleteEvent):每個非同步操作產生,回報結果與操作識別碼IntermediateEvent):操作執行中回報進度StatusEvent):裝置服務呈現新狀態時發送(非所有狀態變更皆回報)所有事件以裝置服務物件參考標識事件源(作為第一個參數)。規格為每個操作定義整數常數表示可能結果與操作識別碼。
J/XFS 僅有一種異常類型 JxfsException,拋出原因以 JxfsConst 介面定義的整數常數表示。例:
throw new JxfsException(JxfsConst.JXFS_E_NOT_SUPPORTED);
所有裝置服務必須支援主要介面 IJxfsBaseService,宣告所有類型共用的方法。
核心啟動裝置服務時發送初始化訊息,攜帶 JxfsLocalDeviceInformation 物件(含裝置服務與客戶端一般資訊、虛擬空間存取權)。此時裝置服務首次接觸真實硬體。
客戶端關閉過程中,核心向所有裝置服務發送關閉訊息:
public void initialize(JxfsLocalDeviceInformation deviceInformation) throws JxfsException
public void shutdown() throws JxfsException
核心發送含 IJxfsEventNotification 型別回調物件的訊息。裝置服務用此發回事件。每個需互動的應用程式各獲一個此類物件,分配控制 ID 並回傳:
public int registerControl(String deviceType, IJxfsEventNotification callback) throws JxfsException
public int deregisterControl(int controlID) throws JxfsException
deviceType 參數含裝置類型(進階開發詳見規格)。反註冊後該回調物件不可再用。
public int open(int controlID) throws JxfsException
public int close(int controlID) throws JxfsException
open 通知可能有操作請求隨之而來,controlID 必須為有效已註冊 ID。close 表示該控制 ID 不再需要操作請求,於 deregisterControl 前發送。
少數不遵循非同步規則的方法,呼叫會阻塞直到授權或逾時:
public boolean claim(int timeout, int controlID) throws JxfsException
public boolean release(int timeout, int controlID) throws JxfsException
前置條件:open 已成功處理。
public void cancel(int identificationID, int controlID) throws JxfsException
停止由 controlID 啟動、以 identificationID 標識的操作。若可能,將硬體恢復操作前狀態。取消請求本身無識別 ID(不可被取消)。
極重要,回傳 JxfsStatus 實例,為非同步規則的另一例外:
public JxfsStatus getStatus(int controlID) throws JxfsException
兩大重點:
JxfsStatus 實例時需同步存取JxfsStatus 為值物件(僅攜帶資料無邏輯),內容可被任何持有參考者修改,故每次呼叫必須回傳新實例,確保服務擁有唯一參考簡易實作範例:
public JxfsStatus getStatus(int controlID) throws JxfsException {
synchronized (getStateMonitor()) {
if (isClosed())
throw new JxfsException(JxfsConst.JXFS_E_CLOSED, "The device service is in state 'closed'.");
final JxfsStatus state = new JxfsStatus();
state.setBusy(isBusy());
state.setClaimed(isClaimed());
state.setClaimPending(isClaimPending());
state.setHardwareError(isHardwareError());
state.setOpen(isOpen());
state.setPowerSave(isPowerSave());
state.setUserActionError(isUserActionError());
return state;
}
}
public JxfsVersion getDeviceServiceVersion(int controlID) throws JxfsException
public String getPhysicalDeviceName(int controlID) throws JxfsException
public String getPhysicalDeviceDescription(int controlID) throws JxfsException
支援多機型時應回報實際配置。
public JxfsVersion getDeviceFirmwareVersion(int controlID) throws JxfsException
public JxfsVersion getRepositoryFirmwareVersion(int controlID) throws JxfsException
public int getFirmwareStatus(int controlID) throws JxfsException
public boolean updateFirmware(int controlID) throws JxfsException
不支援時拋出 JXFS_E_NOT_SUPPORTED。getFirmwareStatus 比較版本回報哪個較新。實際更新在 updateFirmware 處理(非同步但無識別 ID)。須妥善文件化 J/XFS 伺服器上用於韌體管理的鍵值,避免資料意外覆寫。
public boolean isPowerSaveModeSupported(int controlID) throws JxfsException
public int wakeUpFromPowerSave(int controlID) throws JxfsException
硬體支援低耗能模式時回傳 true,狀態可透過 getStatus 取得。核心發送 wakeUpFromPowerSave 喚醒硬體。
public void connectionFailure(int controlID)
連線遺失時,裝置服務必須移除該控制 ID 的獨佔存取、設狀態為「關閉」、反註冊回調物件。
IJxfsBaseService 中唯一直接使用硬體功能的操作,屬例外。若硬體提供 J/XFS 標準未涵蓋功能,可用此操作封裝資訊。命令值需大於 JxfsConst.JXFSDIRECTIO_OFFSET,參數藏於 JxfsType 子類物件。理想情況不應支援,因損失可移植性,典型實作直接拋出 JXFS_E_NOT_SUPPORTED。
各硬體類型功能由獨立 Java 介面宣告。開發新裝置服務時,同時實作 IJxfsBaseService 與對應硬體類型介面。不想支援的功能可拋出 JXFS_E_NOT_SUPPORTED。例:印表機介面 IJxfsPrinterService 含 resetPrinter,實作時將重設硬體程式碼置於此方法。
FDI for J/XFS 是 J/XFS 核心的參考實作,可從 J/XFS 論壇免費下載。除實作標準規格,還包含許多便利開發的工具與支援類。
ZIP 檔包含五大文件來源:
與裝置服務開發相關的套件層次:
com.jxfs.control.cdr
com.jxfs.control.msd
com.jxfs.control.pin
com.jxfs.control.ptr
com.jxfs.control.tio
裝置操作所需類別定義於 J/XFS 標準中。附加套件:
com.jxfs.events:所有事件類別(含 JxfsException)com.jxfs.forum.support:輔助便利類別com.jxfs.general:核心類別與介面 (JxfsConst, JxfsLocalDeviceInformation, JxfsMediaStatus, JxfsStatus, JxfsThresholdStatus, JxfsType, JxfsVersion)com.jxfs.service:最重要,含 IJxfsBaseService 及所有裝置服務介面各裝置類型的抽象超類:
com.jxfs.service.alm
com.jxfs.service.cdr
com.jxfs.service.msd
com.jxfs.service.pin
com.jxfs.service.ptr
com.jxfs.service.tio
內建日誌/追蹤機制,資訊發送給 JxfsLogger (透過 getReference() 取得)。
origin 字串識別,需先 registerModule 註冊,停用前 deregisterModule 反註冊writeErrorLog (需 origin、錯誤碼、擴充錯誤碼、訊息、解決提示、參考 URL)writeLog,建議先用 isLogActive 檢查是否啟用以節省效能使用範例:
final String origin = "developerWorksDeviceService";
JxfsLogger.getReference().registerModule(origin, "J/XFS device service for IBM developerWorks.");
// ...
// log
JxfsLogger.getReference().writeErrorLog(this, origin, 0, 0,
"This is an error log entry.", "Hint to solve the problem.",
"Find more information at https://www.ibm.com/java.");
// ...
// trace
if (JxfsLogger.getReference().isLogActive(origin, 101))
JxfsLogger.getReference().writeLog(this, origin, 101, "J/XFS trace entry.");
// ...
JxfsLogger.getReference().deregisterModule(origin);
J/XFS 規格定義裝置介面,FDI 提供對應 Java 類別檔。除介面外,FDI 為每種裝置類型提供抽象超類別。建議建立適當子類別實作裝置服務,確保規格擴充時新方法自動納入核心新版本,預設拋出 JXFS_E_NOT_SUPPORTED。舊規格開發的服務繼承新方法仍可與新核心協作,新功能可覆寫繼承方法加入。
範例:日誌印表機服務類別
import com.jxfs.service.*;
import com.jxfs.service.ptr.*;
// ... import any packages needed
public class DeveloperWorksJournalPrinter extends AJxfsJournalPrinterService
implements IJxfsBaseService, IJxfsPrinterService {
// implementation of the device service ...
}
com.jxfs.forum.support 套件提供少量開發輔助類:
IJxfsServiceJob 的獨立類別(「作業」物件),加入佇列控制物件。支援主動模式(自有控制執行緒連續執行)與被動模式(自建控制執行緒呼叫 getNextJob 取得下一作業)OpenJob、CloseJob、ClaimJob、ReleaseJob本系列旨在作為 J/XFS 平台與其參考實作 (FDI for J/XFS) 的優質介紹。理解基本概念後,實作並不困難。希望能準備並鼓勵您開發自有 J/XFS 裝置服務,滿足銀行業應用供應商需求,擴展 J/XFS 與 Java 平台的應用。