2009-03-09 21 views
14

¿Cuál sería una buena y buena manera de desactivar temporalmente un detector de mensajes? El problema que quiero resolver es:Cómo deshabilitar temporalmente un detector de mensajes

  • mensaje JMS es recibida por un receptor de mensajes
  • consigo un error al intentar procesar el mensaje.
  • Espero que mi sistema se prepare nuevamente para poder procesar el mensaje.
  • Hasta que mi sistema esté listo, no quiero más mensajes, por lo que ...
  • ... Quiero desactivar el detector de mensajes.
  • Mi sistema está listo para procesar nuevamente.
  • Se procesa el mensaje fallido y se confirma el mensaje JMS.
  • Habilita el detector de mensajes nuevamente.

En este momento estoy usando Sun App Server. Inhabilité el detector de mensajes configurándolo como nulo en MessageConsumer, y lo habilité de nuevo usando setMessageListener (myOldMessageListener), pero después de esto no recibo más mensajes.

Respuesta

14

¿Qué tal si no regresas del método de escucha onMessage() hasta que tu sistema esté listo para procesar los mensajes nuevamente? Eso evitará que JMS entregue otro mensaje a ese consumidor.

Ese es el equivalente asíncrono de no llamar a receive() en un caso síncrono.

No hay multi-threading para una sesión JMS dada, por lo que la canalización de mensajes se mantiene hasta que el método onMessage() regrese.

No estoy familiarizado con las implicaciones de llamar dinámicamente a setMessageListener(). Javadoc dice there's undefined behavior si se llama "cuando los mensajes están siendo consumidos por un oyente o consumidor de sincronización existente". Si llama desde dentro de Message(), parece que está llegando a ese caso indefinido.

Hay start/stop métodos en el nivel de Conexión, si no es demasiado gruesa para usted.

+0

Oh, realmente fue así de simple. Esperaba que más hilos llamaran al método onMessage. ¡Gracias un montón! – davidi

+0

Las conexiones son seguras para subprocesos. Las sesiones de abajo (sesiones, consumidores, productores) no son seguras para subprocesos. Tu código necesita evitar el acceso multiproceso. Para hacer cumplir eso, JMS no podía procesar múltiples llamadas de escucha en un consumidor. –

+3

Acabo de notar que la especificación JMS especifica explícitamente este comportamiento de entrega en serie. Es la sección 4.4.16 de la especificación JMS 1.0.2. En el pasado, pensé que solo estaba implícito en las reglas de enhebrado. –

0

Eso me parece que los mensajes se están entregando pero no pasa nada con ellos porque no tiene un oyente conectado. Ha pasado un tiempo desde que hice algo con JMS pero no desea que el mensaje se envíe a la cola de mensajes no entregados o algo así mientras arregla el sistema, y ​​luego vuelve a colocar los mensajes en la cola original una vez que está listo para el procesamiento de nuevo?

+0

Eso podría ser lo que ocurra. Desafortunadamente, no tengo ese control del servidor de jms, todo lo que puedo hacer es especificar una cola para recibir mensajes, sin cola de letras muertas. Supongo que podría detener la QueueConnection, pero eso no se puede hacer desde el hilo messagelistener. – davidi

+0

¿Cómo es que no tiene acceso al servidor JMS? Como Duffymo ha señalado correctamente, es la cola de errores a la que desea acceder. De lo contrario, terminará replicando el comportamiento en el código que el servidor JMS proporciona para usted – tddmonkey

+0

Tengo ese acceso al servidor JMS ... en mi entorno de desarrollo, pero no puedo esperar que los usuarios de la aplicación que estoy trabajando en (un puente entre dos sistemas de mensajería) tienen los mismos permisos para el servidor JMS. ¿Es esa cola de cartas muertas la forma habitual de tratar estos problemas? – davidi

0

En WebLogic puede configurar reintentos máximos, una cola de errores para manejar mensajes que exceden el límite máximo de reintento y otros parámetros. No estoy seguro de la cabeza, pero también podría especificar un período de espera. Todo esto está disponible para usted en la consola de administración. Vería el administrador del proveedor de JMS que tienes y vería si puede hacer algo similar.

2

Problema resuelto por una solución que reemplaza al oyente de mensajes por un bucle de recepción(), pero todavía estoy interesado en cómo desactivar un oyente de mensajes y habilitarlo en breve.

0

En JBoss el siguiente código hará el truco:

MBeanServer mbeanServer = MBeanServerLocator.locateJBoss(); 
    ObjectName objName = new ObjectName("jboss.j2ee:ear=MessageGateway.ear,jar=MessageGateway-EJB.jar,name=MessageSenderMDB,service=EJB3"); 
    JMSContainerInvokerMBean invoker = (JMSContainerInvokerMBean) MBeanProxy.get(JMSContainerInvokerMBean.class, objName, mbeanServer); 

    invoker.stop(); //Stop MDB 
    invoker.start(); //Start MDB 
0

Creo que se puede llamar

messageConsumer.setMessageListener(null); 

dentro de su aplicación MessageListener y programar la tarea de restablecimiento (por ejemplo, en ScheduledExecutorService). Esta tarea debe llamar al

connection.stop(); 
messageConsumer.setMessageListener(YOUR_NEW_LISTENER); 
connection.start(); 

y estará funcionando. Los métodos start() y stop() se utilizan para reiniciar los strutrues de entrega (no la conexión TCP).

Leer el Javadoc https://docs.oracle.com/javaee/7/api/javax/jms/Connection.html#stop--

Interrumpe temporalmente la entrega de una conexión de mensajes entrantes. La entrega se puede reiniciar utilizando el método de inicio de la conexión. Cuando se detiene la conexión, se inhibe la entrega a todos los consumidores de mensajes de la conexión: el bloque de recepción síncrona y los mensajes no se entregan a los receptores de mensajes.

0

Por detiene temporalmente la entrega de una conexión de mensajes entrantes que necesita para utilizar stop() método de Connection interfaz: https://docs.oracle.com/javaee/7/api/javax/jms/Connection.html#stop--

Simplemente no llamar connection.stop() de MessageListener porque de acuerdo a las especificaciones JMS. obtendrá un punto muerto o una excepción. En su lugar, puede llamar al connection.stop() desde un hilo diferente, solo necesita sincronizar MessageListener y enhebrar que va a suspender la conexión con la función connection.stop()

Cuestiones relacionadas