2017-02-16 110 views
1

如何在不從隊列中刪除原始消息的情況下從WebSphere MQ讀取消息。spring jmstemplate讀取消息而不刪除(WebSphere MQ)

我有Spring應用程序,它從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

我沒有使用JMS的XML配置。相反,JmsTemplate對象是使用java創建的。 (有問題添加了代碼片段) – user1940878

2

你不能做到這一點與方法,因爲操作完成(從會話角度)當接收方法返回。

您需要運行會話範圍內可能失敗的代碼;例如有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