2009-03-09 4 views
14

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

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

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

ответ

14

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

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

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

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

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

+0

О, это действительно было так просто. Я ожидал, что больше потоков вызовет метод onMessage. Огромное спасибо! – davidi

+0

Соединения являются потокобезопасными. Сеансы вниз (сеансы, потребители, производители) не являются потокобезопасными. Ваш код должен избегать многопоточного доступа. Чтобы обеспечить это, JMS не может вызвать многопользовательский прослушиватель на одного пользователя. –

+3

Я только заметил, что спецификация JMS явно указывает это поведение последовательной доставки. Это раздел 4.4.16 спецификации JMS 1.0.2. Раньше я думал, что это просто подразумевается правилами нитей. –

0

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

+0

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

+0

Почему у вас нет доступа к серверу JMS. Как справедливо указал duffymo, его очередь ошибок, к которой вы хотите получить доступ. В противном случае вы закончите репликацию поведения в коде, который предоставит вам сервер JMS – tddmonkey

+0

У меня есть этот доступ к JMS-серверу ... в моей среде разработки, но я не могу ожидать, что пользователи приложения я работая (мост между двумя системами обмена сообщениями), имеют одинаковые права доступа к серверу JMS. Является ли эта мертвая буква обычным способом справиться с этими проблемами? – davidi

0

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

2

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

0

В 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 
0

Я думаю, что можно назвать

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--

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

0

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

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

Смежные вопросы