我正在使用Spring JMS和MQ发送和接收消息。在阅读邮件时,我想确保在发生任何错误时,邮件将至少重新发送3次,然后再将它们发送到“退出队列”。主队列的回退阈值为3。
我将Transacted设置为True,将sessionAcknowledgeMode设置为CLIENT_ACKNOWLEDGE(值为2)。 在消息监听器中,我也在做message.acknowledge();。 但是,它不起作用。我想念什么吗?
<jee:jndi-lookup id="QConnectionFactory" jndi-name="jndi/QCF"/>
<jee:jndi-lookup id="MainQ" jndi-name="jndi/MainQ"/>
<jee:jndi-lookup id="MainQBO" jndi-name="jndi/MainQBO"/>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref local="QConnectionFactory"/>
</property>
<property name="sessionAcknowledgeMode" value="2" />
<property name="sessionTransacted" value="true" />
</bean>
<bean id="msgHandler" class="myservice.MyMessageHandler">
<property name="jmsTemplate" ref="jmsTemplate"/>
<property name="MainQ" ref="MainQ"/>
<property name="MainQBO" ref="MainQBO"/>
</bean>
<bean id="messageListener" class="myservice.MyMessageListener" />
<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="QConnectionFactory"/>
<property name="destination" ref="MainQ"/>
<property name="messageListener" ref="messageListener" />
<property name="sessionTransacted" value="true"/>
<property name="sessionAcknowledgeMode" value="2"/>
</bean>
Listener Class ...
public void onMessage(Message message) {
try{
... some code ...
message.acknowledge();
}catch(Exception E){
logger.erro(e);
}
}
答案 0 :(得分:0)
“不工作”永远是不够的信息。
那是
}catch(Exception E){
logger.erro(e);
}
您正在捕捉并吃掉异常;侦听器需要引发异常以重新排列消息。
答案 1 :(得分:0)
我能够使用以下方法解决此问题。希望对其他人有帮助。
配置
<bean id="messageListener" class="messageListenerClass" />
<bean id="fixedBackOff" class="org.springframework.util.backoff.FixedBackOff">
<constructor-arg index="0" value="30000" />
<constructor-arg index="1" value="3" />
</bean>
<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactoryBean" />
<property name="destination" ref="destinationQueue" />
<property name="messageListener" ref="messageListener" />
<property name="sessionTransacted" value="true" />
<property name="backOff" ref="fixedBackOff" />
</bean>
监听器类
@Override
public void onMessage(Message message) {
if (message instanceof TextMessage) {
try {
String msg = ((TextMessage) message).getText();
........
........
} catch (JMSException e) {
logger.error("JMSException occured while reading the JMSMessage : {}", e);
throw new RuntimeException();
} catch (SomeException e) {
logger.error("SomeException ... : {}", e);
throw new RuntimeException();
} catch (SomeException e) {
logger.error("SomeException ... : {}", e);
throw new RuntimeException();
}
} else {
logger.error("Message must be of type TextMessage");
throw new IllegalArgumentException("Message must be of type TextMessage");
}
}
答案 2 :(得分:0)
这可能是对 OP 问题的较晚回答,但如果您对应用程序连接到的 IBM MQ 服务器(队列管理器)具有管理访问权限,则基本上可以将所有消息重试委托给 MQ 自己的算法,称为“消息回退策略”,用于有害消息,即由于任何原因无法由消费应用程序正确处理的消息。
详情请参阅https://www.ibm.com/docs/en/ibm-mq/9.1?topic=applications-handling-poison-messages-in-mq-classes-jms。
请注意,MQ 会很高兴地处理回退计数(即同一条消息被重新传递了多少次)、回退阈值(连续失败的次数等于一条消息“有毒”)和回退队列(一个软死信队列,一旦它们超过回退阈值,有毒消息将被路由到该队列)为您配置,但此机制没有提供方便的方法 a) 延迟消息重新传递,和 b) 选择性消息重新传递(哪些消息要再次尝试,哪些消息应该立即拒绝)。至少在撰写本文时在 IBM MQ Series 9 中是这样。如果这是您的业务流程需要的东西,应用程序必须实现它。
附言并且不要忘记将 JMS 消息侦听器容器的 sessionTransacted
属性设置为 true
,以便在应用程序引发的异常时正确回退消息!