4

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 コンソールで確認すると、キューに 1 つのメッセージがあることがわかります。ここで JBoss を再起動すると、予想どおり、メッセージが何度も受信されます。
構成に問題があるのか​​もしれませんが、再起動後に機能するのはなぜですか?

  • HornetQ 2.2.10
  • JBoss 5.1.0
  • 春 3.1.2

更新
デバッグを有効にすると、初めて表示されます:

DEBUG [org.springframework.jms.connection.JmsTransactionManager] (baseScheduler-1) [null] という名前の新しいトランザクションを作成: PROPAGATION_REQUIRED,ISOLATION_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 DEBUG [org.springframework.jms.connection.JmsTransactionManager] (baseScheduler-1) JMS のロールバックセッションでのトランザクション

では、なぜロールバックが初めて発生せず、サーバーを再起動するとすぐにロールバックが常に発生するのでしょうか? 私は何を間違っていますか?

4

1 に答える 1

4

わかりました、ついに私は自分の間違いを理解することができました:)外側のifのelseでは、トランザクションをコミットする必要がありました。これが、JBoss の再起動後にメカニズムが機能する理由です。保留中のトランザクションはありません。

于 2012-11-05T10:12:47.457 に答える