JMS、XML和異構(gòu)企業(yè)
--使用JMS和XML來促進(jìn)企業(yè)應(yīng)用的互操作性
Todd Sundsted
ComFrame Software 公司
2000 年 4 月
如今,大多數(shù)計算環(huán)境更多地是由不同平臺組成,而不是固守任何一個平臺。 Java 消息服務(wù) (JMS) ,與可擴展標(biāo)記語言 (XML) 一起,滿足了這種異構(gòu)環(huán)境集成的愿望。這篇文章演示了如何使用 JMS 來創(chuàng)建基于 XML 的消息并將這些消息同樣分發(fā)到 Java 和非 Java 應(yīng)用程序。
經(jīng)過幾年構(gòu)建、擴展和維護(hù)龐大的分布式應(yīng)用之后,程序員逐步體會到平臺無關(guān)的行為和平臺無關(guān)的數(shù)據(jù)的好處了。
Java 編程語言已經(jīng)向滿足平臺無關(guān)的行為(盡管例如 TCL 這樣的腳本語言在一段或更長時間內(nèi)還受到關(guān)注)的需要邁進(jìn)了一步。而且 XML(可擴展標(biāo)記語言)正在成為開放、平臺無關(guān)的數(shù)據(jù)解決方案的中堅力量。
本文演示了在與 Java 消息服務(wù) (JMS) 一起使用的情況下,XML 如何滿足平臺無關(guān)的數(shù)據(jù)的愿望。
消息傳遞將它們聯(lián)系在一起
JMS 為消息服務(wù)定義了通用 Java 語言接口。它支持最常見的消息傳遞模型(包括發(fā)布/訂閱和點到點)。
首先將平臺無關(guān)的數(shù)據(jù)與 Java 技術(shù)放在一段文字中提及看起來比較奇怪。然而,既然JMS是一種基于 Java(因此是平臺無關(guān)的)的技術(shù),我們?yōu)槭裁丛谑褂?JMS 時需要平臺無關(guān)的數(shù)據(jù)呢?
答案來源于經(jīng)常使用消息傳遞的環(huán)境。消息傳遞的一個最大優(yōu)點體現(xiàn)在應(yīng)用集成領(lǐng)域。被集成的應(yīng)用多半不全是 Java 應(yīng)用。
在這種情況下 JMS 非常理想,因為它是一種接口規(guī)范 -- 而不是實現(xiàn)。這意味著JMS位于已經(jīng)有了相當(dāng)?shù)膽?yīng)用現(xiàn)有技術(shù)的上面一層。(當(dāng)然,所有 Java 實現(xiàn)也能利用這種 JMS 和 XML 的解決方案。)
圖 1. 位于專有消息服務(wù)上層的 JMS
圖 1 說明了這樣一種環(huán)境。非 Java 應(yīng)用與專用消息服務(wù)直接進(jìn)行通信。Java 應(yīng)用通過 JMS 通信。每一樣是無縫的,對嗎?
但不完全是。數(shù)據(jù)仍然是一個需要解決的問題。
平臺無關(guān)的數(shù)據(jù)解決了問題
請考慮 JMS 的五種消息類型。JMS 提供了三種結(jié)構(gòu)化或半結(jié)構(gòu)化的消息類型(MapMessage、ObjectMessage 和 StreamMessage)以及兩種非結(jié)構(gòu)化的或自由格式的消息類型(TextMessage 和 BytesMessage)。
結(jié)構(gòu)化的消息格式只代表了眾多處理結(jié)構(gòu)化數(shù)據(jù)方法中的少數(shù)幾種(只有映射表、序列化對象和數(shù)據(jù)元素流是直接表示的)。更重要的是,它們引發(fā)了與非 Java 應(yīng)用交互操作的問題。轉(zhuǎn)換或映射,特別是在轉(zhuǎn)換涉及到序列化的類時是如何實現(xiàn)的呢?
非結(jié)構(gòu)化的消息格式似乎能夠更好地進(jìn)行交互操作,但這僅僅是因為它們在消息上很少利用結(jié)構(gòu)。然而這個很小的便利卻為每個接受者加重了語法分析和確認(rèn)的負(fù)擔(dān)。
XML 減輕了這種負(fù)擔(dān)。它為豐富的功能性數(shù)據(jù)結(jié)構(gòu)提供了清晰的標(biāo)準(zhǔn)化途徑,并通過越來越多的工具來支撐它,這些工具是用來執(zhí)行語法分析和確認(rèn)這些費力的工作的。
通過在環(huán)節(jié)中使用 XML,每一樣都是無縫的。
代碼
以下兩段代碼說明了如何傳送 XML 消息。因為 XML 基本上是文本,所以它在 TextMessage 實例的主體中傳送。兩個示例都假設(shè)有 XMLValidator 類存在。這個類是許多基于 Java 的 XML 語法分析和確認(rèn)工具之一的一個簡單封裝。
發(fā)送方是非常簡單的。清單 1 中的代碼說明了如何找到 Queue 和 QueueConnectionFactory、如何創(chuàng)建連接和會話、如何將 XML 填充到 TextMessage,以及如何將消息發(fā)送給隊列。
清單 1. 發(fā)送 XML 消息的示例
public
static
void
send(
String stringQueue,
String stringQueueConnectionFactory,
XMLValidator xmlvalidator,
String stringXML)
throws
NamingException,
JMSException,
XMLValidationException {
//在一個名為JNDI和目錄服務(wù)中查找Queue 和 QueueConnection 類廠,或者直接創(chuàng)建它們
Context context = new InitialContext();
Queue queue = null;
queue = (Queue)context.lookup(stringQueue);
QueueConnectionFactory queueconnectionfactory = null;
queueconnectionfactory =
(QueueConnectionFactory)context.lookup(stringQueueConnectionFactory);
QueueConnection queueconnection = null;
queueconnection = queueconnectionfactory.createQueueConnection();
QueueSession queuesession = null;
queuesession =
queueconnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
// 創(chuàng)建 QueueSender.
QueueSender queuesender = null;
queuesender = queuesession.createSender(queue);
//首先在XML中創(chuàng)建一個TextMessage,如果XML是通過用戶輸入創(chuàng)建的,那么驗證XML的合法性是非常必要的。然后發(fā)送它。
xmlvalidator.validate(stringXML);
TextMessage textmessage;
textmessage = queuesession.createTextMessage();
textmessage.setText(stringXML);
queuesender.send(textmessage);
}
在接收方有許多事要做(見清單 2)。接收了 TextMessage 后,代碼抽取 XML 并驗證它。確認(rèn)過程根據(jù)文檔類型定義 (DTD) 來檢查 XML,DTD 可以是 XML 的一部分,也可以在它的外部。
如果 DTD 是在外部存儲的,您很可能要面臨創(chuàng)建和維護(hù)企業(yè)范圍的 DTD 資源庫。資源庫嚴(yán)格定義了共同參加的企業(yè)應(yīng)用程序可以交換的消息的結(jié)構(gòu)。
現(xiàn)在,TextMessage 成為非常有條理、定義明確的消息的“載體”,Java 和非 Java 應(yīng)用程序都可以理解。
清單 2. 接收 XML 消息的示例
public
static
String
receive(
String stringQueue,
String stringQueueConnectionFactory,
XMLValidator xmlvalidator)
throws
NamingException,
JMSException,
XMLValidationException {
//在一個名為JNDI和目錄服務(wù)中查找Queue 和 QueueConnection 類廠,或者直接創(chuàng)建它們 Context context = new InitialContext();
Queue queue = null;
queue = (Queue)context.lookup(stringQueue);
QueueConnectionFactory queueconnectionfactory = null;
queueconnectionfactory =
(QueueConnectionFactory)context.lookup(stringQueueConnectionFactory);
QueueConnection queueconnection = null;
queueconnection = queueconnectionfactory.createQueueConnection();
QueueSession queuesession = null;
queuesession =
queueconnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
// 創(chuàng)建 QueueReceiver.
QueueReceiver queuereceiver = null;
queuereceiver = queuesession.createReceiver(queue);
//接受一個TextMessage, 提取其中的XML,
//并在返回之前驗證它。在驗證XML和返回之前,將XML轉(zhuǎn)換成一個DOM數(shù)或者其它的表示方法也是可以的。
TextMessage textmessage;
textmessage = (TextMessage)queuereceiver.receive();
String stringXML = textmessage.getText();
xmlvalidator.validate(stringXML);
return stringXML;
}
結(jié)束語
似乎大家有了共識,認(rèn)為面向消息的中間件(JMS 是其一部分)和 XML 屬于一起的。我希望我的論述為這個提法增添了說服力。它并不是那么出人意外的。XML 文檔是真實的消息 -- 它們是結(jié)構(gòu)化的,但仍具有相當(dāng)?shù)撵`活性。另外,MOM,和 XML 一樣,擅長集成異構(gòu)應(yīng)用程序。
參考資料
了解有關(guān) Java Message Service API 的信息。
在 JMS frequently asked questions 清單中查找問題的答案。
關(guān)于作者
自從計算機有了方便的臺式機型以來,Todd Sundsted 就在編寫程序。盡管他最初時對使用 C++ 構(gòu)建分布式應(yīng)用程序感興趣,但在 Java 成為構(gòu)建分布式應(yīng)用程序的首選后,Todd 就轉(zhuǎn)向了 Java 編程語言。除了寫作外,Todd 還是 ComFrame Software 公司的 Java 設(shè)計師??梢酝ㄟ^ tsundsted@comframe.com 與 Todd 聯(lián)系。