使用JBoss 4.0.5,JBossMQ和Spring 2.0.8,我試圖配置Spring來實例化依賴於遠程JMS隊列資源的bean。我遇到的所有示例都依賴於使用JNDI來查找遠程ConnectionFactory對象等內容。遠程機器未運行時如何初始化遠程JMS隊列的ConnectionFactory?
我的問題是,當試圖啓動一個將消息放入遠程隊列的機器時,如果遠程機器沒有啓動,JNDI查找失敗,導致部署失敗。有沒有辦法讓Spring繼續嘗試在後臺查找此對象,同時不阻止剩餘的部署?
使用JBoss 4.0.5,JBossMQ和Spring 2.0.8,我試圖配置Spring來實例化依賴於遠程JMS隊列資源的bean。我遇到的所有示例都依賴於使用JNDI來查找遠程ConnectionFactory對象等內容。遠程機器未運行時如何初始化遠程JMS隊列的ConnectionFactory?
我的問題是,當試圖啓動一個將消息放入遠程隊列的機器時,如果遠程機器沒有啓動,JNDI查找失敗,導致部署失敗。有沒有辦法讓Spring繼續嘗試在後臺查找此對象,同時不阻止剩餘的部署?
Iit很難確定沒有看到您的spring配置,但假設您使用Spring的JndiObjectFactoryBean
來執行JNDI查找,那麼您可以將lookupOnStartup
屬性設置爲false,這允許上下文即使在JNDI目標不在那裏。 JNDI解析將在第一次使用ConnectionFactory時完成。
但是,這只是將問題進一步轉移到鏈上,因爲如果某個其他組件試圖在啓動時獲得JMS Connection
,那麼您又回到了開始的位置。您可以在其他bean上使用lazy-init="true"
屬性來防止在部署時發生這種情況,但是很容易在您的配置中意外放入一些東西,這會強制所有內容初始化。
你是對的。我試着將lookupOnStartup設置爲false並且lazy-init = true。這只是首次嘗試使用隊列時的問題。然後拋出如下異常:
[org.jboss.mq.il.uil2.SocketManager] Failed to handle: org.jboss.mq.il.uil2.msgs.CloseMsg29702787[msgType: m_connectionClosing, msgID: -2147483606, error: null]
java.io.IOException: Client is not connected
此外,它看起來像查找再也不會嘗試。當帶有遠程隊列的機器恢復運行時,隨後不會處理任何消息。這確實看起來好像應該在J2EE廢話的用例範圍內,然而我沒有太多的運氣......感覺它應該甚至可能是解決了問題。
爲了完成的緣故,以下是我的Spring配置的相關部分。
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.provider.url">localhost:1099</prop>
<prop key="java.naming.factory.url.pkgs">org.jnp.interfaces:org.jboss.naming</prop>
<prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
</props>
</property>
</bean>
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate"/>
</property>
<property name="jndiName">
<value>ConnectionFactory</value>
</property>
</bean>
<bean id="remoteJndiTemplate" class="org.springframework.jndi.JndiTemplate" lazy-init="true">
<property name="environment">
<props>
<prop key="java.naming.provider.url">jnp://10.0.100.232:1099</prop>
<prop key="java.naming.factory.url.pkgs">org.jnp.interfaces:org.jboss.naming</prop>
<prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
</props>
</property>
</bean>
<bean id="remoteConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean" lazy-init="true">
<property name="jndiTemplate" ref="remoteJndiTemplate"/>
<property name="jndiName" value="ConnectionFactory" />
<property name="lookupOnStartup" value="false" />
<property name="proxyInterface" value="javax.jms.ConnectionFactory" />
</bean>
<bean id="destinationResolver" class="com.foo.jms.FooDestinationResolver" />
<bean id="localVoicemailTranscodingDestination" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jndiTemplate"/>
<property name="jndiName" value="queue/voicemailTranscoding" />
</bean>
<bean id="globalVoicemailTranscodingDestination" class="org.springframework.jndi.JndiObjectFactoryBean" lazy-init="true" >
<property name="jndiTemplate" ref="remoteJndiTemplate" />
<property name="jndiName" value="queue/globalVoicemailTranscoding" />
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate" >
<property name="connectionFactory" ref="connectionFactory"/>
<property name="defaultDestination" ref="localVoicemailTranscodingDestination" />
</bean>
<bean id="remoteJmsTemplate" class="org.springframework.jms.core.JmsTemplate" lazy-init="true">
<property name="connectionFactory" ref="remoteConnectionFactory"/>
<property name="destinationResolver" ref="destinationResolver"/>
</bean>
<bean id="globalQueueStatus" class="com.foo.bar.recording.GlobalQueueStatus" />
<!-- Do not deploy this bean for machines other than transcoding machine -->
<condbean:cond test="${transcoding.server}">
<bean id="voicemailMDPListener"
class="org.springframework.jms.listener.adapter.MessageListenerAdapter" lazy-init="true">
<constructor-arg>
<bean class="com.foo.bar.recording.mdp.VoicemailMDP" lazy-init="true">
<property name="manager" ref="vmMgr" />
</bean>
</constructor-arg>
</bean>
</condbean:cond>
<bean id="voicemailForwardingMDPListener"
class="org.springframework.jms.listener.adapter.MessageListenerAdapter" lazy-init="true">
<constructor-arg>
<bean class="com.foo.bar.recording.mdp.QueueForwardingMDP" lazy-init="true">
<property name="queueStatus" ref="globalQueueStatus" />
<property name="template" ref="remoteJmsTemplate" />
<property name="remoteDestination" ref="globalVoicemailTranscodingDestination" />
</bean>
</constructor-arg>
</bean>
<bean id="prototypeListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer"
abstract="true"
lazy-init="true">
<property name="concurrentConsumers" value="5" />
<property name="connectionFactory" ref="connectionFactory" />
<!-- 2 is CLIENT_ACKNOWLEDGE: http://java.sun.com/j2ee/1.4/docs/api/constant-values.html#javax.jms.Session.CLIENT_ACKNOWLEDGE -->
<!-- 1 is autoacknowldge -->
<property name="sessionAcknowledgeMode" value="1" />
<property name="sessionTransacted" value="true" />
</bean>
<!-- Do not deploy this bean for machines other than transcoding machine -->
<condbean:cond test="${transcoding.server}">
<bean id="voicemailMDPContainer" parent="prototypeListenerContainer" lazy-init="true">
<property name="destination" ref="globalVoicemailTranscodingDestination" />
<property name="messageListener" ref="voicemailMDPListener" />
</bean>
</condbean:cond>
<bean id="voicemailForwardMDPContainer" parent="prototypeListenerContainer" lazy-init="true">
<property name="destination" ref="localVoicemailTranscodingDestination" />
<property name="messageListener" ref="voicemailForwardingMDPListener" />
</bean>
嘗試刪除lazy-init的所有定義,並將prototypeListenerContainer定義的autoStartup設置爲false。這將阻止偵聽器容器嘗試獲取上下文啓動時的連接,但是您需要找到一種方法,在偵聽器容器上手動調用start()。哦,歡迎來到JMS的糟糕之處。 – skaffman 2009-08-24 22:17:50
如果我只能讓JNDI查找繼續在後臺進行,並讓我的客戶在沒有服務器的情況下繼續他們的快樂方式,那麼一切都會很好。我會試試你的建議。謝謝。 – Erik 2009-08-24 22:27:21