This question has been asked a few times but I have not found a post that describes my situation exactly. I have a JavaFX/Spring boot based application that is required to perform some cleanup tasks before shutting down. I can intercept the event for the X button being pressed like so :
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);
}
}
I have a shutdown button which calls the same method but with a null argument. Both these methods of shutting down my application result in the shutdownProcessHub() method being called which gracefully stops a bunch of threads and performs writes to the database.
The issue is that this application can also be run with no GUI. In this deployment mode, i use NSSM to create a windows service that points to a batch file which starts the app. Stopping said service results in a CTRL-C call to the app which completely bypasses my shutdown method. I have used the following code to register a shutdown hook :
Runtime.getRuntime().addShutdownHook(new Thread(() -> shutdown(null)));
Said shutdown hook clearly runs after any form of Spring bean has been long destroyed since i'm getting the following exception when sending CTRL-C to the CMD window running the 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
What do i need to do in order to have the shutdown hook still be able to access the entity manager? I understand this might be too late in the Spring / JVM lifespan for any of these to still be accessible, what would be the alternative for a CTRL-C call to be correctly intercepted?