2009-08-24 20 views
5

Utilizando JBoss 4.0.5, JBossMQ y Spring 2.0.8, intento configurar Spring para crear instancias de beans que dependan de un recurso JMS Queue remoto. Todos los ejemplos que he encontrado dependen del uso de JNDI para buscar cosas como el objeto ConnectionFactory remoto.¿Cómo inicializar ConnectionFactory para la cola JMS remota cuando la máquina remota no se está ejecutando?

Mi problema es cuando trato de abrir una máquina que colocaría mensajes en la cola remota, si la máquina remota no está activa, la búsqueda JNDI simplemente falla, lo que hace que la implementación falle. ¿Hay alguna manera de que Spring continúe intentando buscar este objeto en el fondo sin bloquear el resto de la implementación?

Respuesta

3

de IIT difícil estar seguro sin ver su configuración primavera, pero suponiendo que está utilizando la primavera de JndiObjectFactoryBean para hacer la búsqueda JNDI, entonces se puede establecer la propiedad lookupOnStartup false, lo que permite que el marco para poner en marcha incluso si el JNDI el objetivo no está allí. La resolución JNDI se realizará la primera vez que se use ConnectionFactory.

Sin embargo, esto simplemente desplaza el problema más arriba en la cadena, porque si algún otro componente intenta obtener un JMS Connection en el inicio, entonces está de vuelta donde comenzó. Puede utilizar el atributo lazy-init="true" en sus otros beans para evitar que esto suceda durante la implementación, pero es fácil poner accidentalmente algo en su configuración que obliga a que todo se inicialice.

1

Tienes toda la razón. Intenté configurar lookupOnStartup en falso y lazy-init = true. Esto simplemente resiste el problema la primera vez que se intenta utilizar la cola. A continuación, se produce una excepción de la siguiente manera:

[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 

Por otra parte, parece que la búsqueda nunca se intenta de nuevo. Cuando la máquina con la cola remota vuelve a subir, nunca se procesa ningún mensaje. Esto realmente parece que debería estar dentro del sobre de casos de uso para tonterías J2EE, y sin embargo no estoy teniendo mucha suerte ... Parece que debería ser un problema resuelto.

Para completar, la siguiente es la parte pertinente de mi configuración de 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> 
+0

Pruebe eliminando init de lazy-init todas las definiciones, y establezca el autoStartup de la definición prototypeListenerContainer en falso. Esto evitará que el contenedor de escucha intente conectarse al inicio del contexto, pero luego deberá encontrar la manera de llamar manualmente a start() en el contenedor de escucha. Ah, y bienvenidos al horror que es JMS. – skaffman

+0

SI pudiera hacer que la búsqueda JNDI siguiera pasando en segundo plano y simplemente dejar que mis clientes siguieran felices sin un servidor, todo sería color de rosa. Probaré tu sugerencia. Gracias. – Erik

Cuestiones relacionadas