簡介
IBM WebSphere Application Server V7 中的 IBM WebSphere MQ 消息提供程 序提供對基於 Java™ 通道出口的完整支持。道出口是運行在 IBM® WebSphere® MQ 通道生命周期中被指定點上的用戶代碼。通道出口有許多可能的用法,包括審計、安全、壓 縮、轉換等等。
之前的 WebSphere Application Server 版本中,通道出口沒有得到完整的支持,必須通過 定制屬性配置。在 WebSphere Application Server V7 中,通道出口可以使用管理控制台或管 理命令配置連接工廠和激活規范指定,也可以使用客戶端通道定義表 (CCDT) 條目指定。
通道出口類型
WebSphere MQ 消息提供程序支持三種不同的通道出口:安全、發 送和接受出口。每種出口類型都在客戶端連接通道的不同時點調用,如表 1 所示。
表 1. 通道出口調用時間 出口類型 何時調用構造函數 安全出口 通道初始化時。
如果從安裝在服務器連接 通道的安全出口接收安全流。
發送出口 通道初始化時。
在任何數據發送到隊列管理程序之前。
接收出口 通 道初始化時。
從隊列管理程序收到數據之後,且在將該數據傳遞到應用程序之前。
發送和接收出口支持鏈;即可以對 WebSphere MQ 消息提供程序資 源指定多個發送和接收出口。如果使用鏈,則調用鏈中的第一個出口,返回的數據將傳遞到鏈 中的下一個出口。在調用所有出口之前該操作將一直持續,然後將數據發送到相應的隊列管理 程序或客戶端。
正如上文所述,如果相應服務器連接通道上的安全出口發送了一個安全 流,那麼僅調用安全出口 WebSphere MQ 消息提供程序上安裝的安全出口。由於僅在通道啟動 時調用安全出口,安全出口對於執行只需執行一次的功能非常理想。顧名思義,這通常意味著 執行驗證。圖 1 顯示啟動驅動時將調用的安全出口。
圖 1. 安全出口調用
在通過隊列 管理程序發送和接收數據之前,應該分別調用發送方和接收方通道出口。這些出口類型常見的 用法包括:計算發送或接收數據的數量,或者執行某種形式的數據轉化,比如壓縮。如果有必 要,可以在通道的任何一端安裝互補的發送和接收出口。例如,如果使用出口執行數據壓縮, 那麼在執行解壓縮時在兩端都需要接收出口。如圖 2 所示。
圖 2. 互補的發送和接收 出口
通道出口使 用限制
使用通道出口和 WebSphere MQ 消息提供程序時有一些必須注意的限制:
為了利用通道出口,WebSphere MQ 消息提供程序連接工廠和激活規范的傳輸類型必須 為 client 或 bindings-then-client。這是因為只有在使用客戶端連接通道連接到 WebSphere MQ 隊列管理程序或隊列共享組時才使用通道出口程序。如果選擇了 bindings-then-client 傳 輸模式,那麼只有在綁定模式連接失敗時才使用通道出口。
除了 Java 之外, WebSphere MQ 支持以各種編程語言編寫的通道出口,包括 C 和 C++。但是,WebSphere MQ 消 息提供程序僅支持基於 Java 的通道出口,因此不能使用 C 和 C++ 通道出口。
使用通 道出口的 WebSphere MQ 消息提供程序資源根據第一次使用資源的應用程序類路徑加載通道出 口類。如果 IBM 沒有推薦其他資源,請確保遵守有關指定加載通道出口資源地點的 WebSphere MQ 文檔。有關帶有 WebSphere MQ 消息提供程序的通道出口的類加載考慮事項,將在本文的下 一節介紹。
編寫簡單的通道出口
創建使用 WebSphere MQ 消息提供程序的通道 出口需要實現一個或多個 Java 通道出口界面。有兩個接口集:一個為 WebSphere MQ V7 引用 ,提供增強的性能和功能;另一個從 WebSphere MQ V5 開始可用。兩個接口都可以用於 WebSphere MQ 消息提供程序,但是本文中的示例將僅使用新接口。
不管使用的是哪種 接口集,它們都遵從相同的模式。一個接口提供給每種通道出口,每個接口都提供一個需要實 現的方法。接口和方法簽名如表 2 所示。
表 2. 通道出口接口定義 接口類型 接口名稱 接口方法 新發送 出口 com.ibm.mq.exits.WMQSendExit public ByteBuffer channelSendExit(MQCXP channelExitParms, MQCD channelDefinition, ByteBuffer agentBuffer) 新接收出口 com.ibm.mq.exits.WMQReceiveExit public ByteBuffer channelSendExit (MQCXP channelExitParms, MQCD channelDefinition, ByteBuffer agentBuffer) 新安全出口 com.ibm.mq.exits.WMQSecurityExit public ByteBuffer channelReceiveExit( MQCXP channelExitParms, MQCD channelDefinition, ByteBuffer agentB 原來的發送出口 com.ibm.mq.MQSendExit public byte[] sendExit(MQChannelExit channelExitParms, MQChannelDefinition channelDefinition, byte[] agentBuffer) 原來的接收出口 com.ibm.mq.MQReceiveExit public byte[] receiveExit(MQChannelExit channelExitParms, MQChannelDefinition channelDefinition, byte[] agentBuffer) 原來的安全出口 com.ibm.mq.MQSecurityExit public byte[] securityExit(MQChannelExit channelExitParms, MQChannelDefinition channelDefinition, byte[] agentBuffer)
如果要使用新樣式出口,則在編寫和編譯通道出口時需要 com.ibm.mq.jmqi.jar 副本,如果要使用較舊樣式出口,那麼需要 com.ibm.mq.jar 副本。這 些 jar 文件可以直接從 <WAS_INSTALL_ROOT>/lib/WMQ/ra/ 獲取,也可以從 WebSphere MQ 安裝中獲取。
每個出口最簡單的形式是使用出口接口方法返回傳入的 agentBuffer 參數。清單 1 中展示的類提供了這三種出口最基本的實現。本文的剩下部分將引用該示例。
清單 1
package com.ibm.ce;
<IMPORTS REMOVED>
/**
* A simple channel exit that provides an implementation of a send,
* receive and security exit.
*/
public class LoggingChannelExit implements WMQSendExit, WMQReceiveExit, WMQSecurityExit
{
/**
* Send exit implementation.
*/
public ByteBuffer channelSendExit(MQCXP channelExitParms,
MQCD channelDefinition,
ByteBuffer agentBuffer)
{
System.out.println("Send Exit Invoked");
return agentBuffer;
}
/**
* Receive exit implementation.
*/
public ByteBuffer channelReceiveExit(MQCXP channelExitParms,
MQCD channelDefinition,
ByteBuffer agentBuffer)
{
System.out.println("Receive Exit Invoked");
return agentBuffer;
}
/**
* Security exit implementation.
*/
public ByteBuffer channelSecurityExit(MQCXP channelExitParms,
MQCD channelDefinition,
ByteBuffer agentBuffer)
{
System.out.println("Security Exit Invoked");
return agentBuffer;
}
}
創建和安裝通道出口時,每個定義的出口 最多可以傳入 32 個字符的數據,可以用於配置目的。在新的樣式接口中,可以通過 MQCXP.getUserData() 方法訪問該數據,該方法將返回一個字符串。下一節將展示如何設置這 個出口數據。
在 WebSphere 消息提供程序資源上配置通道出口
用來指定特定 WebSphere MQ 消息提供程序運行哪個通道出口的步驟取決於該資源是否基於 CCDT 中的信息。 如果資源以 CCDT 為基礎,那麼將在創建 CCDT 時制定通道出口信息。圖 3 展示了如何使用 WebSphere MQ Explorer 工具向客戶端連接通道定義添加上文定義的簡單通道出口程序。(有 些用戶數據已經在此指定,但在本例中,通道出口實現不使用它)。
圖 3. 在 CCDT 上 配置通道出口
如果向非 CCDT 定義的 WebSphere MQ 消息提供程序資源添加通道出口,那麼可以使用管理 控制台或 wsadmin 命令行工具。
如果使用管理控制台:
登錄管理控制台並導航 到基於非 CCDT 的相關 WebSphere MQ 消息提供程序激活規范或連接工廠。
如圖 4 所 示,單擊 Additional 屬性下方面板右邊的 Client transport properties 鏈接。
圖 4. 客戶端傳輸屬性
在相關的 通道出口字段,輸入通道出口類的完整名稱,包括包。在本例中,輸入 com.ibm.ce.LoggingChannelExit。如果需要多個發送和接收出口,則使用逗號分隔名稱。
在相關用戶數據字段輸入任何用戶數據。如果定義了多個通道出口,則可以定義多個以 逗號分隔的用戶數據集。如果定義的通道出口多於用戶數據,則剩余通道出口的用戶數據將為 空字符串。類似地,如果輸入兩個逗號作為用戶數據,那麼列表中該位置的通道出口將獲取由 空白字符串組成的用戶數據。
單擊 OK 保存更改。
在應用服務器環境資源中使 用支持通道出口的資源
編寫企業應用程序使用配置為使用通道出口的 WebSphere MQ 消 息提供程序資源時,您必須小心確保消息提供程序可以加載通道出口實現。本節介紹如何在應 用程序服務器環境中實現這一點,下一節將解釋如何讓通道出口實現類可用於應用程序客戶端 環境。
如果 WebSphere MQ 消息提供程序激活規范或連接工廠的實例已經使用通道出口 配置,那麼在創建激活規范或實現類時,消息提供程序將嘗試使用映像加載通道出口實現類。 為了實現這一點,通道出口實現類必須可用於 WebSphere MQ 消息提供程序運行時使用的類加 載程序。可以用三種方式實現:
最簡單的方法是讓通道出口類可用於整個應用服務器運 行時加載,向應用服務器類路徑添加類即可實現。但是,不建議使用該方法,因為它可能導致 加載類的實際位置不明確,尤其是在一個應用服務器中使用多個版本的相同類時。
第二 種方法是,每個應用程序可以使用其內部綁定的通道出口類副本進行部署(部署為 JAR 或一個 或多個其他類文件。如果只有一個應用程序使用通道出口配置的 WebSphere MQ 消息提供程序 連接工廠或激活規范,那麼這種方法更加合理。但是,在大部分情況下(尤其是通道出口廣泛 使用時),該方法不是很合適,因為它增加了應用程序的大小,並且使通道出口實現升級時間 過長,且容易出錯。
第三種常用的方法是將通道出口實現作為共享庫提供,使需要的應 用程序能夠訪問它們。這種方法意味著應用程序開發人員不需要意識到使用通道出口,此外, 它有助於防止類路徑過於臃腫,在通道出口實現更改時還提供了一個簡單的升級戰略。在 WebSphere Application Server 中使用標准庫的辦法由幾種:您可以使用共享庫引用,或者使 用 WebSphere Application Server V7 中引入的新資產支持。
當企業應用程序使用配 置為使用通道出口的 WebSphere MQ 消息提供程序資源時,通道出口實現不可用於應用程序類 路徑,結果生成一個帶有 2406 錯誤代碼的 MQException。清單 2 展示了一個發生這種情況的 示例。在該清單中,應用程序嘗試使用配置為使用 LoggingChannelExit 類作為發送出口的 WebSphere MQ 消息提供程序工廠。當在應用服務器環境中運行時,這些異常一般包含在一個或 多個 First Failure Data Capture (FFDC) 記錄中。
清單 2
com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2'
('MQCC_FAILED') reason '2406' ('MQRC_CLIENT_EXIT_LOAD_ERROR').
at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:206)
... 30 more
Caused by: com.ibm.mq.jmqi.JmqiException: CC=2;RC=2406;AMQ9535: User exit not valid.
[1=com.ibm.ce.LoggingChannelExit]
at com.ibm.mq.jmqi.remote.internal.RemoteExitChain.loadJavaExitByName
(RemoteExitChain.java:1858)
at com.ibm.mq.jmqi.remote.internal.RemoteExitChain.loadByName
(RemoteExitChain.java:1816)
at com.ibm.mq.jmqi.remote.internal.RemoteExitChain.parseSendReceiveExitsChain
(RemoteExitChain.java:1655)
at com.ibm.mq.jmqi.remote.internal.RemoteExitChain.loadExits
(RemoteExitChain.java:824)
at com.ibm.mq.jmqi.remote.internal.RemoteHconn.initSendReceiveExits
(RemoteHconn.java:683)
at com.ibm.mq.jmqi.remote.internal.system.RemoteConnectionPool.getConnection
(RemoteConnectionPool.java:295)
at com.ibm.mq.jmqi.remote.internal.RemoteFAP.jmqiConnect(RemoteFAP.java:1371)
at com.ibm.msg.client.wmq.internal.WMQConnection.<init> (WMQConnection.java:331)
... 29 more
Caused by: java.lang.ClassNotFoundException: com.ibm.ce.LoggingChannelExit
at java.net.URLClassLoader.findClass(URLClassLoader.java:419)
at java.lang.ClassLoader.loadClass(ClassLoader.java:643)
at java.lang.ClassLoader.loadClass(ClassLoader.java:609)
at com.ibm.mq.jmqi.remote.internal.RemoteExitChain.loadJavaExitByName
(RemoteExitChain.java:1855)
... 36 more
以下步驟展示了如何 使用共享庫,使企業應用程序可以使用經過通道出口配置的 WebSphere MQ 消息提供程序連接 工廠或激活規范。
從 WebSphere Application Server 管理控制台導航到 Applications => Application Types => WebSphere enterprise applications,然後 單擊將使用支持通道出口的 WebSphere MQ 消息提供程序資源的應用程序。
如圖 5 所 示,單擊 References 區域的 Shared library references。選擇將使用 WebSphere MQ 消息 提供程序資源的應用程序模塊,然後單擊 Reference shared libraries 按鈕。
圖 5. 定制 屬性
如果沒有定 義相關的共享庫,那麼單擊 New 按鈕(圖 5 圓圈處)。這將顯示一個面板,用於輸入可以用 來定位出口庫的類路徑信息。輸入信息並單擊 OK。
從 Available 列表中選擇庫,然後 使用箭頭按鈕將它移動到 Selected 列表(圖 6)。單擊 OK,再單擊 OK。
圖 6. 共享庫映 射
最後,保 存更改並重啟應用服務器。
當再次運行企業應用程序時,它應該能夠使用支持通道出口 的 WebSphere MQ。例如,使用配置為使用 LoggingChannelExit 類作為發送出口的 WebSphere MQ 消息提供程序連接工廠時要謹慎。這將輸出清單 3 中所示的應用服務器日志。
清單 3. LoggingChannelExit 輸出
[05/10/08 16:06:02:736 BST] 00000010 SystemOut O Send Exit Invoked
[05/10/08 16:06:02:861 BST] 00000010 SystemOut O Send Exit Invoked
[05/10/08 16:06:02:877 BST] 00000010 SystemOut O Send Exit Invoked
[05/10/08 16:06:02:877 BST] 00000010 SystemOut O Send Exit Invoked
[05/10/08 16:06:02:877 BST] 00000010 SystemOut O Send Exit Invoked
[05/10/08 16:06:02:877 BST] 00000010 SystemOut O Send Exit Invoked
[05/10/08 16:06:02:877 BST] 00000010 SystemOut O Send Exit Invoked
[05/10/08 16:06:02:986 BST] 00000010 SystemOut O Send Exit Invoked
在應用程序客戶端環境中使用支持通道出口的資源
在客戶端環境中使用 WebSphere MQ 消息提供程序連接工廠時,類加載考慮事項比服務器環境要簡單地多。通道出口類或 JAR 要麼 是客戶端應用程序的一部分,要麼調整客戶端應用程序類路徑,使其包含對外部通道出口類或 JAR 的引用。這種情況下的最佳方法是使用 launchClient 命令的 -CCclasspath 屬性引用外 部 JAR 或類集合,如清單 4 所示。
清單 4. 使用 launchClient 指定類路徑信息
C:\was7gm\profiles\AppSrv01\bin>launchClient.bat client.ear - CCclasspath=c:\exits\
2809 m1
IBM WebSphere Application Server, Release 7.0
Java EE Application Client Tool
Copyright IBM Corp., 1997-2008
WSCL0012I: Processing command line arguments.
WSCL0013I: Initializing the Java EE Application Client Environment.
[05/10/08 16:18:00:002 BST] 00000000 W UOW=null source=com.ibm.ws.ssl.config.SSLConfig
org=IBM prod=WebSphere component=Application Server thread=[P=879377:O=0:CT]
CWPKI0041W: One or more key stores are using the default password.
WSCL0035I: Initialization of the Java EE Application Client Environment has completed.
WSCL0014I: Invoking the Application Client class Main
Send Exit Invoked
Send Exit Invoked
Send Exit Invoked
結束語
WebSphere Application Server V7.0 中的 IBM WebSphere MQ 消息提供程序使部署直接利用 WebSphere MQ 企業消息功能的 Java EE 應用程 序成為可能。本文概述了通道出口、介紹了它們的好處和使用限制,並提供一些演示如何在應 用服務器和應用程序客戶端環境中實現它們的示例。