Domanda

Quale sarebbe un buon modo per disabilitare temporaneamente un listener di messaggi? Il problema che voglio risolvere è:

  • Un messaggio JMS viene ricevuto da un listener di messaggi
  • Viene visualizzato un errore durante il tentativo di elaborare il messaggio.
  • Aspetto che il mio sistema si prepari di nuovo per poter elaborare il messaggio.
  • Fino a quando il mio sistema non è pronto, non voglio più messaggi, quindi ...
  • ... Voglio disabilitare il listener di messaggi.
  • Il mio sistema è di nuovo pronto per l'elaborazione.
  • Il messaggio non riuscito viene elaborato e il messaggio JMS viene riconosciuto.
  • Abilita nuovamente il listener di messaggi.

In questo momento, sto usando Sun App Server. Ho disabilitato il listener di messaggi impostandolo su null in MessageConsumer e l'ho riabilitato utilizzando setMessageListener (myOldMessageListener), ma dopo questo non ricevo più messaggi.

È stato utile?

Soluzione

Che ne dici se non ritorni dal metodo listener onMessage () fino a quando il tuo sistema non è pronto per elaborare nuovamente i messaggi? Ciò impedirà a JMS di recapitare un altro messaggio su quel consumatore.

È l'equivalente asincrono di non chiamare a ricevere () in un caso sincrono.

Non esiste il multi-threading per una determinata sessione JMS, quindi la pipeline di messaggi viene trattenuta fino a quando non viene restituito il metodo onMessage ().

Non ho familiarità con le implicazioni della chiamata dinamica di setMessageListener (). Il javadoc dice c'è comportamento indefinito se chiamato "quando i messaggi vengono consumati da un ascoltatore esistente o sincronizzano il consumatore". Se chiami da dentro onMessage (), sembra che stai colpendo quel caso indefinito.

Ci sono start / stop metodi a il livello di connessione, se non è troppo grossolano per te.

Altri suggerimenti

Problema risolto da una soluzione alternativa che sostituisce il listener di messaggi con un ciclo di ricezione (), ma sono ancora interessato a come disabilitare un listener di messaggi e abilitarlo a breve.

Mi sembra che i messaggi vengano recapitati, ma non succede nulla perché non hai nessun ascoltatore allegato. È passato un po 'di tempo da quando ho fatto qualcosa con JMS ma non vuoi che il messaggio sia inviato alla coda delle lettere morte o qualcosa del genere mentre ripari il sistema, quindi sposta i messaggi nella coda originale una volta che hai pronto per l'elaborazione di nuovo?

Su WebLogic è possibile impostare un numero massimo di tentativi, una coda di errori per gestire i messaggi che superano il limite massimo di tentativi e altri parametri. Non sono certo al di sopra della mia testa, ma potresti anche essere in grado di specificare un periodo di attesa. Tutto questo è disponibile nella console di amministrazione. Guarderei l'amministratore del provider JMS che hai e vedere se può fare qualcosa di simile.

In JBoss il seguente codice farà il trucco:

   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

Penso che tu possa chiamare

messageConsumer.setMessageListener(null);

all'interno dell'implementazione di MessageListener e pianificare l'attività di ristabilimento (ad esempio in ScheduledExecutorService). Questa attività dovrebbe chiamare

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

e funzionerà. I metodi start () e stop () vengono utilizzati per riavviare le strutture di consegna (non la connessione TCP).

Leggi il Javadoc https: // docs .oracle.com / JavaEE / 7 / api / javax / jms / Connection.html # stop--

  

Arresta temporaneamente la consegna dei messaggi in arrivo da parte di una connessione. La consegna può essere riavviata utilizzando il metodo di avvio della connessione. Quando la connessione viene interrotta, la consegna a tutti gli utenti dei messaggi della connessione viene inibita: il sincrono riceve il blocco e i messaggi non vengono recapitati ai listener di messaggi.

Per interrompere temporaneamente la consegna dei messaggi in arrivo di una connessione, è necessario utilizzare il metodo stop () dall'interfaccia Connection : https://docs.oracle.com/javaee/7/api/javax/jms/Connection. html # stop--

Basta non chiamare connection.stop () da MessageListener perché secondo le specifiche JMS. otterrai deadlock o eccezioni. Invece puoi chiamare connection.stop () da thread diversi, devi solo sincronizzare MessageListener e thread che sta per sospendere la connessione con la funzione connection.stop ()

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top