MDP JMS事务回滚,然后在无限循环中重新处理消息
如果通过指定
sessionTransacted=true
或transactionManager=jmsTransactionManager
在DefaultMessageListenerContainer上启用事务管理,则只要MDP中发生异常,事务就会回滚,消息就会放回队列。这会导致消息被再次处理,事务一次又一次地回滚,从而创建一个无限循环。
我想我的问题是..。我错过了什么吗?如果消息只是意味着它将被反复处理,那么为什么要让它回到队列中呢?
<!-- jms connection factory -->
<bean name="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:ConnectionFactory" />
</bean>
<!-- jms transaction manager -->
<bean id="jmsTransactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory" ref="jmsConnectionFactory" />
</bean>
<!-- Destination for Inbound_Email_Q -->
<bean name="inboundEmailDestination" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="queue/inbound_Email_Queue" />
</bean>
<!-- JmsTemplate for Inbound_Email_Q -->
<bean name="jmsInboundEmailTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="jmsConnectionFactory" />
<property name="defaultDestination" ref="inboundEmailDestination" />
<property name="messageConverter" ref="xmlMessageConverter" />
</bean>
<!-- jms asynchronous listener -->
<bean id="emailMessageServiceMdp" class="org.site.wso.core.jms.EmailMessageServiceMdp" />
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<!-- <property name="transactionManager" ref="jmsTransactionManager" /> -->
<!-- <property name="sessionTransacted" value="true"/> -->
<property name="destination" ref="inboundEmailDestination"/>
<property name="messageListener" ref="messageListener"/>
</bean>
<!-- jms message listener adapter -->
<bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
<constructor-arg>
<bean class="org.site.wso.core.jms.EmailMessageServiceMdp"/>
</constructor-arg>
<property name="messageConverter" ref="xmlMessageConverter"/>
</bean>
这是我的MDP:
public class EmailMessageServiceMdp implements MessageDelegate {
public void handleMessage(Object object) {
EmailMessageRequestVO requestVO = (EmailMessageRequestVO) object;
try {
//Service call that throw exception
} catch (Exception e) {
throw new ApplicationException(e);
}
}
}
JMS
消息重新传递只是您的[已配置]推荐答案实现的默认行为。这是一个无休止的争论,它的相对用处是什么,但看起来,与其丢弃包含一些可能无法恢复的数据的消息,某种形式的重试是一种明智和保守的方法。例如,在您的示例中,您似乎要将JMS消息转换为电子邮件消息并调度到SMTP服务器。如果SMTP网关关闭,您可能希望保留JMS消息,并在网关重新启动时重新处理它们。
一般来说,我认为您处理失败的消息的选项有(取决于JMS实现):
- 丢弃邮件。
- 将消息写入错误队列。
- 延迟n秒后重新传递邮件。
- 重新传递消息n次,然后将消息写入错误队列。
- 在延迟n秒x次后重新传递消息,然后将消息写入错误队列。
如果您喜欢#1,那么只需取消异常,提交事务并向消息挥手告别即可。对于睡觉,应该由jms配置(或者目的地特定配置)来处理。
此外,如果您需要更具体的内容,可以查询消息的getJMSRedelivered()和/或特定于实现的消息头属性,该属性指示消息已重新传递了多少次(受大多数JMS实现支持,但不是标准的),并相应地处理该消息。
相关文章