Spring boot command line application doesn't terminate with neo4j driver

525 views Asked by At

I've added Neo4j connectivity to a simple Spring Boot command line application — it implements CommandLineRunner.

I've almost followed the examples in Neo4j driver manual, but my application doesn't terminate after main() finishes.
The only deviation from those sources is that the driver.close() method is not invoked at main() end, but in a @PreDestroy annotated method:

@Service
public class DatabaseGraphService {
    
    private volatile Driver driver;
    
    private final Logger LOG;
    
    public DatabaseGraphService() {
        LOG = LogManager.getLogger(getClass());
    }

    @PostConstruct
    private void initialize() throws Exception {
        driver = GraphDatabase.driver("bolt://localhost:7687", AuthTokens.basic("neo4j", "neo4j"));
    }
    
    @PreDestroy
    public void close() throws Exception {
        LOG.info("Shutting down Neo4j driver...");
        driver.close();
    }
    
    // ...
    
}

Main class:

@SpringBootApplication(scanBasePackages={ "it" })
public class SpringBootConsoleApplication implements CommandLineRunner {

    @Autowired
    private DatabaseGraphService graphService;
    
    private static Logger LOG = LoggerFactory
      .getLogger(SpringBootConsoleApplication.class);

    public static void main(String[] args) {
        LOG.info("STARTING THE APPLICATION");
        
        SpringApplication.run(SpringBootConsoleApplication.class, args);
        LOG.info("APPLICATION FINISHED");
    }
 
    @Override
    public void run(String... args) {
        LOG.info("EXECUTING : command line runner");
    }
    
}

I run it from within Sprint Tools Suite (Eclipse-based IDE), this is what it logs:

i.c.c.e.SpringBootConsoleApplication     : APPLICATION FINISHED

but nothing else and the process stays active; when I hit the stop button, then:

inMXBeanRegistrar$SpringApplicationAdmin : Application shutdown requested.
i.c.c.services.DatabaseGraphService      : Shutting down Neo4j driver...
com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
[...]

If I run the program without executing any query, the process exists regularly. As long as I do a query - no matter if I consume all the results or do nothing with the Result object - it stays active.

Am I doing something wrong? Or maybe this is the expected behaviour, because when main() finishes it's just its thread that terminates?

Though, in the same application I'm connecting to a PostgreSQL instance, doing queries there too, but the application terminated correctly before adding the Neo4j connection.

1

There are 1 answers

2
injectives On

Neo4j Java Driver manages internal threads that are responsible for network communication. It bootstraps them on first API usage that involves networking.

Your application does not exit because those threads keep running. To shut them down, you have to call Driver's close method. 4.3.4 Javadoc snippet:

Close all the resources assigned to this driver, including open connections and IO threads.

In the described setup, it should be called on interrupt signal (CTRL+C) when running packaged JAR.

Starting from version 4.3.2, those threads have been updated to be daemon threads so that they do not prevent applications from finishing execution. In addition, this change has also been backported to versions 4.2.7 and 4.1.4.