java - 读取而不从 JMS 队列中删除消息

标签 java spring message-queue spring-jms

如何从 WebSphere MQ 读取消息而不从队列中删除原始消息?

我有一个 Spring 应用程序,它从 WebSphere MQ 读取消息。 读完后,我有一个处理方法,它将处理从队列中检索的数据。

第 1 步:

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

第 2 步:

process(response);

process方法有可能抛出异常。如果出现异常,我需要将消息保留在队列中。

这可能吗?他们有办法仅在用户确认后删除该消息吗?

我尝试添加以下内容:

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

最佳答案

您不能使用 receive() 方法执行此操作,因为当 receive 方法返回时操作已完成(从 session 角度来看)。

您需要运行 session 范围内可能失败的代码;例如使用 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();
}

关于java - 读取而不从 JMS 队列中删除消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42272904/

相关文章:

java - 测量某个数据结构的内存使用情况

java - GUI 对象不绘制

java - RabbitMQ 实现细节

google-app-engine - 我可以阻止 Google AppEngine 拉取任务队列直到任务可用吗?

java - 当组中的一个订阅者被严格分配到特定分区时,Kafka 重新平衡

java - 如何使用 GeoFirestore (Java/Android) 在谷歌地图上显示多个标记?

java - 从 ResultSet 获取所有数据库

java - 带有Eureka依赖的Spring启动无法启动

spring - java.lang.NoClassDefFoundError : org/slf4j/LoggerFactory Spring boot 1. 5.2 Maven

java - 使用 Hibernate 和 spring 从不同表形成对象列表的最佳方法是什么