spring-amqp transaction semantics
<p>I am currently testing a rather simple example concerning messaging transactions in connection with database transactions with spring amqp.</p>

<p>The use case is as follows:</p>

<ul>
<li>message is received</li>
<li>a message is sent</li>
<li><p>database is updated</p>

<pre><code>@Transactional
public void handleMessage(EventPayload event) {
    MyEntity entity = new MyEntity();
    entity.setName(event.getName());

    rabbitTemplate.convertAndSend("myExchange", "payload.create", payload);

    MyEntity savedEntity = entityRepository.save(entity);
}
</code></pre></li>
</ul>

<p>The expected behavior in case of a failure during the database operation is that the received message is rolled back to the bus (DefaultRequeueRejected = false) and goes into a dead letter queue. Also the message sent should be rolled back.</p>

<p>I can achieve this with the following configuration:</p>

<pre><code>@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, MessageConverter messageConverter) {
    RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
    rabbitTemplate.setMessageConverter(messageConverter);
    rabbitTemplate.setChannelTransacted(true);
    return rabbitTemplate;
}

@Bean
    SimpleMessageListenerContainer subscriberListenerContainer(ConnectionFactory connectionFactory,
                                                              MessageListenerAdapter listenerAdapter,
                                                              PlatformTransactionManager transactionManager) {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.setQueueNames(SUBSCRIBER_QUEUE_NAME);
        container.setMessageListener(listenerAdapter);
        container.setChannelTransacted(true);
        container.setTransactionManager(transactionManager);
        container.setDefaultRequeueRejected(false);
        return container;
    }
</code></pre>

<p>So this works fine - what I do not understand is that the observed behavior is exactly the same if I do not set the transaction manager on the <code>SimpleMessageListenerContainer</code>. So if I configure the following the bebavior does not change:</p>

<pre><code>@Bean
        SimpleMessageListenerContainer subscriberListenerContainer(ConnectionFactory connectionFactory,
                                                                  MessageListenerAdapter listenerAdapter) {
            SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
            container.setConnectionFactory(connectionFactory);
            container.setQueueNames(SUBSCRIBER_QUEUE_NAME);
            container.setMessageListener(listenerAdapter);
            container.setDefaultRequeueRejected(false);
            return container;
        }
</code></pre>

<p>Can someone explain what is happening there? Why is the second case also working? What is different internally if the <code>PlatformTransactionManager</code> is registered on the <code>SimpleMessageListenerContainer</code>.</p>