2012-09-14 15 views
9

Estoy usando ActiveMQ para enviar el mensaje.¿Por qué el mensaje vuelve a la función onMessage()?

Así que cuando envié un mensaje, el mensaje viene para recibir el mensaje. En la inserción exitosa, se confirma.

Pero tengo un código después del acuse de recibo, que puede arrojar NullPointerException.

Para producir esa excepción intencionalmente, tengo tiro NullPointerException. Entonces cuando lo hago

El mensaje no es dequeued y el mismo mensaje vuelve a la función onMessage.

mi código es:

public void onMessage(Message message) { 
    String msg = null; 
    try 
    { 
     msg = receiveMessage(message); 

     // other code to insert message in db 

     message.acknowledge(); 

     if(true) 
     { 
     throw new NullPointerException("npe")); 
     } 
     ** // other code which might produces null pointer exception ** 
     } 
     catch(Exception ex){} 
    } 

Ahora mi pregunta es por qué el mensaje está llegando a más onMessage() función que tengo acknowledge() también.

Como ya he insertado el mensaje en db.

¿No se eliminará el mensaje dentro de la cola en acknowledge()?

¿Cómo puedo lograr esto? Gracias de antemano.

+0

¿Cuál es el modo de reconocimiento de su sesión? –

+0

@Tim acknowlge mode está establecido como Client_Acknowledge. vikiiii

+0

¿Qué versión de activemq está usando? –

Respuesta

2

Puede crear un método separado para procesar el mensaje, es decir, en la función onMessage() escribir un código para solo insertar ese mensaje en DB.

Y cree una función separada para el procesamiento de ese mensaje. Para que si recibe algún error durante el procesamiento, el mensaje no vuelva a onMessage().

+0

Gracias por la idea. Trataré de ponerla en práctica. – vikiiii

0

Cuando utiliza un modo de confirmación de transacción JMS, su mensaje será recibido por JMS-listener varias veces (en AMQ por defecto es ~ 8) hasta que sea procesado sin excepción o será movido por JMS-container a DQL-queue. Vea Message Redelivery and DLQ Handling para más detalles.

El manejo de las transacciones depende del marco utilizado por usted. Yo prefiero usar la primavera, por lo que mi configuración XML de Spring es que parece

<jms:listener-container container-type="default" connection-factory="calendarConnectionFactory" 
         acknowledge="transacted" destination-type="queue" cache="consumer" concurrency="1-5"> 
    <jms:listener destination="${jms.calendar.destination}" ref="calendarListener"/> 
</jms:listener-container> 

y el código Java de mi mensaje oyente es

@Override 
@Transactional(propagation = Propagation.REQUIRED, 
     noRollbackFor = {ClassCastException.class, IllegalArgumentException.class}) 
public void onMessage(Message message) { 
.... 
} 

Así que se puede gestionar lo excepciones se retrotraer la transacción o no

+0

He intentado con las anotaciones anteriores, pero nuevamente el mismo problema. – vikiiii

4

Utiliza el modo de confirmación AUTO con los enumeradores de mensajes, luego, por especificación, se vuelve a enviar un mensaje si los oyentes del mensaje no pueden regresar correctamente (por ejemplo, si se produce una excepción).

En su caso, está intentando reconocer manualmente el mensaje, pero eso no es posible utilizando una sesión creada con createSession(false, Session.AUTO_ACKNOWLEDGE).

Tu código habría funcionado con Session.CLIENT_ACKNOWLEDGE.

De lo contrario, desea ver las excepciones dentro del método onMessage, al usar AUTO_ACKNOWLEDGE.

Para obtener un control más detallado sobre sus mensajes, considere usar sesiones transaccionadas y use session.commit(); para confirmar que se ha leído un mensaje.

+0

En mi archivo jms-confif.xml. Lo configuré para CLIENT_ACKNOWLEDGE pero sigue teniendo el mismo problema. – vikiiii

3

¿Has comprobado que no estás usando transacted sessions?.Cuando se utiliza sesiones negociados, el modo de confirmación se ignora, por lo que:

  • Su message.acknowledge() sería efectivamente un no-op

  • Su excepción no detectada estaría provocando un "rollback sesión" cuando se escapan de su receptor de mensajes , obligando a volver a entregar el mensaje.

NOTA: El código publicado tiene un catch (Exception ex) { }, así que no sé exactamente cómo su excepción escapa fuera.

+0

Después de confirmar, lanza Nullpointereception y luego va al bloque catch. Después de ese mensaje vuelve a aparecer la función onMessage(). – vikiiii

+0

"Your message.acknowledge() sería efectivamente un no-operativo" ¿Qué significa no-op? – vikiiii

+0

@vikiiii No-op significa "Sin operación". Es un término común para algunas instrucciones que no hace nada. – gpeche

Cuestiones relacionadas