2012-06-28 6 views
5

Ich habe eine Spring-Anwendung, die Hibernate und PostgreSQL verwendet. Es verwendet auch Spring AMQP (RabbitMQ).Spring AMQP/RabbitMQ und Hibernate Transaction Mananger

ich die Hibernate Transaktionsmanager wie folgt konfiguriert bin mit:

<bean id="transactionManager" 
    class="org.springframework.orm.hibernate3.HibernateTransactionManager" 
    p:sessionFactory-ref="sessionFactory" p:dataSource-ref="dataSource" /> 

Ich bin mit dem SimpleMessageListenerContainer für asynchronen Nachrichtenempfang konfiguriert als:

@Resource(name="transactionManager") 
private PlatformTransactionManager txManager; 

@Autowired 
private MyListener messageListener; 

@Bean 
public SimpleMessageListenerContainer mySMLC() 
{ 
    final SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(); 
    container.setConnectionFactory(rabbitConnectionFactory); 
    container.setQueueNames("myQueue"); 

    final MessageListenerAdapter adapter = new MessageListenerAdapter(messageListener); 
    adapter.setMessageConverter(converter); 
    container.setMessageListener(adapter); 
    container.setChannelTransacted(true); 
    container.setTransactionManager(txManager); 
    return container; 
} 

Also im Grunde habe ich, dass der Empfang angegeben von Nachrichten muss transaktional sein. Der Nachrichten-Listener ruft einen Service auf, bei dem Methoden mit @Transactional versehen und möglicherweise CRUD-Operationen in der Datenbank ausgeführt werden können.

Meine Frage ist, gibt es ein Problem mit dem HibernateTransactionManager, um die Transaktion auf der Ebene SimpleMessageListenerContainer zu verwalten? Wird es Probleme geben, einen DB-Transaktionsmanager zu verwenden, um den Empfang von Nachrichten von RabbitMQ zu verpacken?

Ich erwarte XA hier nicht. Ich möchte nur sicherstellen, dass, wenn irgendwelche Operationen in der DB durch den Dienst fehlschlagen, die Nachricht nicht an den RabbitMQ-Broker weitergeleitet wird.

Antwort

1

Gemäß den Spring-Quellen besteht der Hauptzweck der TransactionManager-Eigenschaft von MessageListenerContainer darin, die Transaktion für die vor dem Listener-Aufruf empfangene Nachricht zu starten und die Transaktion zu committen oder zurückzusetzen, nachdem der Listener eine Ausnahme zurückgegeben oder ausgelöst hat. Es müssen also keine Listener-Methoden @Transactional erstellt werden, da die Transaktion bereits gestartet wird, bevor die Listener-Methode aufgerufen wird.

Bei einem Fehler im Listener wird eine Exception ausgelöst, die DB-Transaktion wird zurückgesetzt, und es wird keine Bestätigung an den Nachrichtenbroker gesendet (JMS-Transaktions-Rollback). Aber ohne XA kann es doppelte Nachrichten geben. Zum Beispiel, nachdem die DB-Transaktion erfolgreich festgeschrieben wurde, konnte die Verbindung zum Zurücksetzen des Nachrichtenbrokers nicht hergestellt werden, und ack konnte nicht zum Broker gesendet werden. Nach der Wiederverbindung konnte der Broker eine doppelte Nachricht senden. Wenn Sie das zugeben, brauchen Sie sich nicht mit XA zu befassen.