Spring MDP - как отключить плохое сообщение - PullRequest
2 голосов
/ 12 марта 2012

У меня реализован Spring MDP с использованием Spring DefaultMessageListenderContainer, который прослушивает очередь ввода в WebSphere MQ v7.1. Если поступает плохое сообщение (которое вызывает RuntimeException), то в настоящее время происходит следующее: транзакция откатывается и сообщение помещается обратно в очередь. Однако MDP входит в бесконечный цикл.

Вопрос 1. Для моих требований я хотел бы иметь возможность отключить обработку в тот момент, когда она увидит плохое сообщение. Не требуется повторных попыток. Можно ли корректно отключить прослушиватель сообщений в случае, если он видит плохое сообщение (в отличие от грубых System.exit() или методов такого рода)? Мне определенно не нравится идти в бесконечный цикл.

Edit:

Вопрос 2. Есть ли способ остановить или приостановить контейнер слушателя, чтобы остановить дальнейшую обработку сообщений?

Ответы [ 3 ]

2 голосов
/ 12 марта 2012

Обычный способ обработать это состоит в том, чтобы иметь очередь ошибок и, когда вы видите плохое сообщение, поместить его в очередь ошибок.
Некоторые системы справляются с этим, например, IBM MQ Series. Вам просто нужно настроить очередь ошибок и сколько повторных попыток вы хотите, и она поместит ее туда.
Затем администратор просматривает эти очереди и предпринимает надлежащие действия с сообщениями, находящимися в очереди (то есть исправляет и повторно отправляет их)

1 голос
/ 12 марта 2012

На самом деле, System.exit() слишком жесток и ... не сработает.Повторная попытка сбойных сообщений обрабатывается на стороне посредника (WMQ), поэтому сообщение будет доставлено после перезапуска приложения.

Описываемая вами проблема называется и должна бытьобрабатывается на стороне брокера.Похоже, что это описано в Обработка вредоносных сообщений в руководстве по WMQ и в Как WebSphere Application Server обрабатывает вредоносные сообщения .

0 голосов
/ 16 марта 2012

Я решил проблему следующим образом, но не уверен, что это лучший способ, однако он работает.

  1. MDP реализует ApplicationContextAware;Я также поддерживаю состояние слушателя (перечисление со значениями ОТКРЫТЬ, ЗАКРЫТЬ, ОШИБКА). Ниже приведен фрагмент кода MDP:
//context
private ConfigurableApplicationContext applicationContext;

//listener state
private ListenerState listenerState = ListenerState.OPEN;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  this.applicationContext = (ConfigurableApplicationContext) applicationContext;
}
//onMessage method
public void processMessages(....) {
  try {
    process(...);
  } catch (Throwable t) {
    listenerState = ListenerState.ERROR;           
    throw new RuntimeException(...);            
  }    
}

@Override
public void stopContext() {        
  applicationContext.stop();  
}
  1. В основной java, которая загружает пружинуконтекст я делаю это:
    //check for errors for exit
    Listener listener = (Listener)context.getBean("listener");
    listenerContainer listenerContainer =
            (ListenerContainer)context.getBean("listenerContainer");

    try {
        while(true) {
            Thread.sleep(1000); //sleep for 1 sec
            if(!listener.getListenerState().equals(ListenerState.OPEN)) {
                listener.stopContext();
                listenerContainer.stop();
                System.exit(1);
            }>             }            
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
...