title: spring-amqp transaction semantics
body: <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>