spring - 使用 Spring 管理 JMS 事务

标签 spring jboss jms hornetq spring-jms

我正在尝试使用 Spring 和 HornetQ 管理 JMS 事务。
这是我写的代码:

public void receive() {
    TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
    Message msg = jmsTemplate.receive(queue);
    boolean success = false;
    if (msg != null) {
            try {
               success = handleMessage(msg);
               if (success) { 
                   msg.acknowledge(); // session is still open within the transaction
               }
            } catch (JMSException e) {
                transactionManager.rollback(status);
            }
            if (success)
                transactionManager.commit(status);
            else
                transactionManager.rollback(status):
    }
}

我正在从队列中同步读取,超时设置为 0,因为我不想阻止读取。因此,我必须检查是否确实收到了某些东西。

这是我的 的摘录applicationContext.xml :
<bean id="inVMConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName">
        <value>java:/ConnectionFactory</value>
    </property>
</bean>

<bean id="cachedConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
    <property name="targetConnectionFactory" ref="inVMConnectionFactory" />
</bean>

<bean id="producer" class="it.ubiquity.gestoreprofilazione.onweb.OnWebProducer" scope="singleton">
    <property name="queue" ref="retryQueue" />
    <property name="connectionFactory" ref="cachedConnectionFactory" />
</bean>

<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="cachedConnectionFactory" />
    <property name="sessionTransacted" value="true" />
    <property name="sessionAcknowledgeMode" value="#{T(javax.jms.Session).CLIENT_ACKNOWLEDGE}" />
    <property name="pubSubDomain" value="false" />
    <property name="receiveTimeout" value="#    {T(org.springframework.jms.core.JmsTemplate).RECEIVE_TIMEOUT_NO_WAIT}" />
</bean>

<bean id="jmsTransactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
    <property name="connectionFactory" ref="cachedConnectionFactory" />
</bean>

<bean id="consumer" class="it.ubiquity.gestoreprofilazione.onweb.OnWebConsumer" scope="singleton">
    <property name="queue" ref="retryQueue" />
    <property name="jmsTemplate" ref="jmsTemplate" />
    <property name="transactionManager" ref="jmsTransactionManager" />
</bean>

我遇到的问题很奇怪:第一次收到消息,handleMessage失败,所以我回滚了事务。然后没有更多的事情发生。如果我检查 JMX 控制台,我可以看到队列中有一条消息。现在,如果我重新启动 JBoss,就会按预期一次又一次地收到消息。
也许我的配置有问题,但为什么它在重新启动后工作?
  • HornetQ 2.2.10
  • JBoss 5.1.0
  • Spring 3.1.2

  • 更新
    启用调试后,我第一次看到:

    DEBUG [org.springframework.jms.connection.JmsTransactionManager] (baseScheduler-1) Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT



    在第一次回滚之后,在随后的接收和回滚中,我看到:

    DEBUG [org.springframework.jms.connection.JmsTransactionManager] (baseScheduler-1) Participating in existing transaction



    相反,在重新启动 JBoss 后,我读到事务实际上已回滚:

    DEBUG [org.springframework.jms.connection.JmsTransactionManager] (baseScheduler-1) Initiating transaction rollback 2012-11-05 09:54:14,436 DEBUG [org.springframework.jms.connection.JmsTransactionManager] (baseScheduler-1) Rolling back JMS transaction on Session



    那么,为什么回滚不是第一次发生,而一旦我重新启动服务器,它就会一直发生?我究竟做错了什么?

    最佳答案

    好的,最后我设法理解了我的错误:)
    在外部 if's else 我应该有 promise 交易。这就是该机制在重新启动 JBoss 后起作用的原因:没有事务挂起。

    关于spring - 使用 Spring 管理 JMS 事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13162326/

    相关文章:

    Spring Batch 重试策略和跳过策略问题

    java - 使用 java sdk 为 amazon s3 对象设置对象到期日期

    java - Postgres 的搜索路径不适用于 Spring/DBCP 数据源

    html - JBoss(WildFly) 没有检测到 index.html 的 css 文件

    java - 集成 .net 和 java 应用程序的架构建议

    java - 使用 Spring JMS 时编译错误

    java - 如何通过 Maven 使用 Netbeans 调试 Spring Boot

    apache - 502 Bad Gateway...来自上游服务器的无效响应(apache 和 jboss)

    jboss - 为什么 'from'关键字会向后迭代?

    java - 您会使用发布/订阅或队列来进行长时间运行的后台进程吗?