2012-02-01 14 views
11

Estoy empezando a darme cuenta de cómo funciona JMS ActiveMQ Acknowledgements en Spring. Hasta ahora, tengo un consumidor que funciona a la perfección, con la excepción de que cuando no reconozco el mensaje, todavía se saca de la cola (espero que permanezca allí o termine en una cola de letra muerta).Obteniendo un simple cliente Spring JMS confirme que trabaja

<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:jms="http://www.springframework.org/schema/jms" 
     xmlns:p="http://www.springframework.org/schema/p" 
     xsi:schemaLocation=" 
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.0.xsd"> 

    <!-- A JMS connection factory for ActiveMQ --> 
    <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory" 
    p:brokerURL="failover://(tcp://jms1:61616,tcp://jms2:61616)?randomize=false&amp;jms.redeliveryPolicy.maximumRedeliveries=5" /> 

    <!-- A POJO that implements the JMS message listener --> 
    <bean id="simpleMessageListener" class="com.company.ConsumerClass" /> 

    <!-- A JMS namespace aware Spring configuration for the message listener container --> 
    <jms:listener-container 
      container-type="default" 
      connection-factory="connectionFactory" 
      acknowledge="client" 
      concurrency="10-50" 
      cache="consumer"> 
     <jms:listener destination="someQueue" ref="simpleMessageListener" method="onMessage" /> 
    </jms:listener-container> 
</beans> 

En el ConsumerClass, mi sencilla consumidor se ve algo como esto:

@Override public final void onMessage(Message message) { 
    Object postedMessage = null; 
    try { 
     postedMessage = ((ObjectMessage) message).getObject(); 

     if (postedMessage.getClass() == SomeMessageType.class) { 
      try { 
       //Some logic here 

       message.acknowledge(); 
       return; //Success Here 
      } catch (MyException e) { 
       logger.error("Could not process message, but as I didn't call acknowledge I expect it to end up in the dead message queue"); 
      } 
     } 
    } catch (JMSException e) { 
     logger.error("Error occurred pulling Message from Queue", e); 
    } 

    //Also worth noting, if I throw new RuntimeException("Aww Noos"); here then it won't take it from the queue, but it won't get consumed (or end up as dead letter)... 
} 

Respuesta

-2

En mi práctica del reconocimiento del cliente rara vez o nunca se utiliza. La configuración típica es confirmación automática, por lo tanto, si su código vuelve de onMessage() normalmente (sin excepción), el mensaje se confirmará automáticamente. Si su código arroja una excepción de onMessage(), no hay acuse de recibo y, por lo general, el mensaje se volvería a entregar al número de veces preconfigurado, después del cual normalmente se descartaría o se colocaría en la cola de mensajes muertos.

En su caso, desde el punto de vista del servidor JMS, parece que el cliente solicitó un mensaje pero nunca lo reconoció, por lo que el cliente todavía está 'procesándolo'. En tal caso, el mensaje sería invisible para otros consumidores en la misma cola, por lo que podría tener la impresión de que el mensaje fue "quitar la cola" mientras que, de hecho, todavía está allí. Obviamente, tampoco verá ese mensaje en la cola de mensajes muertos.

Le sugiero que lea la especificación JMS para obtener una comprensión clara de los diferentes modos de reconocimiento.

+0

Lo siento, en este caso es exitoso si regreso después del mensaje.acknowledge() (he añadido esto en el ejemplo de código) –

+0

Además, si elimino el comentario del lanzamiento RuntimeException (tiene que ser el tiempo de ejecución para satisfacer la interfaz MessageListener) Obtengo un error: 08: 39: 59,066 WARN org.springframework.jms.listener.DefaultMessageListenerContainer # 0-2 listener.DefaultMessageListenerContainer: 694 - Falló la ejecución de la escucha del mensaje JMS y no se ha configurado ErrorHandler. java.lang.RuntimeException: Aww Noos Veo que en este caso los mensajes se mantienen con el consumidor hasta que lo termine, en ese momento intentarán consumir a otro consumidor haciéndome pensar que acknowledge = " cliente "no hace nada –

+1

En realidad, si leo el derecho javadoc," auto "reconocerá ANTES de que se llame al oyente: " sessionAcknowledgeMode "puesto a" AUTO_ACKNOWLEDGE "(predeterminado): reconocimiento automático de mensajes antes de la ejecución del oyente; no se vuelve a entregar en caso de excepción lanzada. " – dstibbe

15

leer esta documentación: contenedor de primavera JMS no utiliza el message.acknowledge()

El contenedor oyente ofrece las siguientes opciones de acuse:

"sessionAcknowledgeMode" set to "AUTO_ACKNOWLEDGE" (default): Automatic message acknowledgment before listener execution; no redelivery in case of exception thrown.
"sessionAcknowledgeMode" set to "CLIENT_ACKNOWLEDGE": Automatic message acknowledgment after successful listener execution; no redelivery in case of exception thrown.
"sessionAcknowledgeMode" set to "DUPS_OK_ACKNOWLEDGE": Lazy message acknowledgment during or after listener execution; potential redelivery in case of exception thrown.
"sessionTransacted" set to "true": Transactional acknowledgment after successful listener execution; guaranteed redelivery in case of exception thrown.

+0

Documentación de origen: [AbstractMessageListenerContainer] de Spring Framework (http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jms/listener/AbstractMessageListenerContainer.html) –

-1

Use el siguiente código, funcionará.

<bean id="{containerName}" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> 
    <property name="connectionFactory" ref={connectionFactoryBean} /> 
    <property name="destinationName" ref="{queue}" /> 
    <property name="messageListener" ref="{listner}" /> 
    <property name="sessionAcknowledgeModeName" value="CLIENT_ACKNOWLEDGE"/> 
</bean> 
-1

Método de reconocimiento de llamada() en el mensaje en su consumidor.

Consider the following scenario: An application receives but does not acknowledge a message. The application receives a subsequent message and acknowledges it. What happens to the former message? The former message is also considered acknowledged. Generally, acknowledging a particular message acknowledges all prior messages the session receives. In the above output, only message 5 is explicitly acknowledged. All the messages before message 5 are implicitly acknowledged. Messages after message 5 are not acknowledged.

Para más información lea this article

También puedes ver este artículo Sun Java System Message Queue 4.3 Developer's Guide for Java Clients

3

Hoy en día la primavera proporciona un buen envoltorio más lisos JMS escuchas de mensajes.

Consulte JavaDocs de AbstractMessageListenerContainer.

"sessionAcknowledgeMode" set to "CLIENT_ACKNOWLEDGE" : Automatic message acknowledgment after successful listener execution; best-effort redelivery in case of a user exception thrown as well as in case of other listener execution interruptions (such as the JVM dying).

Por lo tanto, cuando se define un método @JmsListener, el reconocimiento se envía automáticamente cuando se ha completado con éxito, pero se puede lanzar una excepción para recibir el mensaje de nuevo.

Cuestiones relacionadas