2014-02-26 48 views
0

有一个'MyConsumer'类接收队列中的消息并对其进行处理。有两个要求:如何不使用Spring-JMS确认一条消息?

  1. 如果有一个消息包含无效内容,MyConsumer不应该承认这一点,但可以处理后续的邮件
  2. 时MyConsumer重新启动

未被消耗的消息将被重新传递我用spring-jms尝试了listener-container支持,但找不到符合第一个要求的解决方案。

我的代码:MyConsumer

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

类:

@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"); 
    } 
} 

您可能会注意到,在listener-containeracknowledgeclient,实际上它有3个值:

  1. 自动(缺省)
  2. 客户
  3. 交易

我想所有的人,但没有一个适合我的要求。我的测试场景:

  1. 制片人把3个消息要排队
  2. 启动一个线程来监视队列中的消息计数,当计数的变化,打印
  3. 启动消费者,它将从队列接收消息,并对其进行处理
  4. 等待一段时间,把另外3个消息要排队

auto

接收每一个消息,无论抛出异常或不

对于client

MyConsumer将承认:

MyConsumer将承认只有当没有例外onMessage抛出。对于第三条消息,它会抛出异常,队列中会有一条消息未被消除。但是,当它获得第4消息,并且不会引发异常,在队列中的第三个消息将被disapeared

对于transacted

如果MyConsumer抛出的异常,该消息不会被承认和被重新交付几次。在此之后,该消息从队列

消失,但它们都不符合要求1.

我想:如果我需要寻找比Spring-JMS,或我的用法是错误的其他解决方案?

+0

嗨@Freewind,你有达到你的要求吗? –

回答

0

autoDefaultMessageListenerContainer是专为交易而设计的 - 如您发现的那样,使用自动功能时,消息始终得到确认。您可以使用SimpleMessagseListenerContainer,它可以按照您的要求工作,但它有其他限制;请参阅JavaDocs。

client这就是JMS的工作方式,当你检查#4,#3时也会自动检查 - 看到Message JavaDocs。客户端模式用于减少确认流量(通过每10条消息进行确认)。

transacted这是代理的功能,您可以配置AMQ在一些重试次数后将错误消息发送到死信队列。

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

0

使用WMQ,您可以使用BackOut功能使用BOTHRESH和BOQNAME队列配置参数来实现此需求,其中BOTHRESH定义尝试使用消息的次数,然后在参数BOQNAME中定义QUEUE的名称,表明您的消息将被重新传递。在这种情况下,您可以使用DLQ QUEUE,您可以在一段时间后将消息移动到主QUEUE,或者将主QUEUE作为DLQ QUEUE使消息在消费者中旋转。 希望有所帮助。