搭配 GenericJMSRA 的 SJSAS
連線能力 > 容器 > 搭配 GenericJMSRA 的 SJSAS
使用 ActiveMQ Classic、Generic JMS RA 和 SJSAS (Glassfish)
本文記錄我如何使用 GenericJMSRA 讓 ActiveMQ Classic 和 SJSAS 協同運作。目標是讓 ActiveMQ Classic 作為 JMS 提供者,而 MDB 可以部署在 SJSAS 中,監聽來自 ActiveMQ Classic 的訊息。請注意,我使用的 SJSAS 版本是 9.0 Update 1。我沒有時間用 SJSAS 9.1 或 Glassfish v2 測試。
步驟
首先,下載所有二進位檔
- genericra 1.7 (rar)
- activemq 4.1.1 (zip 或 tar.gz)
activemq 有一些相依性,但是您可以輕鬆地在發行版 (zip 或 tar.gz) 中找到所有相依性。以下是最低相依性清單
- activemq-core
- activeio
- commons-logging
- backport-util-concurrent
為了使用 genericra,您需要先使用 asadmin (SJSAS 的命令列工具) 建立資源介面卡設定。
asadmin create-resource-adapter-config
--property
SupportsXA=false
:RMPolicy=OnePerPhysicalConnection
:ProviderIntegrationMode=javabean
:ConnectionFactoryClassName=org.apache.activemq.ActiveMQConnectionFactory
:QueueConnectionFactoryClassName=org.apache.activemq.ActiveMQConnectionFactory
:TopicConnectionFactoryClassName=org.apache.activemq.ActiveMQConnectionFactory
:XAConnectionFactoryClassName=org.apache.activemq.ActiveMQXAConnectionFactory
:XAQueueConnectionFactoryClassName=org.apache.activemq.ActiveMQXAConnectionFactory
:XATopicConnectionFactoryClassName=org.apache.activemq.ActiveMQXAConnectionFactory
:UnifiedDestinationClassName=org.apache.activemq.command.ActiveMQDestination
:QueueClassName=org.apache.activemq.command.ActiveMQQueue
:TopicClassName=org.apache.activemq.command.ActiveMQTopic
:ConnectionFactoryProperties=brokerURL\\\=tcp\\\://127.0.0.1\\\:61616
:LogLevel=FINE
myapp#genericra
您應該注意,上述命令應以單行執行,且在「:」周圍沒有空格。就像這樣
asadmin create-resource-adapter-config --property SupportsXA=false:ConnectionFactoryProperties=brokerURL=tcp://127.0.0.1:61616 myapp#genericra
在 DOS 命令提示字元下,您應該只使用一個「/」來跳脫,就像這樣。
asadmin create-resource-adapter-config --property SupportsXA=false:ConnectionFactoryProperties=brokerURL=tcp://127.0.0.1:61616 myapp#genericra
將您的應用程式、genericra.rar 和 activemq 相依性打包在一個 EAR 中。EAR 的結構應如下所示
lib/activemq-core-4.1.1.jar
lib/log4j-1.2.13.jar
lib/commons-logging-1.1.jar
lib/backport-util-concurrent-2.1.jar
lib/activeio-core-3.0.0-incubator.jar
META-INF/application.xml
genericra.rar
mymodules.jar
在 mymodules.jar (我放置 MDB 的地方) 中,sun-ejb-jar.xml 應如下所示
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-ejb-jar
PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 8.1 EJB 2.1//EN"
"http://www.sun.com/software/appserver/dtds/sun-ejb-jar\_2\_1-1.dtd">
<sun-ejb-jar>
<enterprise-beans>
<ejb>
<ejb-name>TestingMessageDrivenBean</ejb-name>
<mdb-connection-factory>
<jndi-name>jms/SimpleQueueConnectionFactory</jndi-name>
</mdb-connection-factory>
<mdb-resource-adapter>
<resource-adapter-mid>myapp#genericra</resource-adapter-mid>
<activation-config>
<activation-config-property>
<activation-config-property-name>DestinationType</activation-config-property-name>
<activation-config-property-value>javax.jms.Queue</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>DestinationProperties</activation-config-property-name>
<activation-config-property-value>PhysicalName=Foo.Bar</activation-config-property-value>
</activation-config-property>
</activation-config>
</mdb-resource-adapter>
</ejb>
</enterprise-beans>
</sun-ejb-jar>
application.xml 應如下所示
<?xml version="1.0" encoding="UTF-8"?>
<application
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_5.xsd"
version="5">
<description>Example DD</description>
<display-name>sample app with amq and genericra</display-name>
<module>
<ejb>mymodules.jar</ejb>
</module>
<module>
<connector>genericra.rar</connector>
</module>
</application>
部署 genericra
asadmin deploy --name myapp myapp.ear
建立連線池。在單行中執行以下命令
asadmin create-connector-connection-pool
--raname myapp#genericra
--connectiondefinition javax.jms.QueueConnectionFactory
--transactionsupport LocalTransaction
ActiveMQQueueConnectionFactoryPool
建立連線工廠管理物件。在單行中執行以下命令,請注意,“jms/SimpleQueueConnectionFactory” 需要與您的 sun-ejb-jar.xml 中的內容相符
asadmin create-connector-resource
--poolname ActiveMQQueueConnectionFactoryPool
jms/SimpleQueueConnectionFactory
類別載入器 / commons-logging+log4j 問題
在上面顯示的步驟中,您應該注意到一件事,即 RA、ActiveMQ Classic 和我的 MDB 是作為一個單一 EAR 部署的。您可以獨立部署 genericra 而無需將其放入 ear 中,前提是您不直接或間接使用 commons-logging 和 log4j。
在我正在開發的應用程式中,使用了 commons-logging,而 ActiveMQ Classic 也使用 commons-logging。在 SJSAS 中,連接器類別載入器是應用程式類別載入器的父類別載入器,因此,如果您獨立部署 genericra,然後部署您的應用程式,除非您將應用程式的 log4j.xml 與 ActiveMQ Classic jars 放在一起,否則永遠不會載入 log4j.xml。
使用 Java 標準類別載入程序,類別載入器會先將載入委派給父類別載入器。當應用程式類別載入器查找 LogFactory 類別時,它會先委派給其父類別載入器 (即連接器類別載入器)。由於連接器類別載入器已載入 ActiveMQ Classic 及其相依性 (包括 commons-logging),因此 LogFactory 最終會由連接器類別載入器載入。當 commons-logging 嘗試初始化 LogFactoryImpl,並因此觸發 log4j 初始化的標準程序時,將不會載入應用程式中的 log4j 設定 (log4j.xml 或 log4j.properties) (因為 log4j 記錄器是由連接器類別載入器載入的)。
因此,在這種情況下,獨立部署 genericra 並非完美的解決方案。
幸運的是,在 Glassfish 論壇的建議 (感謝 Sivakumar) 下,我找到了一個更好的解決方案,即將所有東西 (包括 genericra 和 activemq) 打包到一個 EAR 中。以這種方式打包後,所有類別都會在一個類別載入器下載入,好處是,您可以將 log4j.xml 放在其中一個 jar 中 (即正常的方式!)。
但是,您應該注意一個小問題,獨立部署 genericra 和與 EAR 一起打包之間有一個小差異。如果您使用 EAR 部署 RA,則需要使用 ‘appName#raName’ 格式來參照 RA。因此,RA 的參照名稱是 myapp#genericra (請參閱 create-resource-adapter-config 和 sun-ejb-jar.xml 部分)。
如果您獨立部署 RA,則 ra 名稱只是 genericra (如 Ramesh 的範例所示)。
LocalTransaction
在上述說明中,使用了 LocalTransaction。(SupportsXA=false 和 –transactionsupport LocalTransaction) 因為我目前使用的是 Non-XA 交易,但是,如 Ramesh 的範例所示,XA 也應該可以運作。
設定 genericra
當您建立 resource-adapter-config 時,有兩種設定方式。一種方式是使用 JNDI,另一種方式是使用 genericra 的 JavaBean 自省功能。在上面的範例中,我選擇使用 JavaBean 自省功能 (因此 ‘ProviderIntegrationMode=javabean’)。有關更多詳細資訊,請查看 genericra 的使用者指南。此外,我發現 genericra 網站上提供的範例也是寶貴的資源。