【发布时间】:2019-06-02 15:13:22
【问题描述】:
这个问题已经被问过好几次了,但我还没有找到能准确描述我的情况的帖子。我有一个基于 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() 方法,该方法会优雅地停止一堆线程并执行对数据库的写入。
问题是这个应用程序也可以在没有 GUI 的情况下运行。在这种部署模式下,我使用 NSSM 创建一个指向启动应用程序的批处理文件的 Windows 服务。停止所述服务会导致对应用程序的 CTRL-C 调用完全绕过我的关闭方法。我使用以下代码注册了一个关闭挂钩:
Runtime.getRuntime().addShutdownHook(new Thread(() -> shutdown(null)));
在任何形式的 Spring bean 被长期销毁后,所述关闭挂钩显然会运行,因为我在将 CTRL-C 发送到运行 JAR 的 CMD 窗口时遇到以下异常:
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 调用的替代方法是什么?
【问题讨论】:
-
您想通过 javafx 中的某个关闭按钮终止 Spring Boot 应用程序吗?
-
该位现在工作正常。我需要处理的是当应用程序在没有来自 Windows 服务的 GUI 的情况下启动时,因此除了停止向应用程序发送 CTRL-C 命令的 NSSM 服务之外,不可能与程序进行实际的用户交互。当前使用我的关闭挂钩尝试执行此操作会导致 IllegalStateException 告诉我实体管理器已关闭。我需要在应用程序/服务关闭之前进行这些数据库写入,因为它们是我应用程序中不同模块的状态指示器。
-
我没听明白,如果您通过一些步骤修改您的问题,为您提供帮助会更容易。
-
您希望我添加哪些步骤?除了shutdownProcessHub()方法之外,我已经描述了几乎所有步骤,该方法既庞大又无关紧要,因为我只是在寻找一种在停止使用CTRL-C运行的命令提示符时调用它的方法同时仍然加载了所有 Spring 资源。
-
如果您添加 Step-1 之类的步骤,运行 spring boot 服务器,step-2 执行一些操作来提供您的确切要求的详细信息,人们会发现它很有用,并且可能会帮助您解决问题。
标签: java spring-boot javafx entitymanager shutdown-hook