I have a monitoring service that sends a rabbitMQ message when the application starts, the application terminates, and every minute (tick).
Start 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 using an destroyinterface method DisposableBean.
I also tried to implement the interface ApplicationListener<ContextClosedEvent>and Lifecycleinterface
Both of the above methods return:
java.lang.IllegalStateException: ApplicationContext is closed and ConnectionFactory can no longer create connections.
I noticed that the bug https://jira.spring.io/browse/AMQP-536 , which offers an interface , has been fixed Lifecycle.
How do I ensure that my disconnect event message is sent before the RabbitMQ connection is closed?
EDIT: More Information and Latest Code
The application has several factories connecting to various servers. The monitoring service connects to the RabbitMQ server through monitorRabbitTemplate.
The problem is that the monitorRabbitTemplateFactory connection receives the Lifecycle / Shutdown / Dispose event before MonitorService.
Last code (using Lifecycleinstead 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;
}
}