Как временно отключить прослушиватель сообщений

Что было бы хорошим и хорошим способом временно отключить прослушиватель сообщений? Проблема, которую я хочу решить, заключается в следующем:

  • Сообщение JMS принимается слушателем сообщения
  • При попытке обработать сообщение появляется сообщение об ошибке.
  • Я жду, когда моя система снова подготовится, чтобы обработать сообщение.
  • Пока моя система не готова, я не хочу больше сообщений, поэтому...
  • ... Я хочу отключить прослушиватель сообщений.
  • Моя система готова к обработке снова.
  • Неисправное сообщение обрабатывается, и сообщение JMS получает подтверждение.
  • Включите прослушиватель сообщений еще раз.

Сейчас я использую Sun App Server. Я отключил прослушиватель сообщений, установив его в null в MessageConsumer и снова включив его с помощью setMessageListener (myOldMessageListener), но после этого я больше не получаю никаких сообщений.

Ответы

Ответ 1

Как насчет того, если вы не вернетесь из метода onMessage(), пока ваша система не будет готова обрабатывать сообщения еще раз? Это не позволит JMS передавать другое сообщение этому пользователю.

Это асинхронный эквивалент не вызывающего метода receive() в синхронном случае.

Там нет многопоточности для данного сеанса JMS, поэтому конвейер сообщений сохраняется до тех пор, пока не будет возвращен метод onMessage().

Я не знаком с последствиями динамического вызова setMessageListener(). Javadoc говорит там undefined поведение, если он называется "когда сообщения потребляются существующим слушателем или пользователем синхронизации". Если вы звоните изнутри onMessage(), это звучит так, будто вы попадаете в этот случай undefined.

Есть start/stop методы на уровне соединения, если это не слишком грубовато для вас.

Ответ 2

Проблема решена обходным решением, заменяющим прослушиватель сообщений контуром receive(), но меня все еще интересует, как отключить прослушиватель сообщений и снова включить его.

Ответ 3

Мне кажется, что сообщения доставляются, но с ними ничего не происходит, потому что у вас нет слушателя. Прошло некоторое время с тех пор, как я сделал что-то с JMS, но не хотите, чтобы сообщение отправлено в очередь мертвых букв или что-то еще, пока вы исправляете систему, а затем переместите сообщения обратно в исходную очередь, готов к обработке снова?

Ответ 4

В WebLogic вы можете настроить макс-повторы, очередь ошибок для обработки сообщений, которые превышают максимальный лимит повтора, и другие параметры. Я не уверен в своей голове, но вы также можете указать период ожидания. Все это доступно вам в консоли администратора. Я бы посмотрел на администратора вашего JMS-провайдера и посмотрел, может ли он что-то сделать.

Ответ 5

В JBoss следующий код выполнит трюк:

   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

Ответ 6

Я думаю, вы можете позвонить

messageConsumer.setMessageListener(null);

внутри вашей реализации MessageListener и запланировать задачу восстановления (например, в ScheduledExecutorService). Эта задача должна вызвать

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

и он будет работать. start() и stop() используются для перезапуска структуры доставки (не для TCP-соединения).

Прочитайте Javadoc https://docs.oracle.com/javaee/7/api/javax/jms/Connection.html#stop--

Временное прекращение доставки входящих сообщений. Доставка может быть перезапущена с использованием метода запуска соединения. Когда соединение остановлено, подача на всех потребителей сообщений подключения запрещена: синхронный принимает блок, а сообщения не доставляются слушателям сообщений.

Ответ 7

Для временного прекращения доставки входящих сообщений необходимо использовать метод stop() из интерфейса Connection: https://docs.oracle.com/javaee/7/api/javax/jms/Connection.html#stop--

Просто не вызывайте connection.stop() из MessageListener, потому что согласно спецификации JMS. вы получите тупик или исключение. Вместо этого вы можете вызывать connection.stop() из другого потока, вам просто нужно синхронизировать MessageListener и поток, который будет приостанавливать соединение с помощью функции connection.stop()