title: Send RabbitMQ message on Spring Application shutdown
body: <p>I have a monitor service that sends a message to rabbitMQ on application startup, application shutdown and every minute (tick).</p>
  
  <p>The startup and tick events work fine.
  When the class was originally written the shutdown event also worked.</p>
  
  <p>I am using spring-boot-starter-amqp 1.3.3.RELEASE</p>
  
  <p>The event was fired on the <code>destroy</code> method of the <code>DisposableBean</code> interface.</p>
  
  <p>I have also tried implementing <code>ApplicationListener&lt;ContextClosedEvent&gt;</code> interface and <code>Lifecycle</code> interface</p>
  
  <p>Both the above methods return:</p>
  
  <blockquote>
    <p>java.lang.IllegalStateException: The ApplicationContext is closed and
    the ConnectionFactory can no longer create connections.</p>
  </blockquote>
  
  <p>I notice there was a bug fix <a href="https://jira.spring.io/browse/AMQP-536" rel="nofollow">https://jira.spring.io/browse/AMQP-536</a> wich suggests the <code>Lifecycle</code> interface.</p>
  
  <p>How do I ensure my shutdown event message is sent before the RabbitMQ connection is closed?</p>
  
  <p><strong>EDIT: More info and Latest Code</strong></p>
  
  <p>The application has multiple connection factories to different servers. The Monitor Service copnnects to the RabbitMQ server via <code>monitorRabbitTemplate</code>.</p>
  
  <p>The issue seems to be the  <code>monitorRabbitTemplate</code> connection Factory gets the Lifecycle/Shutdown/Dispose event before the <code>MonitorService</code>.</p>
  
  <p>Latest code (using <code>Lifecycle</code> instead of <code>ApplicationListener&lt;ContextClosedEvent&gt;</code>  and <code>DisposableBean</code>):</p>
  
  <pre><code>@Component
  public class MonitorServiceImpl implements  MonitorService , Lifecycle {
      private static final Logger LOGGER = LoggerFactory.getLogger(MonitorServiceImpl.class);
  
      private final RabbitTemplate monitorRabbitTemplate;
      private final String queueName;
      private final Gson gson = new Gson();
  
      @Autowired
      public MonitorServiceImpl(@Qualifier("monitorRabbitTemplate") final RabbitTemplate monitorRabbitTemplate,
                                @Value("${monitor.rabbitmq.queue.name:monitor}") final String queueName) {
          this.monitorRabbitTemplate = monitorRabbitTemplate;
          this.queueName = queueName;
      }
  
      @Scheduled(fixedDelay = 60000)
      public void tick() {
          try {
              send(new Monitor(Status.INFO, "I am here"));
          } catch (final Exception e) {
              LOGGER.error("FAILED TO SEND TICK EVENT", e);
          }
      }
  
      @Override
      public void send(final Monitor monitor) {
          try {
              final Message message = MessageBuilder.withBody(gson.toJson(monitor).getBytes())
                  .setContentType("application/json").setPriority(0).setDeliveryMode(MessageDeliveryMode.PERSISTENT)
                  .build();
  
              monitorRabbitTemplate.send(queueName, message);
          } catch (final Exception e) {
              LOGGER.error("FAILED TO SEND MONITOR EVENT", e);
              LOGGER.error("FAILED TO SEND MONITOR EVENT to {}:{}", monitorRabbitTemplate.getConnectionFactory()
                  .getHost(), monitorRabbitTemplate.getConnectionFactory().getPort());
  
          }
  
      }
  
      @Override
      public void start() {
          try {
              send(new Monitor(Status.STARTING, "Application starting up..."));
          } catch (final Exception e) {
              LOGGER.error("FAILED TO SEND STARTUP EVENT", e);
          }
      }
  
      @Override
      public void stop() {
          try {
              send(new Monitor(Status.TERMINATING, "Application shutdown..."));
          } catch (final Exception e) {
              LOGGER.error("FAILED TO SEND SHUTDOWN EVENT", e);
          }
  
      }
  
      @Override
      public boolean isRunning() {
          return true;
      }
  }
  </code></pre>