![]() | ![]() |
![]() |
級別: 初級 Sing Li (westmakaha@yahoo.com), 作者 2005 年 8 月 08 日 Apache Geronimo 是具有開放架構(gòu)且功能強大的開源 Java? 2 平臺企業(yè)版 (J2EE) 1.4 服務(wù)器容器,可以承載多種現(xiàn)有的服務(wù)器和服務(wù)。ActiveMQ 是一個經(jīng)驗證的最佳開源 Java 消息服務(wù) (JMS) 引擎,該引擎還附帶一個精巧多用的功能和連接選項庫。二者結(jié)合使用時,會發(fā)生奇跡般的效果!Sing Li 將為您介紹這種共存關(guān)系,并提供示例代碼,幫助您開始編寫 JMS 應(yīng)用程序并立即使用 Geronimo 創(chuàng)建 Message-Driven Beans (MDB)。 JMS API 是 J2EE 平臺的整體組成部分,允許在松耦合組件之間進行基于消息的通信。通過客戶機、Web 層組件、業(yè)務(wù)層企業(yè) JavaBeans (EJB) 和企業(yè)信息系統(tǒng) (EIS) 層服務(wù)之間的 J2EE 堆??梢园l(fā)送和接收消息。這些消息是異步發(fā)送的,消息發(fā)出后,發(fā)送方能夠繼續(xù)使用其他應(yīng)用程序邏輯,消息代理 (message broker) 負責代表發(fā)送方傳遞消息。消息可以在特定的端點(發(fā)送方和接收方)之間發(fā)送和接收,或通過公共/訂閱交互模式在生產(chǎn)者與消費者之間進行匿名傳遞。在 J2EE 架構(gòu)內(nèi)部,通過 JMS 進行通信的組件可以使用容器提供的安全和事物處理功能。Geronimo 通過集成名為 ActiveMQ 的開源項目來支持這個重要的 API。 本文將探討如何在 Geronimo 中集成 ActiveMQ。您將了解 Geronimo 如何從集成中受益,以及 ActiveMQ 功能如何通過駐留在 Geronimo 內(nèi)部得到增強。可以從本文下載一個操作示例,該示例揭示了如何對通過 JMS 進行通信的客戶機和組件進行編碼。另一個示例顯示了如何在 Geronimo 內(nèi)部創(chuàng)建萬能的 MDB。 在 JMS 術(shù)語中,ActiveMQ 是一個成熟而又功能豐富的 JMS 服務(wù)器或消息代理。位于 Codehaus(請參閱 參考資料)中的 ActiveMQ 支持許多不同的傳輸(如 TCP、SSL、UDP、多點傳送、內(nèi)部 JVM 和 NIO)和客戶機交互(如推、拉和發(fā)行/訂閱)。以一定規(guī)模的現(xiàn)有用戶為基礎(chǔ),ActiveMQ 服務(wù)器完全可以獨立工作,而不依賴任何容器(J2EE 或其他容器),它還可以與 J2EE 服務(wù)器主機(如 Geronimo)結(jié)合使用。 當 ActiveMQ 在 Geronimo 中運行時,會對 MDB 提供支持,即使用 JMS 消息的 EJB。JMS 的異步特性允許容器隨需應(yīng)變地激活 MDB,代表客戶機執(zhí)行 J2EE 服務(wù)器內(nèi)的任務(wù)。Geronimo 會從 ActiveMQ 的富客戶機支持中得到很大好處。與會話或?qū)嶓w EJB 不同,MDB 不是通過嚴格的 EJB 界面調(diào)用的。相反,客戶機只需將 JMS 消息發(fā)送到目標,便可以調(diào)用 MDB 服務(wù)。這樣大大簡化了使用基于 EJB 服務(wù)的客戶機的編碼過程。事實上,Geronimo 繼承了向非 J2EE 客戶機提供服務(wù)的功能 —— 這些功能受到獨立 ActiveMQ 服務(wù)器的支持。
ActiveMQ 消息代理被設(shè)計成可嵌入式的。Geronimo 充分利用了這一功能。通過提供包裝已嵌入消息代理的 GBean 容器,可以創(chuàng)建 ActiveMQContainerGBean。ActiveMQ 消息代理的其他組件也被包裝到 GBeans 中,您很快就會看到這種情形。圖 1 說明了 ActiveMQContainerGBean 是如何嵌入 ActiveMQ 消息代理的。 圖 1. ActiveMQContainerGBean ![]() 通過將 ActiveMQ 消息代理包裝到 GBean 中,該代理的生命周期由 Geronimo 管理。具體地說,您可以使用 Geronimo 部署程序和管理工具部署、啟動和管理 ActiveMQ 消息代理實例。消息代理的可配置屬性是作為 GBean 屬性公開的。在 圖 1 中,ActiveMQContainerGBean 對 ActiveMQ 消息代理進行了包裝,并提供了生活周期管理和配置服務(wù)。除了提供生命周期和配置支持外,Geronimo 還對持久消息提供持久支持。目前的 ActiveMQ 服務(wù)器配置使用默認 Derby RDBMS 實例來處理持久消息。 由 Geronimo 提供的默認 J2EE 服務(wù)器集集成了一個 ActiveMQ 消息代理實例。這個集合在服務(wù)器啟動時啟動消息代理,通常使用的命令行如下:
要查看此實例是如何配置的,可以檢查 Geronimo 源代碼分配的計劃目錄中的 system-activemq-plan.xml 部署計劃。您將看到 ActiveMQContainerGBean 和其他相關(guān)的 ActiveMQ 組件是如何配置的。清單 1 顯示了此部署計劃中的相關(guān)字段。 清單 1. 在 system-activemq-plan.xml 部署計劃中配置 ActiveMQContainerGBean
在 清單 1 中,第一個 GBean 對 ActiveMQ 消息代理進行設(shè)置。該 GBean 的屬性引用了一個永久適配器并指向第二個 GBean。第二個 GBean 包裝了一個 ActiveMQ 內(nèi)存緩存的實例,并且它引用了 ActiveMQ 的永久組件,以便支持永久性的信息。第三個 GBean 連接 JDBC 數(shù)據(jù)源,以便提供永久支持,并指向 SystemDatasource —— 一個 Derby RDBMS 實例。最后兩個 GBeans 設(shè)置了以下兩個傳輸,用于訪問消息代理:
如果需要更改此實例的配置,可以修改這個 system-activemq-plan.xml 文件,然后重新部署 org/apache/geronimo/ActiveMQServer 配置。
利用 JMS 的應(yīng)用程序組件(如 servlet、JSP 或 EJB)必須通過實現(xiàn) JMS API 的庫才能訪問消息代理。這個 API 是由 Geronimo 提供的。若要用某種方法實現(xiàn)這個可以與任何 JMS 提供者(如消息代理)一起使用的 API,那么 Geronimo 必須支持 J2EE Connector (JCA) 1.5 規(guī)范。JCA 1.5 規(guī)范詳細說明了應(yīng)用服務(wù)器 (Geronimo) 和資源適配器 (RA) 之間所需的契約 —— 由 ActiveMQ 提供的一個驅(qū)動程序。(請參閱 參考資料,閱讀關(guān)于 JCA 1.5 的文章。)Geronimo 中駐留的管理應(yīng)用程序組件只有通過此 RA 才能訪問 ActiveMQ 消息代理。這是 ActiveMQ 提供給表的另一個主要好處 —— 它含有符合 JCA 1.5 且可以與之集成的 RA 實現(xiàn)。圖 2 顯示了符合 ActiveMQ JCA 1.5 的 RA。 圖 2. 符合 ActiveMQ JCA 1.5 的 RA ![]() 在 圖 2 中,可以看到 ActiveMQ RA 通過已定義好的 JCA 1.5 系統(tǒng)契約與 Geronimo 的安全和事物處理系統(tǒng)發(fā)生的交互。ActiveMQ RA 支持出站連接(JMS 向外調(diào)用消息代理)和入站連接(用 ActiveMQ 初始的調(diào)用來調(diào)用 MDB)。對于出站連接,消息發(fā)送應(yīng)用程序可以將提供者(本例中為 ActiveMQ)注冊為分布式事物處理的一部分,也可以包括其他資源管理程序(如 RDBMS)。對于入站連接,一般先通過激活 MDB,Geronimo 才能啟動事物處理。在目前的 JCA 1.5 規(guī)范以及 Geronimo 實現(xiàn)中,入站連接不與容器的安全子系統(tǒng)交互。 WorkManager 契約是 JCA 1.5 的一部分。它允許 RA 向應(yīng)用程序服務(wù)器提交工作,以便于執(zhí)行。這樣允許服務(wù)器 —— Geronimo —— 對符合 RA 的線程管理和工作分配進行控制。對于 ActiveMQ,此功能用于管理入站連接的線程。有關(guān)此功能的更多信息,請參閱“JCA 1.5, Part 3: Message inflow”(developerWorks,2005 年 6 月)。 清單 2 顯示了 system-jms-plan.xml 部署計劃的一個片段。此計劃對 RA 實例的組件進行了配置,正如 JCA 1.5 規(guī)范中部署描述符詳細描述的那樣。就 ActiveMQ RA 而言,這些組件包括 RA 實現(xiàn)類、出站連接工廠、主題和隊列(管理的對象)。 清單 2 中部署計劃的配置如下:
如果需要修改這個 JMS RA 的默認配置(例如,添加其他隊列),則需要在 system-jms-plan.xml 部署計劃中進行適當?shù)母?。要使任何更改有效,首先要取消?org/apache/geronimo/SystemJMS 配置的部署,然后,重新部署該配置。對于其他配置 ActiveMQ RA 實例的部署計劃,請參閱側(cè)欄 部署 ActiveMQ RA。
Geronimo 客戶機應(yīng)用程序容器支持的 J2EE 應(yīng)用程序客戶機可以訪問 ActiveMQ 消息代理。圖 3 顯示了一些客戶機訪問配置。 圖 3. J2EE 和非 J2EE 客戶機對消息代理的訪問 ![]() 圖 3 中上部的配置顯示 J2EE 客戶機應(yīng)用程序?qū)蛻魴C范圍內(nèi)部署的 RA 的訪問情況。這個 RA 實例被配置成可以訪問服務(wù)器端的消息代理。圖 3 中的第二個配置顯示另一個 J2EE 客戶機,該客戶機附帶一個客戶機范圍內(nèi)部署的 RA,但是也可以訪問在客戶機上部署的消息代理實例。(這種情況在非連續(xù)的操作中非常有用,例如,偶爾連接到企業(yè)網(wǎng)絡(luò)的筆記本電腦。)在第三個配置中,非 J2EE 客戶機可以通過任何配置的傳輸直接訪問 ActiveMQ 消息代理。該操作示例演示了如何創(chuàng)建這樣一個獨立的、非 J2EE ActiveMQ 應(yīng)用程序客戶機。
創(chuàng)建 JMS 應(yīng)用程序:servlet 生產(chǎn)者和本地 ActiveMQ 消費者 這里的第一個示例顯示 servlet 如何通過 JMS 與外部非 J2EE 應(yīng)用程序通信。該示例使用了稱為 SendReceiveQueue 的全局服務(wù)器范圍的隊列(參見 清單 2)。它包括 JMS 消息發(fā)送方(生產(chǎn)者)和 JMS 消息接收方(消費者)。生產(chǎn)者是一個 servlet,稱為 SenderServlet,它在 Geronimo 內(nèi)部運行。調(diào)用程序是一個獨立的 ActiveMQ 客戶機,不使用 Geronimo 對 JMS 提供支持。圖 4 顯示了這個示例中的交互情況。 圖 4. SenderServlet 和 ActiveMQ 接收方應(yīng)用程序 ![]() 在 圖 4 中,應(yīng)用程序流程如下:
本示例的 Web 應(yīng)用程序源代碼位于代碼下載文件夾的 war_only 目錄中(請參閱下面 參考資料 的下載部分)??蛻魴C代碼位于 mqclient 子目錄中。 如果只是想嘗試使用此示例,可以在 war_only/dist 子目錄中找到 sender.war 文檔,只需將下面的應(yīng)用程序文檔部署在 Geronimo 服務(wù)器上即可:
出現(xiàn)提示時,請輸入用戶名 通過在瀏覽器地址欄輸入 http://localhost:8080/sender/sendform.cgi 可以訪問數(shù)據(jù)項 servlet。 將文本消息輸入到字段中,然后單擊 Send。您會注意到 ActiveMQ 客戶機會立即收到該消息并將其打印出來。 瀏覽 清單 3,可以看到一些 SendServlet.java 代碼,在 war_only/src 目錄中,可以找到完整的源代碼。 在 清單 3 中,servlet 針對 HTTP GET 請求生成輸入窗體,并根據(jù) HTTP POST 請求處理窗體提交的信息。實際的 通過 Java 命名和目錄界面 (JNDI), 清單 4. web.xml 中的 JNDI 映射和資源引用
在 清單 4 中,<message-destination-ref> 通過 <message-destination-link> 子元素將名稱 dwSendReceiveQueue 映射到系統(tǒng)范圍的隊列中。遺憾的是,J2EE 1.4 規(guī)范不支持 web.xml 中 <resource-ref> 元素中的 <resource-link> 子元素。因此,必須使用連接工廠的實際資源名 (DefaultActiveMQConnectionFactory),或者必須創(chuàng)建一個自定義部署計劃(如 geronimo-web.xml)以映射該引用。 接收方是本地 ActiveMQ 客戶機,它不需要任何 Geronimo 客戶機支持。它通過 TCP 傳輸和 URL tcp://localhost:61616 訪問 Geronimo 中駐留的 ActiveMQ 消息代理。此客戶機 JMSReceiver 的部分源代碼如 清單 5 所示。在 war_only/clientsrc 目錄中,可以看到完整的源代碼。 清單 5. JMSReceiver.java —— 非 J2EE JMS 消息接收方客戶機
在 清單 5 中,JMSReceiver 完全獨立于 J2EE 代碼。無需執(zhí)行 JNDI 查找或目標映射,因為 ActiveMQ 本地庫會自動執(zhí)行等同的操作。 通過混合使用 JMS API 和 ActiveMQ 支持庫,對這個非 J2EE 消息消費者進行編碼非常簡單。使用 Geronimo 的支持對 J2EE 消息消費者進行編碼也很簡單。下一個示例將顯示如何構(gòu)建有用的 J2EE 消息消費者:MDB,該程序可以將產(chǎn)品類別添加到 Really Big Pet Store 示例中。
創(chuàng)建用于數(shù)據(jù)更新的 MDB 第二個操作示例將顯示如何構(gòu)建 MDB。這個示例使用與第一個示例完全相同的 SendServlet 代碼,但是,消息消費者現(xiàn)在是同一企業(yè)應(yīng)用程序內(nèi)的 MDB(綁定在同一 EAR 中)。圖 5 舉例說明了這個示例的操作過程。 圖 5. MDB 示例的操作過程 ![]() 這個示例使用的代碼來自文章“Geronimo! 第 2 部分:馴服 J2EE 1.4 這匹野馬”(developerWorks,2005 年 5 月)。這篇文章還包含關(guān)于 Really Big Pet Store 操作的更多信息。 在 圖 5 中,初始 Web 應(yīng)用程序的操作過程被完好地保留下來。購物者可以使用瀏覽器訪問該店鋪的基于 JSP 的用戶界面。StoreController servlet 使用稱為 CategoriesBean 的無狀態(tài)會話 EJB 的 對 CategoriesBean 進行修改,以便使用新的 helper 類 MDB 又稱為 CategoriesMDB。在將消息放入 SendReceiveQueue 時,EJB 會被激活。CategoriesMDB 提取此消息內(nèi)容,并通過它將產(chǎn)品類別添加到 在生產(chǎn)環(huán)境中,代表類別的實體 bean 可以代替 SenderServlet 的代碼與第一個示例的版本幾乎一樣。請參閱 ear_ejb/src/SenderServlet.java,以獲得完整的源代碼。 CategoriesMDB 的代碼如 清單 6 所示,您可以在 ejb/CategoriesMDB.java 找到完整的源代碼。 清單 6. CategoriesMDB —— 使用 JMS 消息并添加類別
MDB 代碼非常簡單。清單 7 中突出顯示的行是執(zhí)行任務(wù)的位置。隊列收到 JMS 消息時,Geronimo 將執(zhí)行以下操作:
您需要在部署描述符 ejb-jar.xml 中使用關(guān)聯(lián)的 JMS 目標(或隊列)配置 MDB。在 清單 7 中可以看到它的一個示例。 在 清單 8 中,SendReceiveQueue 通過 <message-driven> 元素中的 <activation-config> 子元素與 MDB 關(guān)聯(lián),要選擇將要使用的 JMS RA,請創(chuàng)建與 清單 8 類似的自定義 openejb=jar.xml。 清單 8. 自定義部署計劃 openejb-jar.xml 來選擇 JMS RA
在 清單 8 中,默認的系統(tǒng)范圍的 RA 使用 <resource-link> 元素按名稱進行選擇。請參閱側(cè)欄 父配置和類裝載,以了解 geronimo-application.xml 部署計劃所需的信息。 要嘗試使用這個示例,請部署 reallybigpet.ear 應(yīng)用程序,它位于 ear_ejb/dist 目錄中。要訪問該店鋪,請將瀏覽器指向 http://localhost:8080/ReallyBigPetStore/store.cgi。要訪問添加類別的窗體,請將瀏覽器指向 http://localhost:8080/ReallyBigPetStore/sendform.cgi。
ActiveMQ 為 Geronimo 提供了高質(zhì)量的 JMS 服務(wù),同時,Geronimo 為 ActiveMQ 提供了基于 JDBC 的持續(xù)性、生命周期管理(通過遵從 JCA 1.5)、安全性、傳輸和工作管理。這種共存關(guān)系使 Geronimo 用戶獲得了兩者的優(yōu)點:可以訪問通過 ActiveMQ 的豐富傳輸和客戶機支持增強的標準化了的 J2EE 1.4 JMS 和 MDB 工具。
作者衷心感謝 Geronimo 團隊的 David Jencks,在本文評審期間,他給予了專業(yè)幫助。
|