使用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):
    }
}

我正在从队列中进行同步阅读,因为我不想阻止读取。因此,我必须检查是否实际收到了什么。

这是我的 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,这些消息会像预期的那样一次又一次接收。
也许我的配置有问题,但是为什么在重新启动后起作用?

  • 黄蜂2.2.10
  • JBOSS 5.1.0
  • 春季3.1.2

更新
通过启用调试,我第一次看到:

debug [org.springframework.jms.connection.jmstransactionmanager] (baseScheduler-1)用名称[null]创建新事务: propagation_required,siration_default

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

debug [org.springframework.jms.connection.jmstransactionmanager] (basescheduler-1)参与现有交易

相反,重新启动JBOSS后,我读到交易实际上是回滚的:

debug [org.springframework.jms.connection.jmstransactionmanager] (BaseScheduler-1)启动交易回滚2012-11-05 09:54:14,436调试 [org.springframework.jms.connection.jmstransactionmanager] (basescheduler-1)在会话上回滚JMS

所以,为什么回滚不会第一次发生,而我一旦重新启动服务器,它就会一直发生?我在做什么错?

好吧,最后我设法理解了我的错误:)在外部if中,我应该有命令交易。这就是为什么该机制在重新启动JBOSS之后工作的原因:

没有交易。

最新更新