Solace是否通过不承认以前的消息而违反了JMS规范?

时间:2018-05-24 10:57:51

标签: java jms solace

JMS 1.1规范第4.4.11节说:“承认a 消费消息自动确认收到所有消息 这是由其会议提供的。“

然而,这不是我在Solace中观察到的行为。我编写了以下100行程序,它发送了20条消息,然后读取消息并在确认和删除它们之间交替。结果是所有偶数编号的消息都保留在队列中。

Solace是否违反了JMS规范,或者我错过了什么?

package com.example;

import java.util.function.Predicate;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.QueueConnection;
import javax.jms.QueueSession;
import javax.jms.TextMessage;

import com.solacesystems.jms.SolConnectionFactory;
import com.solacesystems.jms.SolJmsUtility;
import com.solacesystems.jms.SupportedProperty;

public class SolaceAckTest {

    private static final String host = "localhost";
    private static final String username = "MyUser";
    private static final String password = "MyPassword";

    private static final String COUNTER_PROPERTY_NAME = "MyCounter";

    private static final String QUEUE_NAME = "MATCHED_1";

    private static final int NUM_MESSAGES_TO_SEND = 20;

    private static final long SENDING_INTERVAL_IN_MILLISECONDS = 100;

    /**
     * Determines on which messages we should call
     * {@link Message#acknowledge()}.
     */
    private static final Predicate<Message> SELECTOR_OF_MESSAGES_TO_ACKNOWLEDGE = new Predicate<Message>() {
        @Override
        public boolean test(Message m) {
            try {
                return (m.getIntProperty(COUNTER_PROPERTY_NAME) % 2) == 1;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    };

    public static void main(String[] args) throws Exception {

        SolConnectionFactory connectionFactory = SolJmsUtility.createConnectionFactory();
        connectionFactory.setHost(host);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setRespectTTL(true);

        QueueConnection queueConnection = connectionFactory.createQueueConnection();
        QueueSession queueSession = queueConnection.createQueueSession(false, SupportedProperty.SOL_CLIENT_ACKNOWLEDGE);
        Destination requestDest = queueSession.createQueue(QUEUE_NAME);
        queueSession.createConsumer(requestDest).setMessageListener(new MessageListenerThatAcknowledgesSomeMessages());
        MessageProducer messageProducer = queueSession.createProducer(requestDest);

        queueConnection.start();

        for (int counter = 1; counter <= NUM_MESSAGES_TO_SEND; counter++) {
            TextMessage msg = queueSession.createTextMessage();
            msg.setText("Message #" + counter);
            msg.setIntProperty(COUNTER_PROPERTY_NAME, counter);
            messageProducer.send(msg);
            Thread.sleep(SENDING_INTERVAL_IN_MILLISECONDS);
        }

        // Prevent the program from terminating.
        Thread.sleep(1000);
    }

    /**
     * A listener that calls {@link Message#acknowledge()} only on messages that
     * meet the criteria specified by
     * {@link SolaceAckTest#SELECTOR_OF_MESSAGES_TO_ACKNOWLEDGE}.
     */
    private static class MessageListenerThatAcknowledgesSomeMessages implements MessageListener {
        public MessageListenerThatAcknowledgesSomeMessages() {
        }

        @Override
        public void onMessage(Message msg) {
            try {
                final String text = ((TextMessage) msg).getText();
                if (SELECTOR_OF_MESSAGES_TO_ACKNOWLEDGE.test(msg)) {
                    msg.acknowledge();
                    System.out.println("Acknowledging message: " + text);
                } else {
                    System.out.println("Not acknowledging message: " + text);
                }
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

我相信蒂姆是正确的。在您的示例中,您似乎使用的是Solace扩展而不是标准的JMS客户端确认模式。创建会话时,请尝试指定标准JMS客户端确认模式。例如:

 QueueSession queueSession = queueConnection.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);

您最初指定的SOL_CLIENT_ACKNOWLEDGE扩展允许您确认特定消息,而不会隐式确认会话收到的所有其他消息。如果您有多个工作线程处理来自会话的消息,这将非常有用。每个线程在完成处理时都可以确认其消息,而不会隐式确认其他线程正在处理的消息。

相关问题