2017-02-16 42 views
1

Как читать сообщение из WebSphere MQ без удаления исходного сообщения из очереди ..?spring jmstemplate прочитанное сообщение без удаления (WebSphere MQ)

У меня есть приложение весны, которое читает сообщение из WebSphere MQ. После прочтения у меня есть метод процесса, который обрабатывает данные, полученные из очереди.

Шаг 1

response = jmsTemplate.receive(); 
//Message automatically removed from queue. 

Шаг 2

process(response); 

Есть вероятность генерации исключений в методе процесса. В случае исключений мне нужно сохранить сообщение в очереди. Возможно ли это? Это их способ удалить сообщение только при подтверждении пользователя? Я попытался добавить

jmsTemplate.setSessionAcknowledgeMode(javax.jms.Session.CLIENT_ACKNOWLEDGE); 

но все же сообщение удаляется.

Пожалуйста, помогите!

JmsTemplate Создание фрагмента кода

JndiConnectionFactorySupport connectionFactoryBean = new JndiConnectionFactorySupport(); 
    connectionFactoryBean.setBindingsDir(this.bindingDir); 


     connectionFactoryBean 
       .setConnectionFactoryName(connectionFactoryName); 
     connectionFactoryBean.afterPropertiesSet(); 
     jmsTemplate.setConnectionFactory(connectionFactoryBean.getObject()); 


    JndiDestinationResolver destinationResolver = new JndiDestinationResolver(); 
    destinationResolver.setJndiTemplate(connectionFactoryBean 
      .getJndiTemplate()); 

    jmsTemplate.setDestinationResolver(destinationResolver); 
    jmsTemplate.setReceiveTimeout(20000); 
    jmsTemplate.setDefaultDestinationName(this.defaultDestinationName); 

Попробовал метод jmsTemplate.execute(), как показано ниже

@SuppressWarnings({ "unused", "unchecked" }) 
     Message responseMessage = (Message) jmsTemplate.execute(
      new SessionCallback() { 
       public Object doInJms(Session session) 
         throws JMSException { 
        MessageConsumer consumer = session 
        .createConsumer(jmsTemplate.getDestinationResolver().resolveDestinationName(session, "QUEUE_NAME", false)); 
        Message response = consumer.receive(1); 
        try { 
         testMethod();//this method will throw exception. 
         response.acknowledge(); 
         consumer.close(); 
        } catch(Exception e){ 
         consumer.close();//control will come here. 
        } 

        return response; 
       } 
     }, true); 

ответ

0

Вы можете добавить транзакционной обработки сообщений JMS. См. the example

Ваш слушатель должен быть "transacted". Как это

<jms:listener-container connection-factory="connectionFactory" acknowledge="transacted"> 
    <jms:listener ref="notificationProcessor" destination="incoming.queue"/> 
</jms:listener-container> 
+0

я не использую конфигурации XML JMS. Вместо этого объект JmsTemplate создается с помощью java. (Добавлен фрагмент кода) – user1940878

2

Вы не можете сделать это с receive() методами, потому что операция завершена (с точки зрения сеанса), когда приемный метод возвращает.

Вам необходимо запустить код, который может выйти из строя в рамках сеанса; например с JmsTemplate.execute() с SessionCallback - что-то вроде этого ...

this.jmsTemplate.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE); 
this.jmsTemplate.convertAndSend("foo", "bar"); 
try { 
    String value = this.jmsTemplate.execute(session -> { 
     MessageConsumer consumer = session.createConsumer(
       this.jmsTemplate.getDestinationResolver().resolveDestinationName(session, "foo", false)); 
     String result; 
     try { 
      Message received = consumer.receive(5000); 
      result = (String) this.jmsTemplate.getMessageConverter().fromMessage(received); 
      // Do some stuff that might throw an exception 
      received.acknowledge(); 
     } 
     finally { 
      consumer.close(); 
     } 
     return result; 
    }, true); 
    System.out.println(value); 
} 
catch (Exception e) { 
    e.printStackTrace(); 
} 
+0

Пробовал метод execute(). (Добавлен фрагмент кода). Оно работает!!! Большое спасибо Гэри Расселл .. !!! – user1940878