0

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?

Martin
  • 1,977
  • 5
  • 30
  • 67
  • Do you want to terminate spring boot application through some shutdown button from javafx ? – Sambit Jun 02 '19 at 15:25
  • That bit is working properly now. What i need to handle is when the application is launched with no GUI from a windows service and therefore no actual user interaction with the program is possible aside from stopping the NSSM service which sends a CTRL-C command to the app. Doing this currently with my shutdown hook attempts results in the IllegalStateException telling me the entity manager is closed. I need these database writes to happen prior to the app/service shutting down as they are status indicators for the different modules in my app. – Martin Jun 02 '19 at 15:27
  • I am not getting it, if you modify your question with some steps, it will be easier to provide you help. – Sambit Jun 02 '19 at 15:33
  • What steps do you want me to add? I've described pretty much every step there is to this aside from the shutdownProcessHub() method which is both huge and irrelevant because i'm just looking for a way to have it called when stopping the command prompt it's running in with CTRL-C while still having all the Spring resources loaded. – Martin Jun 02 '19 at 15:59
  • if you add steps like Step-1, run spring boot server, step-2 do something to provide the details of your exact requirement, people will find it useful and may help you to solve your problem. – Sambit Jun 02 '19 at 16:54

1 Answers1

0

looks like the SmartLifeCycle interface's stop() method is what i needed. It is called when doing CTRL-C in the command prompt running the JAR and still has access to all of Spring's resources including JPA's entity manager. The only issue is that Log4J2 seems to not be available while this method executes but that is only a minor annoyance.

Cheers

Martin
  • 1,977
  • 5
  • 30
  • 67