SpringJMS-通过将消息发送回同一队列而不是回滚事务来重新交付

SpringJMS-通过将消息发送回同一队列而不是回滚事务来重新交付,spring,transactions,queue,rollback,spring-jms,Spring,Transactions,Queue,Rollback,Spring Jms,这是我在这里的第一篇帖子,所以如果我不遵守格式规则或 其他一般规则 我有一个基于SpringJMS的客户端应用程序,它使用多个使用者从队列中读取数据。 我的限制是:在出现故障时保证重新交付,并检测到消息重复 弹簧配置 <bean id="jndiDestinationResolver" class="org.springframework.jms.support.destination.DynamicDestinationResolver" /> <bean id=

这是我在这里的第一篇帖子,所以如果我不遵守格式规则或 其他一般规则

我有一个基于SpringJMS的客户端应用程序,它使用多个使用者从队列中读取数据。 我的限制是:在出现故障时保证重新交付,并检测到消息重复

弹簧配置

<bean id="jndiDestinationResolver" class="org.springframework.jms.support.destination.DynamicDestinationResolver" />


    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <constructor-arg ref="MyConnectionFactory" />
        <property name="destinationResolver" ref="jndiDestinationResolver" />
        <property name="receiveTimeout" value="100" />
    </bean>


    <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
            <property name="destinationResolver" ref="jndiDestinationResolver" />
            <property name="connectionFactory" ref="MyConnectionFactory" />
            <property name="destinationName" value="my_Queue" />
            <property name="messageListener" ref="MyListener" />
            <property name="maxConcurrentConsumers" value="10"/>
            <property name="sessionTransacted" value="true"/>
    </bean>

我的侦听器代码类似于:

protected void processTextMessage(TextMessage textMessage) { try { // process message } catch(Exception e) { try { sendTextMessage("my_Queue",correlationID, textMessage.getText()); } catch (JMSException e1) { log.error("Error writing message back to the queue!"); throw JmsUtils.convertJmsAccessException(e1); } } } protected void sendTextMessage(String queueName, final byte[] correlationID, String message) { jmsTemplate.convertAndSend(queueName, message, new MessagePostProcessor() { public Message postProcessMessage(Message message) throws JMSException { message.setJMSCorrelationIDAsBytes(correlationID); return message; } }); } 受保护的void processTextMessage(TextMessage TextMessage){ 试一试{ //处理消息 }捕获(例外e){ 试一试{ sendTextMessage(“我的队列”,correlationID,textMessage.getText()); }捕获(jmscexception e1){ log.error(“将消息写回队列时出错!”); 抛出JmsUtils.convertJmsAccessException(e1); } } } 受保护的void sendTextMessage(字符串queueName,最终字节[]correlationID,字符串消息){ convertAndSend(队列名称、消息、新消息后处理器(){ 公共消息后处理消息(消息消息)引发JMSException{ message.setJMSCorrelationIDAsBytes(correlationID); 返回消息; } }); } 我用ActiveMQ进行了一些本地失败测试,重新发送是正常的(我注意到redelivered标志为false)。 我还试图在处理过程中粗暴地停止应用程序服务器,并能够在队列包含1条消息且redelived=true时签入

这是实现我的目标的正确方法吗

我希望这对于我将使用的JMS提供程序是透明的(在生产环境中使用Websphere MQ)。 目前,我希望通过抛出一个异常来避免回滚事务:我希望重新调度失败的消息,就像队列中的新消息一样。 对于重复检测,我认为插入业务存在检查就足够了


提前感谢并致以最诚挚的问候

是的,这是正确的方法。

除了当前(提交)队列之外,还有一个错误队列可能是更好的方法

有几个原因:

  • 在源信息无效的情况下更好地分析错误消息。 您可以在消息头上具有MSG_PROCESSED_CNT属性,并根据需要使用它重新处理消息。当您的业务逻辑中有外部集成时,它非常有用

  • 如果您的代码[try block]由于错误或集成问题而反复抛出异常,会发生什么情况?使用错误队列,您将看到深度增加,并且可以通过设置阈值监视器来通知问题

  • 将再处理工作(非业务相关)委托给第三方应用程序。您的代码将只包含您的业务逻辑