2012-06-28 3 views
5

나는 Hibernate와 PostgreSQL을 사용하는 Spring 어플리케이션을 가지고있다. 또한 Spring AMQP (RabbitMQ)를 사용합니다.Spring AMQP/RabbitMQ와 Hibernate Transaction Mananger

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

나는 SimpleMessageListenerContainer 비동기 메시지 수신을 사용하고 있습니다로 구성 : 내가로 구성 하이버 네이트 트랜잭션 매니저를 사용하고

은 다음 그래서 기본적으로 내가 수신 것을 지정한

@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; 
} 

메시지가 트랜잭션이어야합니다. 메시지 수신기는 @Transactional로 주석 처리 된 메소드를 가질 수 있고 DB에서 CRUD 연산을 수행 할 수있는 서비스를 호출합니다.

내 질문에, HibernateTransactionManager를 사용하여 SimpleMessageListenerContainer 수준에서 트랜잭션을 관리하는 데 문제가 있습니까? RabbitMQ에서 메시지를 받기 위해 DB 트랜잭션 관리자를 사용하는 데 문제가 있습니까?

여기 XA가 필요하지 않습니다. 난 그냥 서비스에 의해 DB에 대한 작업이 실패하면 메시지가 RabbitMQ 중개인에게 반송되지 않도록하고 싶습니다.

답변

1

Spring 소스에 따르면 MessageListenerContainer의 transactionManager 속성의 주요 목적은 리스너 호출 전에 수신 된 메시지에서 트랜잭션을 시작하고 리스너가 예외를 반환하거나 throw 한 후에 트랜잭션을 커밋 또는 롤백하는 것입니다. 리스너 메소드가 호출되기 전에 트랜잭션이 이미 시작되므로 리스너 메소드 @Transactional을 만들 필요가 없습니다.

리스너에 오류가 발생하면 예외가 발생하고 DB 트랜잭션이 롤백되며 메시지 브로커에 ack가 전송되지 않습니다 (jms 트랜잭션 롤백). 그러나 XA가 없으면 중복 된 메시지가있을 수 있습니다. 예를 들어 DB 트랜잭션이 성공적으로 커밋 된 후 메시지 브로커에 대한 연결이 재설정되고 ack를 브로커에 보낼 수 없습니다. 재 연결 후 브로커는 중복 메시지를 전달할 수 있습니다. 이것을 인정하면 XA를 다룰 필요가 없습니다.