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.
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:
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.