如何不承认Spring-JMS只有一条消息?

时间:2014-02-26 10:16:23

标签: java jms spring-jms

有一个类'MyConsumer'从队列接收消息并处理它们。有两个要求:

  1. 如果邮件中包含无效内容,MyConsumer不应该确认,但可以处理以后的邮件
  2. 当MyConsumer重新启动时,未使用的消息将再次传递
  3. 我尝试使用spring-jms,使用监听器 - 容器支持,但找不到符合第一个要求的解决方案。

    我的代码:

    <amq:queue id="destination" physicalName="org.springbyexample.jms.test"/>
    
    <amq:connectionFactory id="jmsFactory" brokerURL="tcp://localhost:11111"/>
    
    <bean id="jmsConsumerConnectionFactory"
          class="org.springframework.jms.connection.SingleConnectionFactory"
          p:targetConnectionFactory-ref="jmsFactory"/>
    
    <bean id="jmsConsumerTemplate" class="org.springframework.jms.core.JmsTemplate"
          p:connectionFactory-ref="jmsConsumerConnectionFactory"
          p:defaultDestination-ref="destination"/>
    
    <bean id="jmsMessageListener" class="test.MyConsumer"/>
    <bean id="errorHandler" class="test.MyErrorHandler"/>
    
    <jms:listener-container container-type="default"
                            connection-factory="jmsConsumerConnectionFactory"
                            error-handler="errorHandler"
                            acknowledge="client">
        <jms:listener destination="org.springbyexample.jms.test" ref="jmsMessageListener"/>
    </jms:listener-container>
    

    班级MyConsumer

    @Override
    public void onMessage(Message message) {
        TextMessage textMessage = (TextMessage) message;
        try {
            System.out.println("!!!!!!!!! get message: " + textMessage.getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }
        if (theNumberOfMessageIs(3)) {
            throw new RuntimeException("something is wrong");
        }
    }
    

    您可能会注意到acknowledge中的listener-containerclient,实际上它有3个值:

    1. 自动(默认)
    2. 客户端
    3. 交易
    4. 我尝试了所有这些,但没有一个符合我的要求。我的测试场景:

      1. 生产者将3条消息放入队列
      2. 启动一个线程来监视队列中的消息计数,当计数改变时,打印它
      3. 启动使用者,它将从队列接收消息并处理它们
      4. 等待一段时间,再将另外3条消息排入队列
      5. auto

        MyConsumer将在收到每条消息后确认,无论是否抛出异常

        client

        MyConsumer仅在onMessage没有抛出异常时才会确认。对于第3条消息,它抛出异常,队列中将有一条未消息的消息。但是当它获得第4条消息并且不会抛出异常时,队列中的第3条消息将会消失

        transacted

        如果在MyConsumer中抛出异常,则不会确认该消息并多次重新传递。之后,消息从队列中消失

        但它们都不符合要求1.

        我想知道:如果我需要寻找除Spring-jms之外的其他解决方案,或者我的用法不正确?

1 个答案:

答案 0 :(得分:0)

auto DefaultMessageListenerContainer实际上是为交易设计的 - 使用auto,正如您所发现的那样,消息始终被确认。您可以使用SimpleMessagseListenerContainer,它可以按您的意愿工作,但它有其他限制;请参阅JavaDocs。

client这就是JMS在你知道#4时的工作方式,#3也自动被激活 - 请参阅Message JavaDocs。客户端模式用于减少ack流量(例如,每10条消息执行一次)。

transacted这是代理的一个功能,你可以配置AMQ在重试一段时间后将坏消息发送到死信队列。

您需要一些过程将消息从DLQ移回主队列以便稍后重试(可能在重启时初始化期间)。