I have a monitor service that sends a message to rabbitMQ on application startup, application shutdown and every minute (tick).
The startup and tick events work fine. When the class was originally written the shutdown event also worked.
I am using spring-boot-starter-amqp 1.3.3.RELEASE
The event was fired on the destroy method of the DisposableBean interface.
I have also tried implementing ApplicationListener<ContextClosedEvent> interface and Lifecycle interface
Both the above methods return:
java.lang.IllegalStateException: The ApplicationContext is closed and the ConnectionFactory can no longer create connections.
I notice there was a bug fix https://jira.spring.io/browse/AMQP-536 wich suggests the Lifecycle interface.
How do I ensure my shutdown event message is sent before the RabbitMQ connection is closed?
EDIT: More info and Latest Code
The application has multiple connection factories to different servers. The Monitor Service copnnects to the RabbitMQ server via monitorRabbitTemplate.
The issue seems to be the monitorRabbitTemplate connection Factory gets the Lifecycle/Shutdown/Dispose event before the MonitorService.
Latest code (using Lifecycle instead of ApplicationListener<ContextClosedEvent> and DisposableBean):
@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;
}
}