Этот вопрос задавался несколько раз, но я не нашел пост, который точно описывает мою ситуацию. У меня есть приложение, основанное на загрузке JavaFX / Spring, которое требуется для выполнения некоторых задач очистки перед завершением работы. Я могу перехватить событие для нажатия кнопки X следующим образом:
primaryStage.setOnCloseRequest(event ->
{
shutdown(event);
});
private void shutdown(WindowEvent event)
{
if (event != null)
{
event.consume();
}
try
{
shutdownProcessHub();
Platform.exit();
}
catch (Exception ex)
{
logEntryService.logError(LogEntrySource.SERVICE, LogEntryType.CORE, "Error stopping process hub : "
+ ex.getMessage(), logger);
}
}
У меня есть кнопка выключения, которая вызывает тот же метод, но с нулевым аргументом. Оба эти метода закрытия моего приложения приводят к тому, что вызывается метод shutdownProcessHub (), который изящно останавливает группу потоков и выполняет запись в базу данных.
Проблема в том, что это приложение также может быть запущено без графического интерфейса. В этом режиме развертывания я использую NSSM для создания службы Windows, которая указывает на пакетный файл, который запускает приложение. Остановка указанной службы приводит к вызову приложения CTRL-C, который полностью игнорирует мой метод завершения работы. Я использовал следующий код для регистрации перехвата отключения:
Runtime.getRuntime().addShutdownHook(new Thread(() -> shutdown(null)));
Указанный хук отключения явно запускается после того, как любая форма Spring bean-компонента была долго уничтожена, так как я получаю следующее исключение при отправке CTRL-C в окно CMD с JAR-файлом:
Exception in thread "Thread-5" org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException: EntityManagerFactory is closed
Что мне нужно сделать, чтобы хук отключения мог по-прежнему иметь доступ к диспетчеру сущностей? Я понимаю, что это может быть слишком поздно для срока службы Spring / JVM для того, чтобы любой из них был по-прежнему доступен, какова альтернатива правильному перехвату вызова CTRL-C?